Vue学习笔记二:浅析数据响应式

1.数据响应式是什么?

数据响应式是指视图页面根据数据的变化做出相应的变化。
举一个简单的例子:

对于模板:

<div id="app">{{ name }}</div>

创建一个Vue实例:

var vm = new Vue({
    el:'#app',
    data:{
        name:'Pray'
    }
})

执行以上代码后,页面显示 Pray。

vm.name = 'Frank'

执行代码以上后,页面更新为 Frank,并不需要去手动修改 DOM 更新数据。

2.原理浅析

我们先来理一下逻辑,Vue的数据响应式的逻辑其实很简单:

数据变动 -> Vue捕获到数据变动 -> 重新渲染

所以问题的关键就在于Vue是怎么样捕获到数据的变动的呢?

答案是通过设置访问器属性getter与setter。
关于getter/setter的作用可以看看这篇文章getter/setter的作用.

简单点来说就是:

  • getter 是读取对象属性时调用的函数。
  • setter 是写入对象属性时调用的函数。
    所以Vue捕获数据变动就以通过setter函数——当数据变化(被写入值)时,JS会调用的set()函数,我们只需要在set()函数中写入渲染函数render()实现即可:
Object.defineProperty(vm,"name",{
    get(){
        return this.name;
    },
    set(newValue){      //vm.name = 'Frank' 时执行 set 函数
        vm.name = newValue;
        render();       //重新渲染
    }
})

注:以上实现仅为简略的介绍Vue数据响应式的原理,实际实现远比其复杂

3.数据响应式的注意事项

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化

对于对象

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。

var vm = new Vue({
  data:{
    a:1
  }
})

// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

解决方法:

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。

Vue.set(vm.someObject, 'b', 2)
this.$set(this.someObject,'b',2)    //this.$set 是 Vue.set 另一种写法
对于数组

Vue 不能检测以下数组的变动:

  • 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  • 当你修改数组的长度时,例如:vm.items.length = newLength
var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

解决方法:

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:

Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)

为了解决第二类问题,你可以使用 splice:

vm.items.splice(newLength)

如果是添加或删除数组头或尾,Vue提供的push,pop,shift,unshift方法都是可以给新数据添加响应式的。

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容