computed用发_Vue中的computed属性和nextTick方法

computed

computed属性的实现原理

Vue实例初始化时,给data的每个属性(dataKey)都添加getter和setter方法

计算属性computed初始化时,提供的函数将作为对应属性(computedKey)的getter方法

其中,computed属性采用函数式声明

computedKey: function(){

return this.dataKey+'change'

}

当首次获取计算属性的值是,dep开始收集依赖,即收集到dataKey和computedKey的依赖关系,也就是上面的this.datakey+'change';

在dataKey变化时,此时会调用dataKey的getter方法,通过dep收集的依赖,可以判定出data与computed对应数据的依赖关系

此时可以做到,在data发生变化时,computed属性数据也发生变化

computed属性的用法

目的:是为了避免模板中加入太多的计算公式,不够精炼,而且computed属性比较节约

官网中的写法:

Original message: "{{ message }}"

Computed reversed message: "{{ reversedMessage }}"

var vm = new Vue({

el: '#example',

data: {

message: 'Hello'

},

computed: {

// 计算属性的 getter

reversedMessage: function () {

// `this` 指向 vm 实例

return this.message.split('').reverse().join('')

}

}

})

在模板文件中,只需要在插值表达式中写reversedMessage这个属性即可,它与message有依赖关系

computed属性与watch的区别

当需要数据在 异步变化或者开销较大时 ,执行更新,使用watch会更好一些;而computed不能进行异步操作;

computed可以用 缓存中拿数据 ,而watch是每次都要运行函数计算,不管变量的值是否发生变化,而computed在值没有发生变化时,可以直接读取上次的值

computed属性与methods的区别

在模板文件中,computed属性只需要写reverseMessage,而methods需要写成reverseMessage(),最明显的区别就是methods是方法,需要执行;

computed属性只有在依赖的data放生变化时,才会重新执行,否则会使用缓存中的值,而methods是每次进入页面都要执行的,有些需要每次进入页面都执行的方法,需要使用methods,而computed属性比较节约。

this.$nextTick

nextTick的原理

nextTick 可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM。

在 Vue 2.4 之前都是使用的 microtasks,但是 microtasks 的优先级过高,在某些情况下可能会出现比事件冒泡更快的情况,(也就是,出现微任务执行比点击事件之类的事件触发还要快,导致逻辑出错)但如果都使用 macrotasks 又可能会出现渲染的性能问题。所以在新版本中,会默认使用 microtasks,但在特殊情况下会使用 macrotasks,比如 v-on。

对于实现 macrotasks ,会先判断是否能使用 setImmediate ,不能的话降级为 MessageChannel ,以上都不行的话就使用setTimeout

nextTick的使用实例

//模板

{{msg}}

Message got outside $nextTick: {{msg1}}

Message got inside $nextTick: {{msg2}}

Message got outside $nextTick: {{msg3}}

Change the Message

//Vue实例

new Vue({

el: '.app',

data: {

msg: 'Hello Vue.',

msg1: '',

msg2: '',

msg3: ''

},

methods: {

changeMsg() {

this.msg = "Hello world."

this.msg1 = this.$refs.msgDiv.innerHTML

this.$nextTick(() => {

this.msg2 = this.$refs.msgDiv.innerHTML

})

this.msg3 = this.$refs.msgDiv.innerHTML

}

}

})

点击前:

点击后:

此时我们看到msg1和msg3显示的内容还是变换之前的,而msg2显示的内容是变换之后的。其根本原因是因为Vue中DOM更新是异步的

具体原因在Vue的官方文档中详细的解释:

Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then 和MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。

例如,当你设置vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。

让我们回到之前的例子,执行点击事件之后msg1,msg3中对DOM进行操作,他们拿到的数据还是DOM为更新前的,还是hello,vue,因为上面说了,置vm.someData = ‘new value’,该组件不会立即重新渲染。而msg2是写在nexttick函数里面的,它的执行会延迟到DOM更新之后,也就是msg变成hello,world之后,这样它操作DOM拿到的数据才是更新后的。

这只是一个简单方便理解的例子,要是想深入了解的话,建议还是可以看一下vue.nextTick的源码。

参考

https://www.jianshu.com/p/a7550c0e164f

https://segmentfault.com/a/1190000015070628

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值