vue数据劫持 ajax,Vue视图更新原理 - 数据劫持,最小量更新和DIFF算法

什么是数据劫持

加入有一个js文件内容如下:

var obj = {

x: 100,

y: 200,

}

Object.defineProperties(obj, {

x: {

set(){

console.log("You gonna update x, the vision will be changed.")

}

}

})

复制代码

30b885b8f275eec3a2dbcc39642bb27e.png

当node运行这个js文件的时候不会有任何效果呈现。

437df6a693a1f8aacf42cbb4ad857ccf.png

但当在这个文件中加入一个变化的东西:

var obj = {

x: 100,

y: 200,

}

Object.defineProperties(obj,{

x: {

set(){

console.log("You gonna update x, the vision will be changed.")

}

}

})

obj.x ++

复制代码

7e80a689e88bf629488e60d603b12a9a.png

console.log()里的话就会被打印出来。

fae193b15ca3d615fd065dc8d481dc1d.png

基本原理是这个Object.defineProperties()函数能在数据更新的过程中捕获数据.

Object.defineProperties()这个函数是原生js。

最小量更新

写一个组件如下,实验一下Vue是否会在页面某个数据变化时在底层更新页面的其他数据。

cf9be6e0818fa69b4a0b0a81076ebefa.png

452df9cffd2887a023e872ad1c2aecdf.png

c5e8552975580820507492347061be92.png

c1f54c2adaa1ae7afcb50360791820d1.png

手动在后台将下面的数字改成“哈哈”后点击x+1的按钮改变上面的数字,后台的“哈哈”保持不变。

这就是Vue特有的最小量更新算法,也叫DIFF算法。

当改变某个量时,Vue会检索template中的三个东西:

① 单个双打括号中是否有这个量;

② 指令中是否有这个量;

③ methods, computed和watch中是否有这个量。

只要符合以上其中一条,这个量都会得到更新。

关于单个双括号中是否有这个量,由于上图都是单个量在单个双括号内所以不能很好的说明这一点。以下再写一个有联动量的双括号:

d1fc0701e8512a78d54bad2475fbf723.png

804e6abdfe04a59dacd678a977f3531c.png

e77ea288ead8541b5528474d0c0cd203.png

这时点任何一个按钮“哈哈”都会更新为x+y的和。

1e89157f517eac6d0173d19673464b3a.png

下面进一步解释这个最少量更新算法的结算机制:

1bac81b93a75af298f3fd3f13446d840.png

cfad026e28c92ee2c6a060d9763a2bd9.png

aeaf0ef397da0144122f68ca645ed55b.png

cb28305e12bc89e36460e72cff21fb4c.png

f1a062486bca522bc9e6fe5380477916.png

45ab37315ccffcaeddcedaab682663d6.png

以上说明Vue视图更新遵循最小量更新原则,没有变化的视图Vue就不会让该视图所属的元素发生变化。

上面说到当改变某个量时Vue会检索单个双大括号中是否有这个量,在这个过程中Vue会进行求值,如果求得的值和原来的值是一样的,则不会发生更新。

【注意】由于Vue的这一机制,在使用时尽量避免混进对DOM的操作改而操作数据,否则容易触发这一机制导致更新无效。

React中也有DIFF算法,效率比Vue高,因为React没有指令系统,其所有数据都是立即求值而不像Vue会先进行一番数据检索。React的更新原理是将更新的DOM存入虚拟DOM中与旧的DOM进行DIFF再进行最少量更新,Vue则比React多了一步词法分析。

最小量更新的重要角色 - key

在使用v-for指令时常常会与key属性连用,否则某些情况下会出现编辑器报错,一般key属性的属性值为循环的item或者index,属性值为item代表的是每一项循环的item本身,属性值为index则代表的是每一项的顺序。

9f6aaf14f73ab2576aea2646868cbcfb.png

4c49c9c82defc27eb1b658188991aa8b.png

c88562c6de2bd676ef5afc9af5c791e4.png

当涉及视图更新时,有没有key属性以及不同的属性值将会引发截然不同的结果。

没有key属性时更新不会触发beforeDestroy(),即原来的节点没有下树只是节点中的内容更新了。

e2697e24cf3181f95295576d71ec8b04.png

d06557e05ac6f54f0c368c89c58b0165.png

有key属性并且属性值为item时更新则会触发beforeDestroy(),证明“α”的节点下树(消亡)了,新的“”的节点被创建并上树。

79c680dcc6514fe07ef71cca7ef8b102.png

7f0941d4f72b91013403c5540678416b.png

有key属性并且属性值为index时更新又不会触发beforeDestroy()了,即没有节点上下树。

d9fa12680c664647d4121bd1be52b47f.png

9982a08a2d6f5f5b9f0937d7d6a7990c.png

759010b247a146a6bd6b60704ebd7ae9.png

所以当v-for循环涉及子组件循环时,key的属性值最好用item而不是index,否则会导致一些程序误判,当涉及一些AJAX等数据交互时也会阻断了组件与服务器之间的信息交换。使key的属性值为item的好处是能正确触发子组件的生命周期。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值