Vue2地级内功心法之---监视数据的原理

124 阅读1分钟

vue会监视data中【所有层次】的数据

如何监测-对象-中的数据?

通过setter实现监视,且要在new Vue时就传入要监测的数据。

在vm中每个对象及对象属性都有get和set方法,当触发set方法时都会引发页面更新。

(1).对象中后追加的属性,Vue默认不做响应式处理

(2).如需给后添加的属性做响应式,请使用如下API:

//方法1
Vue.set(target,propertyName/index,value)
//方法2
vm.$set(target,propertyName/index,value)

如何监测-数组-中的数据?

通过包裹数组更新元素的方法实现,本质就是做了两件事:

  1. 调用原生对应的方法对数组进行更新。

  2. 重新解析模板,进而更新页面。

数组更新检测

变更方法

变更方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse() Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。

非变更方法

非变更方法包括:

  • filter()
  • concat() 
  • slice() 非变更方法不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组,以实现视图更新。

vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

在Vue修改数组中的某个元素一定要用如下方法:

数组中的元素没有get和set方法,所以需要依赖数组方法进行页面更新,如果直接给数组元素指定值,虽然值更改了,但页面没有更新,如下方法解决此类问题:

  1. 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

  2. Vue.set() 或 vm.$set()

简单模拟数据检测

let data = {
        name:'歪比巴布',
        address:'啊!!!!',
}

//创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data)		
console.log(obs)	

//准备一个vm实例对象
let vm = {}
vm._data = data = obs

function Observer(obj){
        //汇总对象中所有的属性形成一个数组
        const keys = Object.keys(obj)
        //遍历
        keys.forEach((k)=>{
                Object.defineProperty(this,k,{
                        get(){
                                return obj[k]
                        },
                        set(val){
                                console.log(`${k}被修改->解析模板->生成虚拟DOM.....渲染页面`)
                                obj[k] = val
                        }
                })
        })
}

特别注意

Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(vm._data) 添加属性!!!