Vue实例和方法
github地址:https://github.com/manlili/vue_learn里面的lesson03
一 实例
每个 Vue 实例都会代理其 data
对象里所有的属性,改变data,vue实例同时改变,当然改变vue实例,data也同时改变,即 vue实例<=>data
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue实例与方法</title> <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <div class="test"> {{a}} </div> <script type="text/javascript"> var data = { a: 1 } var myVue = new Vue({ el: ".test", data: data }) </script> </body> </html>
在console控制台操作是:(其中每种颜色框起来的代码都是一组改变)
二 实例数据如何被追踪变化
注意只有这些被代理的属性是响应的。如果在实例创建之后添加新的属性到实例上,它不会触发视图更新.那么就要讲下实例数据如何被追踪变化
把一个普通对象传给 Vue 实例作为它的 data
选项,Vue.js 将遍历它的属性,用Object.defineProperty 将它们转为 getter/setter,在内部它们让 Vue.js 追踪依赖,在属性被访问和修改时通知变化,
举个栗子:(我们访问接口时返回的数据通常是get和set)
那么来了解一下追踪原理:
上图描述的是:模板中每个指令/数据绑定都有一个对应的 watcher 对象,在计算过程中它把属性记录为依赖。之后当依赖的 setter 被调用时,会触发 watcher 重新计算 ,也就会导致它的关联指令更新 DOM。
那么我们如果在实例化后给数据添加一个属性,由于ES5的限制,Vue.js 不能检测到对象属性的添加或删除,实际上vue的做法是初始化实例时将属性转为 getter/setter,这时已经开始了监控数据变化,所以数据是响应的,但是后来添加进去的属性就没办法转化为getter/setter.
举个栗子,还是上面那段代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue实例与方法</title> <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <div class="test"> {{a}} </div> <script type="text/javascript"> var data = { a: 1 } var myVue = new Vue({ el: ".test", data: data }) </script> </body> </html>
在控制台新添加b和c两个新属性,如下:
但是vue的作者还是想办法实现了在实例创建之后添加属性并且让它是响应的,但是不推荐,先来看一下做法:
(1)方式一:对于 Vue 实例,可以使用 $set(key, value)
实例方法
(2)方式二:对于普通数据对象,可以使用全局方法 Vue.set(object, key, value)
既然vue的作者已经提供了实例化后添加新属性并让它成为实时相应的,那为什么还不推荐使用?
(1)data
对象就像组件状态的模式(schema)。在它上面声明所有的属性让组件代码更易于理解。
(2)添加一个顶级响应属性会强制所有的 watcher 重新计算,因为它之前不存在,没有 watcher 追踪它。这么做性能通常是可以接受的,但是可以在初始化时避免。