因为学习到相关知识,所以在此做了一个知识点的总结。
不过在学习之前我们来先了解下MVVM框架,
MVVM框架:
M–model层 ,它可以对 数据进行增删改查
V–view层,也就是我们所说的视图层,它与HTML一样的模板类似----用户界面(UI)
VM–viewModel,它相当于我们model与view中间的一面镜子也就是我们所说的model和view的一个映射层,它是一个转值器,负责转换Model中的数据对象,来让对象变得更容易管理和使用。
Vue.js深入响应式原理
在我们学习Vue.js中,其最独特的特性是 非侵入性的响应式系统——即数据模型仅仅是普通的 JavaScript 对象,当你修改它们时,视图会进行更新。这使得状态管理非常简单直接,不过理解其工作原理同样重要,这样一来可以避开一些常见的问题。现在我们将总结下 Vue 响应式系统的底层的细节
如何追踪变化
当我们把一个普通JavaScript对象传入Vue实例中作为一个data选项时,Vue会遍历此对象的所有属性,并通过object.definePropery方法将这些属性全部转换为getter/setter。注:object.definePropery()是 ES5 中一个不能打补丁实现的特性,所以 Vue 不支持 IE8 以及更低版本浏览器。
但对用户来说,getter/setter是不可见的,但是在内部它们让Vue能够追踪依赖,在属性被访问和修改时通知变更,这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
模板中每个指令/数据绑定都有一个对应的 watcher 对象,在计算过程中它把属性记录为依赖。之后当依赖的 setter 被调用时,会触发 watcher 重新计算 ,也就会导致它的关联指令更新 DOM。详图如下:
检测变化的相关注意事项
受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在data 对象上才能让 Vue.js 转换它,才能让它是响应的。例如:
new Vue({
data:{
a:1
}
})
// vm.a 是响应式的
vm.b = 2
// vm.b 是非响应式的
但是对于Vue实例来说,我们可以使用Vue.set(object, propertyName, value)方法来添加属性并让其属性是响应式的。例如:
Vue.set(vm.someObject, 'b', 2)
// `vm.b` 和 `data.b` 现在是响应的
对于普通的数据对象,我们还可以使用全局方法vm.$set。如下:
this.$set(this.someObject,'b',2)
// `vm.b` 和 `data.b` 现在是响应的
有时候我们还会使用Object.assign()或_.extend()方法为已有对象添加新的多个属性,但是这样添加到对象上的新的属性是不会触发更新的,这个时候我们可以创建一个新的对象,这个新创建的对象将原有的对象属性和要混入的对象的属性包含在内:
// 代替 Object.assign(this.someObject, { a: 1, b: 2 })
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
还有一些注意事项在列表渲染中有提到,可参考vue.js官网:https://cn.vuejs.org/v2/guide/list.html#注意事项
声明响应式属性
由于 Vue 不允许动态添加根级响应式属性,所以必须在初始化实例前声明所有根级响应式属性,哪怕只是一个空值:
var vm = new Vue({
data: {
// 声明 message 为一个空值字符串
message: ''
},
template: '<div>{{ message }}</div>'
})
// 之后设置 message
vm.message = 'Hello!'
注:如果你未在 data 选项中声明 message,Vue 将警告你渲染函数正在试图访问不存在的属性。
这么做有两个原因:
- data 对象就像组件状态的模式(schema)。在它上面声明所有的属性让组件代码更易于理解。
- 添加一个顶级响应属性会强制所有的 watcher 重新计算,因为它之前不存在,没有 watcher 追踪它。这么做性能通常是可以接受的(特别是对比 Angular 的脏检查),但是可以在初始化时避免。