首页IT科技vue2 vue3响应式原理(Vue2响应式原理)

vue2 vue3响应式原理(Vue2响应式原理)

时间2025-06-21 00:26:22分类IT科技浏览5066
导读:?vue2响应式原理 vue的特性:...

?vue2响应式原理

vue的特性:数据驱动视图双向数据绑定            。vue官方文档也提供了响应式原理的解释:

深入响应式原理

Object.defineProperty()

Object.defineProperty()的作用是直接在一个对象上定义一个新属性            ,或者修改一个属性

使用方式:Object.defineProperty(对象名,属性名,配置项)

<script> let person = { name: 张三, sex: , } Object.defineProperty(person,age,{ value: 18 }) //不能参与遍历 </script>

上述写法是给person对象添加一个age属性                  ,属性的值是18

但是这种写法:

不能进行枚举      ,即无法在遍历的时候获取到age属性的值 不能被修改 不能删除

所以Object.defineProperty()还有其他配置项

Object.defineProperty(person,age,{ value: 18 enumerable: true //控制属性是否可以枚举            ,get="_blank">默认值是false writeable: true //控制属性是否可以被修改                  ,默认值是false configurable: true //控制属性是否可以被删除      ,默认值是false })

现在有一个需求:定义一个新的变量number      ,当number的值修改后                  ,person中age的值也相应被修改;而person中age的值被修改后            ,number的值也相应被修改                  。

这个时候需要借助新的配置项get和set

<script> let number = 18 let person = { name: 张三, sex: , } //能够实现number的值修改后      ,person中age的值也相应被修改 Object.defineProperty(person,age,{ //当有人读取person的age属性时                  ,get函数(getter)就会被调用            ,且返回值就是age的值 get:function(){ return number }, //当有人修改person的age属性时,set函数(setter)就会被调用                  ,且接收到修改的具体值 set(value){ number = value } }) </script>

数据代理

数据代理就是通过一个对象代理另一个对象中属性的操作

vue就是通过vm对象来代理data对象中属性的操作

<body> <div id="app"> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> </div> </body> <script> const vm = new Vue({ el: #app, data: { name: 张三, age: 18 } }) </script>

控制台输出vm,我们可以看到name和age这两个属性

这两个属性都是通过Object.defineProperty()添加到vm上,所以可以发现他们都有对应的getter/setter

也就是说:当读取vm中的name时                  ,会调用getter,把data.name给name;当修改vm中的name时            ,会调用setter                  ,修改data.name中的值(这里跟第一个例子是同一个道理)

但是我们会发现vm上没有data(疑惑:明明在创建vue实例对象的时候      ,设置了data            ,为什么取不到)

其实我们以为的这个data其实是_data                  ,可以验证一下:

let data = { name: 张三, age: 18 } const vm = new Vue({ el: #app, data })

控制台进行一下判断:

所以我们获取数据的时候      ,也可以通过vm._data.age来获取

vue为了编码更方便      ,进行了数据代理                  ,遍历data中的所有属性            ,把每个属性都添加到vm中      ,指定getter/setter      。

所以可以直接通过vm.age来获取数据

基本原理:

通过Object.defineProperty()把data对象中所有属性添加到vm上 为每一个添加vm上的属性                  ,都指定一个getter/setter 在getter/setter内部去操作(读/写)data中对应的属性

实现双向绑定

双向绑定就是数据发生变化时            ,视图也跟着变      。核心是数据劫持发布者-订阅者模式

数据劫持实质就是使用defineProperty重写getter/setter                  。当数据改变时,set就会劫持这个数据的变化                  ,更新视图(view)

但是由于defineProperty无法检测到对象和数组内部的变化                  ,所以遇到属性为对象时,会递归观察该属性;遇到数组时            ,会重写push            、pop                  、shift等方法            。

监测对象中的数据

开始会想认为利用getter/setter                  ,但是这样会造成死循环      。只要有人获取name的值      ,就会调用get            ,然后又会获取一次person.name                  ,造成死循环                  。set同理            。

//错误的代码!!!!!!!!! let person = { name: 张三, } Object.defineProperty(person, name, { get: function() { return person.name }, set(value) { person.age = name } })

正确的做法是:监听数据的每一个属性      ,当监听到属性值发生变化时      ,通知订阅者去更新视图                  ,重新进行模板解析。

<script> let data = { name: 张三, } //创建一个观察者实例对象            ,用于监视data中属性的变化 const obs = new Observer(data) //准备一个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) { obj[k] = val } }) }) } </script>

上述代码只是一个例子      ,只会对一层对象进行处理                  ,vue的操作是递归            ,直到数据类型是简单数据类型                  。

如需给后添加的属性做响应式,可以使用

Vue.set(object,propertyName,value)或 vm.$set(object,propertyName,value) data: { student:{ name: 张三, age: 18, friends:[ {name:小明,age:20}, {name:李四,age:15} ] } } Vue.set(this.student, sex, ) this.$set(this.student, sex, )

监测数组中的数据

这里可以去看一下vue的官方文档:

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

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

(2)重新解析模板                  ,进而更新页面

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

使用API:push(),pop(),shift(),splice(),sort(),reverse()等 Vue.set(),vm.$set()

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
宽带如何提升(如何给宽带加速呢?)