(四)仿《Vue生态》系列___《代理双向绑定打包请求》任务二vue3.0使用Proxy来劫持数据,当然要好好学习和实践这方面的知识了。解释Reflect,将Object的一小部分操作改成Reflect形式。异步总不能用时序这回自己封装了一个简单的'axios'。当然,我需要一台服务器,用koa启动一个简单的服务。1.Proxyvue3.0选择这个属性,虽然也会提供兼容版本,但是基本算是告别了老版本的ie,Proxy会解决之前无法监听到数组修改的痛点,也算是我这一代前端的福音了。使用上会有很大的区别,defineProperty是监听一个对象,而Proxy是返回一个新的对象,这需要我完全重写Observer模块。话不多说,我先来演示一下基本功能。从下面的代码可以看出:Proxy可以代理数组。代理不会改变原始数据的类型,Array仍然是Array。修改length属性会触发set,浏览器认为length当然是一个属性,修改当然会触发set。push、pop等操作也会触发set,而且不止一次,可见这些方法的实现原理。让ary=[1,2,3,4];letproxy=newProxy(ary,{get(target,key){returntarget[key];},set(target,key,value){console.log('我被触发了');返回值;}});console.log(Array.isArray(proxy));//真正的proxy.length=1;//我被触发了我之前写的劫持模块需要完全修改cc_vue/src/Observer.js并更改$data指向我在这里选择做的事情,以保持主要功能纯粹。//数据劫持import{Dep}from'./Watch';lettoString=Object.prototype.toString;classObserver{constructor(vm,data){//由于Proxy的机制是返回一个代理对象,那么我们需要将实例上的$data改为指向vm.$data=this.观察者(数据);}}导出默认观察者;observer对象和数组两种循环方式,每次都递归解析里面的元素,最后整个对象完全由Proxy组成。observer(data){lettype=toString.call(data),$data=this.defineReactive(data);if(type==='[objectObject]'){for(letitemindata){data[item]=this.defineReactive(data[item]);}}elseif(type==='[objectArray]'){letlen=data.长度;for(leti;i{});http.post('http:xxx.com',{name:'lulu'}).then(data=>{});其实get和post方法不需要每次都初始化,我们直接写在外面处理参数直接调用open方法,有些参数只有进入open状态才能设置;添加'?'如果有参数,到链接;参数product在链接后面,我之前遇到过一个bug,在拼接参数的时候如果结尾是'&',有的手机会出现跳转错误,所以为了防止出现特殊情况,需要对结尾'&进行判断杀掉';functionget(path,data){让c_http=newC_http();让str='?';for(letiindata){str+=`${i}=${data[i]}&`;}if(str.charAt(str.length-1)==='&'){str=str.slice(0,-1);}path=str==='?'?路径:`${路径}${str}`;c_http.request.open('GET',路径);returnc_http.handleReadyStateChange();}post这个说起来容易,.data就是自带的request。functionpost(path,data){让c_http=newC_http();c_http.request.open('POST',路径);c_http.data=数据;返回c_http.handleReadyStateChange();}handleReadyStateChangehandleReadyStateChange(){//这个需要打开后写//设置数据类型this.request.setRequestHeader('content-type','application/json;charset=utf-8');//现在前端返回的都是Promise;returnnewPromise((resolve)=>{this.request.onreadystatechange=()=>{//0UNSENT代理已经创建,但是open()方法还没有被调用//1OPENEDopen()方法已经已被调用。//2HEADERS_RECEIVED已调用send()方法,headers和状态可用。//3LOADING下载;responseText属性已包含一些数据。//4DONE下载操作已完成Finish。if(this.request.readyState===4){//因为是独立开发,直接写200,具体项目会比较复杂if(this.request.status===200){//return响应变量中的所有值resolve(this.request.response);}}};//真正的发送事件。这个。发送();});}sendsend(){//数据必须经过JSON处理this.request.send(JSON.stringify(this.data));}很多人提到“拦截器”感觉很高级,但实际上真的没有简单的拦截器“拦截器”吗?//1:使用对象不要使用[]因为可以高效删除拦截器constinterceptorsList={};//2:每次发送数据前执行所有拦截器,不要忘记传入请求源。send(){for(letiininterceptorsList){interceptorsList[i](this);}this.request.send(JSON.stringify(this.data));}//3:增删拦截器的方法,没有什么直接约定期限的。functioninterceptors(cb,type){if(type==='remove'){deleteinterceptorsList[cb];}elseif(typeofcb==='function'){interceptorsList[cb]=cb;}}小函数设置超时时间和超时回调。请求取消类C_http{constructor(){letrequest=newXMLHttpRequest();请求超时=5000;要求uest.responseType='json';request.ontimeout=this.ontimeout;this.request=请求;}ontimeout(){thrownewError('超时,请检查');}abort(){这个请求。中止();}}简单的'axios'已经准备好了,普通的请求就可以了。4.服务器请求完成,当然要启动服务了,这个时候是不会连接数据库的,不然就跑题了。koa2不懂koa的同学跟着学也没问题。npminstallkoa-generator-gKoa2项目名cc_vue/use/server就是这个项目的服务相关存放的地方。cc_vue/use/server/bin/www的端口号可以随意更改。当时9999被占用,我设置9998;const优点='9998';varport=normalizePort(process.env.PORT||pros);cc_vue/use/server/routes/index.js这个页面是专门用来做路由相关的,koa很贴心,router.get是处理get请求的。由于著名的“洋葱圈”,每个函数都必须编写异步。想了解更多的可以去看koa教程,我只有用到的时候才去看看。当你在写代码的时候需要测试延迟的时候,不要总是使用定时器,而是自己启动服务。constrouter=require('koa-router')();router.get('/',async(ctx,next)=>{ctx.body={data:'我是数据'};});router.post('/',async(ctx,next)=>{ctx.body=ctx.request.body;});module.exports=路由器;现在可以开始运行试试了5.跨域?一个很传统的问题出现了“跨域”。这里干脆选择一个插件来解决,很粗鲁.cc_vue/use/server/app.jsnpminstall--savekoa2-corsvarcors=require('koa2-cors');app.use(cors());说到这里,总结一下jsonp跨域的几种方式,这个太传统了,做一个script标签发送request.cors就是服务器设置允许什么来源的请求,什么方法的请求等等,这样跨域.postMessage在两个页面之间传值,经常出现在一个页面负责登录,另一个页面获取用户的登录token.document.domain,同一个域可以互相取数据.window.name这个没用,不过挺好玩的,有a,b,c三个页面,a和b同源,c单源,a用iframe打开c页面,c把值设为在window.name上传输,监听加载成功事件,瞬间将iframe的地址改为b,此时b同源,window会被继承。特征;location.hash也很好玩,是一个很聪明的人想出来的,有a,b,c三个页面,a和b同源,c单源,a发送一个hash值给c(因为一个URL就这样,不会跨域),c解析hash,将结果用iframe传递给b,b使用window.parent.parent找到parent的parent,window.parent.parent.location。hash='xxxxx',控制父级;http-proxy就像是vue的代理请求。毕竟服务器之间是没有跨域的。配置nginx就够了,比前端好多了。Websocket并不是天生就跨域的。本次测试的dom结构
n:{{n.length}}
m:{{m}}
n+m:{{n.length+m}}
{{http}}
让vm=newC({el:'#app',data:{n:[1,2,3],m:2,http:'等待'}});http.get('http://localhost:9998/',{name:'lulu',age:'23'}).then(data=>{vm.http=data.data;vm.n.length=1vm.n.push('22')});具体效果请查看项目中的end。让自己对vue对框架和数据的操作有了更深入的了解,受益匪浅。下一集:指令分析。具体指令的处理方法。如果篇幅足够,我们可以谈谈事件和生命周期。大家可以交流,一起工作。共同学习,共同进步,早日实现自我价值!!github:github个人技术博客:链接说明更多文章,ui库编写文章列表:链接说明