Vue相关内容
概述 :
Vue是前端的一个Js库 ( 诞生于2015年 , 兴起于2016年 , 尤雨溪写的(目前是阿里巴巴在维护) ) , vue是MVVM模式的框架 .
MVVM概述 :
-
model 数据
-
view 视图
-
viewmodel 视图模型 ( 管理 , 数据驱动视图 )
Vue的双向数据绑定
-
视图变化 --- 数据也会变化
-
数据变化 --- 视图也会变化
双向数据绑定 运用在表单标签 ( input )
代码实现 ( v-model指令 )
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./lib/vue.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>
原生Js实现vue2的双向数据绑定
流程 :
-
获取所有的input框
-
过滤出有v-model属性的input框并返回
-
遍历所有加了v-model属性的input框
-
找这个v-model属性的值 , 设置给data里面的msg
-
给input添加监听 , 监听input的value变化 设置给data
-
使用Object.defineProperty的set来监听数据的变化
-
在数据变化的时候 , 重新渲染input的值
-
渲染应该解析对应的{{}} , 找到对应的属性名进行替换
代码实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div class="box"> <input type="text" v-model="msg"> {{msg}} </div> <script> class Vue { constructor(option) { //获取需要渲染的元素 this.el = document.querySelector(option.el) //获取要渲染的数据 this.data = option.data //拷贝一个渲染的数据,以便后续defineProerty的使用 this.model = Object.assign({}, option.data) //拿到页面上的显示的内容,后面需要做替换 this.template = this.el.innerHTML this.render() this._obServer() } //观察数据的变化 _obServer() { let self = this //遍历所有数据的属性 for (let key in this.data) { // 定义属性的get和set方法(需定义的对象,需定义对象的属性,处理方法) Object.defineProperty(this.data, key, { //获取就直接返回数据的属性 get() { return self.model[key] }, //把数据的属性赋给传进来的对象 set(v) { self.model[key] = v // 渲染 self.render() } }) } } // 渲染的方法 render() { let self = this // 获得页面上的数据并进行替换({{msg}}换成msg),然后再渲染到页面上 this.el.innerHTML = this.template.replace(/\{\{\w+\}\}/g,(str)=> { let property = str.substring(2, str.length - 2).trim() return self.data[property] }) // 获取页面上的input框,再过滤除带有v-model属性的input,并把它们返回出去 Array.from(this.el.querySelectorAll('input')).filter((item) => { return item.getAttribute('v-model') }).forEach((item) => { let self = this //遍历带有v-model属性的input框,再给他们设置oninput事件 let attributeName = item.getAttribute('v-model') item.oninput = function () { //获取input的value并设置给data里面的属性msg self.data[attributeName] = this.value } //将input的value设置给data的属性msg item.value = this.data[attributeName] }) } } //调用vue方法 new Vue({ el: '.box', data: { msg: 'aloha' } }) </script> </body> </html>
深拷贝和浅拷贝
浅拷贝
概述 :
第一层拷贝它的值 , 第二层及之后拷贝的都是地址 , 相当于你拷贝的是一个快捷方式 , 这个快捷方式跟原本的不是一个 , 但里面的内容是一样的
-
Object.assign 实现浅拷贝
let obj = {name:'jack',list:[1,2,3],params:{'ok'}} let copyObj = Object.assign({},obj) console.log(obj == copyObj) //false console.log(obj.list==copyObj.list)//true
- Array.prototype.concat ( 数组的浅拷贝 )
//数组的浅拷贝 concat let arr = [1, 3, 5, 7, { username: 'alex' }] let copyArr = [].concat(arr) console.log(arr == copyArr) //false console.log(arr.username == copyArr.username) //true
- Array.prototype.slice ( 数组的浅拷贝 )
// 3.数组的浅拷贝 slice let copyArr1 = arr.slice() //截取全部 console.log(arr == copyArr1) //false console.log(arr.username == copyArr1.username) //true
- 扩展运算符
console.log('------扩展运算符--------'); let copyArr2 = [...arr] console.log(arr == copyArr2) //false console.log(arr.username == copyArr2.username) //true
- 自定义函数实现浅拷贝
console.log('------函数--------'); function copy(obj) { //先用一个变量接收obj的构造函数 let constructor = obj.constructor //再拷贝一下这个变量 let copyObj1 = new constructor() //变量传入的obj for (let key in obj) { //拷贝的obj1里的地址=传入的obj的地址 copyObj1[key] = obj[key] } //返回拷贝的obj1 return copyObj1 } let copyArr4 = copy(arr) console.log(arr == copyArr4) //false console.log(arr.username == copyArr4.username) //true let copyObj2 = copy(obj) console.log(obj == copyObj2) //false console.log(obj.family == copyObj2.family) //true
- _.clone () ( 第三方工具 ( lodash .js ) )
console.log('------lodash--------'); let copyArr3 = _.clone(arr) console.log(arr == copyArr3) //false console.log(arr.username == copyArr3.username) //true
深拷贝
概述 :
深拷贝是拷贝所有的内容 , 这两个内容相同的点只有值是一样的 , 引用地址都不一样
深拷贝的实现
-
序列化和反序列化 ( JSON.stringify , JSON.parse )
// 1.序列化和反序列化 let obj = { list: [{ name: '西瓜' }, { name: '椪柑' }, { name: '猕猴桃' }], price: 20, user: { userName: '张三' } } let copyObj = JSON.parse(JSON.stringify(obj)) console.log('-------序列化和反序列化---------') console.log(obj == copyObj) console.log(obj.list == copyObj.list) console.log(obj.price == copyObj.price) console.log(obj.user == copyObj.user)
- _.cloneDeep ( 使用第三方工具 lodash.js )
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script> <script> let copyObj2 = _.cloneDeep(obj) console.log('-------lodash---------') console.log(obj == copyObj2) console.log(obj.list == copyObj2.list) console.log(obj.price == copyObj2.price) console.log(obj.user == copyObj2.user) </script>
- 自定义函数实现深拷贝 ( 递归实现 )
function cloneDeep(obj) { //判断传入的obj是否为对象或者空,不是就返回值 if (!(typeof obj == 'object' && obj)) { return obj } // 判断传入的obj是对象还是数组 let copyObj1 = obj instanceof Array ? [] : {} // 遍历 for (let key in obj) { copyObj1[key] = cloneDeep(obj[key]) } return copyObj1 } let copyObj1 = cloneDeep(obj) console.log(copyObj1) console.log(obj == copyObj1) //false console.log(obj.list == copyObj1.list) //false console.log(obj.price == copyObj1.price) //true console.log(obj.user == copyObj1.user) //false
Vue原理介绍
虚拟dom
概述 : 虚拟dom顾名思义 就是虚拟的don对象 ( 对象 ) , 这个虚拟的dom对象跟实体的dom对象没有直接的关系 , 因为操作实体dom会造成大量的重绘和回流 ( 页面渲染次数增加 , 渲染速度变慢 ) . 为了解决这个问题 , vue就是先操作虚拟dom , 再通过虚拟dom渲染实体dom ( 只有一次 ) . 虚拟dom是存储在内存中的 , 它的形成是抽取了实体dom ( 模仿实体dom创建的对象 )
diff算法 ( 可用于性能优化 )
是用于比对的算法 , 它是比对虚拟dom内容的改变 , 然后通过这个改变来控制实体dom的内容变化
通过节点来进行对比的 ( 元素节点 , 属性节点 , 文本节点 )
节点比对流程
节点比对流程先比key ( 下标不能作为key ( 下标会变 ) ) , 然后比节点名 , 再比属性名 , 比对子节点
vue中有个patch的方法来帮助我们进行分类比较 , 比较完就进行渲染 ( 模板引擎mustache )
相关优化
生命周期优化 ( 预编译(挂载的时候) 、缓存(组件销毁的时候) 、回收资源 (组件销毁的时候))
打包优化 ( webpack / glup(核心 : 文件流))
标签:arr,Vue,console,log,day26,let,obj,拷贝 From: https://www.cnblogs.com/itlulu/p/16867585.html