day26Vue相关内容及深拷贝和浅拷贝
Vue相关内容
概述:
vue是前端的一个js库,是一个MVVM模式的框架
MVVM概述
Vue相关内容
双向数据绑定:视图变化数据也会变化,数据变化视图也会变化
通过v-model指令代码实现
<script src="./myvue.js"></script> </head> <body> <div id="app"> <!-- 视图渲染的地方 --> <input type="text" v-model="msg"> <!-- 插值表达式 可以获取data里面的数据 --> {{msg}} </div> <script> //这个vue.js文件导出的是一个构造函数vue let vm=new Vue({ el:'#app',//需要将视图挂载的位置 data:{//放数据 msg:'你好' } }) console.log(vm); </script> </body> </html>
原生实现vue2的双向数据绑定
流程
获取所有的input框
过滤有属性v-model的input
遍历所有加了v-model属性的input
找v-model属性的属性值 对应data里面的数据值
给对应的input添加监听 监听input的value变化 设置给对应的data
使用Object.defineProperty的set来监听数据的变化
在数据变化的时候重新渲染对应的input的值
渲染应该解析对应{{}} 找到对应的属性名 进行替换
class Vue{ constructor(option){ this.el = document.querySelector(option.el) //找到对应渲染的元素 this.data = option.data //用于Object.defineProperty的使用 this.model = Object.assign({},option.data) //拿到传入的元素的里面显示的所有的内容 this.template = document.querySelector(option.el).innerHTML this.render() this. _obServer() } //观察者 观察data的数据变化 _obServer(){ let _this = this //遍历所有的属性 for(let key in this.data){ Object.defineProperty(this.data,key,{ get(){ return _this.model[key] }, set(v){ _this.model[key] = v //渲染 _this.render() } }) } } //渲染的方法 render(){ let _this = this //找到所有的{{}} 括起来的内容 进行替换 this.el.innerHTML = this.template.replace(/\{\{\w+\}\}/g,(str)=>{ //str {{msg}} let propertyName = str.substring(2,str.length-2).trim() //msg return _this.data[propertyName] }) //找到对应el里面的input框 Array.from(this.el.querySelectorAll('input')) .filter((input)=>{ //找到input中是否具备v-model属性 return input.getAttribute('v-model') }) .forEach((input)=>{ let _this = this //遍历所有的input框 (都是有v-model属性的) //获取对应的v-model的属性值 let propertyName = input.getAttribute('v-model').trim() //给这个input添加onchange事件或者是oninput input.oninput = function(){ //获取他的value 设置给对应的data里面的属性 _this.data[propertyName] = this.value } //将对应的input的value 进行设置(对应的data里面属性的数据) input.value = this.data[propertyName] }) } }
深拷贝和浅拷贝
浅拷贝 :只拷贝第一层的值 其他层拷贝的是地址
实现浅拷贝的方式:
Object.assign
Array.prototype.concat (数组)
Array.prototype.slice(数组)
. . . 扩展运算符
var obj = { name: 'haha', arr: [1, 2, 3, 4] } var copyObj = Object.assign({}, obj) console.log(copyObj == obj); console.log(copyObj.arr == obj.arr); console.log(copyObj.name == obj.name); copyObj.arr.push(5) console.log(obj.arr) //数组的浅拷贝arr var arr = [1, 2, 3] var copyArr1 = [].concat(arr)//连接 console.log(copyArr1 == arr); console.log(copyArr1[0] == arr[0]); let arr1 = [ { name: '11', age: '18' }, { name: '22', age: '25' } ] let copyArr2=arr1.slice()//截取 console.log(copyArr2==arr1); console.log(copyArr2[1]==arr1[1]); let copyArr3=[...arr1]//扩展运算符 console.log(copyArr3==arr1); console.log(copyArr3[1]==arr1[1]); console.log(copyArr3); //函数实现浅拷贝 function copy(obj) { let constructor=obj.constructor let copyObj=new constructor() for(let key in obj){ copyObj[key]=obj[key] } return copyObj } var copyArr4=copy(arr1) console.log(copyArr4==arr1); console.log(copyArr4[0]==arr1[0]); //第三方插件lodash.js (_.clone)
</script>
深拷贝:拷贝所有内容,值相同但是其他引用地址不一样,两者互不影响
序列化和反序列化 (JSON.stringify JSON.parse)
使用第三方工具 lodash.js (_.cloneDeep)
自定义函数实现深拷贝(递归实现)
//递归实现深拷贝 function deepClone(obj) { if (!(typeof obj == 'object' && obj)) { return obj } let copyObj = obj instanceof Array ? [] : {} for (let key in obj) { copyObj[key] = deepClone(obj[key]) } return copyObj }
Vue原理介绍
虚拟dom
虚拟的dom对象,存在内存中,虚拟dom的形成是抽取对应的实体dom,模仿实体don创建的对象,跟实体的dom对象没有直接关系,因为直接操作实体dom会造成大量的重绘和回流,导致页面渲染次数增加,渲染的速度变慢,所以为了解决这个问题,vue先操作对应的虚拟的dom,再通过虚拟dom渲染实体dom(只渲染一次)
diff算法
比对虚拟dom内容的改变,通过对应的节点进行比对(元素节点,属性节点,文本节点)
节点对比流程
节点对比流程先比key(下标不能作为key),比对对应的节点名、属性名、子节点,然后通过patch方法进行分类比较,然后进行渲染(模板引擎mustache)
相关优化
生命周期优化(预加载(挂载的时候)、缓存(组件销毁的时候)、回收资源(组件销毁的时候))
打包优化(webpack/glup(文件流))