vue监测数据改变的原理
-
vue监听数据的流程为:数据修改时vm.data = data.然后调用data里边的set方法。set方法重新进行DOM(页面)重新遍历。新的虚拟DOM和旧的虚拟DOM进行对比,数据才被修改。(下面写这么多,只有这句话最有用)
-
以下是模拟vue监视数据
-
<body></body> <script> let data = { name: '安斯卡', address: '十大科技' } /*当数据被修改时,Observer是构造函数故调用需要需要 vue创建一个监视的实例对象,用于监听data中的属性变化.Observer有观察者的意思.*/ const obs = new Observer(data) console.log(obs) //准备一个vm的实例对象 let vm = {} //将监听的data放入_data中 vm._data = data = obs //obj可以是data对象,但不会改变原来data的数据 function Observer(obj){ //汇总所有对象的属性形成一个数组 const keys = Object.keys(obj) //遍历,k为属性名 keys.forEach((k)=>{ //选取this,this指代的是Observer的对象,而不是data的对象。 Object.defineProperties(this,k,{ get(){ //obj[k]的意思是将obj对象属性名为k进行返回 return obj[k] }, set(val){ //将obj对象的属性名k进行修改 obj[k] = val //`${k}`为name console.log(`${k}被修改了,所以去解析模板,生成虚拟DOM`); } }) }) } </script>
-
vue可以进行多层监视对象,生成get和set方法。
-
//data的属性有多少层对象,vue就对应生成多少个set方法。用于监视数据修改。模拟案例无法实现 let data = { name: '安斯卡', address: { sex: { phone: '123' } } }
Vue_set()方法
-
不可以用vm直接添加信息。
-
当data中没有定义属性age,在不动用源码的情况下。在控制台使用如下
-
Vue.set(vm._data.age,'sex','男'),或者vm.$set(vm._data.age,'set','男')
-
上边的代码不够严谨,可以直接用vm访问data的属性。
-
Vue.set(vm.age,'sex','男'),或者vm.$set(vm.age,'set','男')
-
设置按下按钮后才在data中的对象添加(属性值、属性名)或对象,不能直接在vm和_data添加
-
<template> <div class="hello"> <!-- data中的对象未定义属性,按下按钮后才在data中的对象添加(属性值、属性名)或对象 --> <button @click="addshu">按下按钮添加属性</button> <p v-if="name.sex">性别:{{ name.sex }}</p> </div> </template> <script> export default { data () { return { name: { age: '12', username: '', arr: { minage: '55', maxage: '44' }, } } }, methods: { addshu () { // 这里的this是vm, this.$set(选取添加的对象, 添加属性名, 添加属性值) this.$set(this.name, 'sex', '男') } } } </script> <style scoped> </style>
-
在array2: ['开车', '放歌', '开香槟']中,Vue无法给索引值为0、1、2设置get和set的方法,但Vue可以给array2[0].name设置get和set的方法。
-
解决方案。如:this.$set(this.name.array2.push('拉拉'))。用下列的方法,Vue会调用数组的push,之后进行数据代理。改变DOM页面
1、给数组最后的位置添加一个元素用,push
2、给数组开头的位置添加一个元素用,unshift
3、删除数组最后一个元素用,pop
4、删除数组第一个元素用,shift
5、替换或修改数组中的某个元素用,splice
6、对数组从小到大排序用sort
7、反转数组用,reverse
-
过滤数组用,filter。但filter过滤后生成新的数组不归Vue所管理,也就是Vue不会进行数据代理
-
<template> <div class="hello"> <ul> <!-- 对包含在name对象下的array进行遍历,没有定义id。可以用index作为索引 --> <li v-for="(arrays,index) in name.array" :key="index"> {{ arrays.nameday }}--{{ arrays.ageday }}--{{ arrays.sexday }} </li> <!-- 遍历array2的数组 --> <li v-for="(arr2,index) in name.array2" :key="index">{{ arr2 }}</li> <!-- 给数组添加数据 --> <button @click="fixNum">给数组添加数据</button> <p>{{ name.array2 }}</p> </ul> </div> </template> <script> export default { data () { return { name: { array: [ {nameday: '晓东', ageday: '23', sexday: '男'}, {nameday: '小志', ageday: '53', sexday: '男'}, {nameday: '小明', ageday: '63', sexday: '男'} ], array2: ['开车', '放歌', '开香槟'] } } }, methods: { fixNum () { this.$set(this.name.array2.push('拉拉')) } // fixNum () { // array2.splice(选取要修改数组的索引, 修改的个数, 修改后的元素)) // this.$set(this.name.array2.splice(0, 1, '拉拉')) // }, } } </script> <style scoped> </style>