vue computed计算属性 watch监听
计算属性
computed:{ 变量:function(){ return 计算好的值 } }
<template> <div class="watch"> <input type="text" v-model="msg" /> <input type="text" v-model="comsg" /> </div> </template> <script> export default { name: "watch", data() { return { msg: "123" }; }, methods: {}, computed: { comsg: function() { return this.msg .split("") .reverse() .join(""); } } }; </script>
效果:
初始有值的时候 就已经计算了,并且监听数据改变重新计算
计算属性的getter 和setter:以上我们举例的是默认的getter。
在你需要时,也可以提供一个setter 函数, 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发setter 函数,执行一些自定义的操作
getter/setter语法
computed: { 变量: { get: function() { return 计算的值; }, set: function(newold) { //当计算的值被改变时调用set console.log(newold); } } }
上面的例子,除了使用计算属性外,我们也可以通过在表达式中调用方法来达到同样的效果,那么方法和computed都应该处于什么场景呢
computed:计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
方法:每当触发重新渲染时,调用方法将总会再次执行函数
假设我们有一个性能开销比较大的的计算属性,它需要遍历一个巨大的数组并做大量的计算。
如果没有缓存,我们将不可避免的多次执行 它的 getter!如果你不希望有缓存,请用方法来替代。
watch监听
监听大概可以分为三种
上面说到计算属性的时候 初始化的时候就可以被监听到并且计算 但是watch是发生改变的时候才会触发:例如
这是基本用法
<template> <div class="watch"> <input type="text" v-model="msg" /> <input type="text" v-model="comsg" /> </div> </template> <script> export default { name: "watch", data() { return { msg: "123", comsg: "" }; }, methods: {}, watch: { msg(newval, old) { console.log(newval, old); this.comsg = this.msg .split("") .reverse() .join(""); } } }; </script>
效果:可以发现 初始化的时候并没有触发 watch监听 图二改变的时候才触发了watch
handler方法和immediate属性
如果 父组件向子组件传值时 这时候值并没有发生改变我们却想在初始的时候就触发watch 就需要这个属性了 immediate 默认为false 为true时只初始化可以被监听
<template> <div class="watch"> <input type="text" v-model="msg" /> <input type="text" v-model="comsg" /> </div> </template> <script> export default { name: "watch", data() { return { msg: "123", comsg: "" }; }, methods: {}, watch: { msg: { handler(newval, old) { console.log(newval, old); this.comsg = this.msg .split("") .reverse() .join(""); }, immediate: true } } }; </script>
效果:
可以看到 初始的时候就触发了watch监听 old打印为undefined
注意到handler
了吗,我们给 msg 绑定了一个handler
方法,之前我们写的 watch 方法其实默认写的就是这个handler
,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler
。
deep属性
watch 里面还有一个属性 deep
,默认值是 false
,代表是否深度监听
语法:用来监听obj
watch: { obj: { handler(newval, old) { //newval old }, immediate: true, deep: true } }
deep
的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj
里面任何一个属性都会触发这个监听器里的 handler。
如果监听obj中的属性 例如obj.a 就可以优化,使用字符串形式监听 这样 vue会一层一层解析,直到遇见a属性,然后给它设置监听函数
watch: { 'obj.a': { handler(newval, old) { //newval old }, immediate: true, // deep: true } }
注销watch
为什么要注销 watch
?因为我们的组件是经常要被销毁的,比如我们跳一个路由,从一个页面跳到另外一个页面,那么原来的页面的 watch 其实就没用了,这时候我们应该注销掉原来页面的 watch 的,不然的话可能会导致内置溢出。我们平时 watch 都是写在组件的选项中的,会随着组件的销毁而销毁。
如果这种写法就需要手动注销watch
const unWatch = app.$watch('text', (newVal, oldVal) => { console.log(`${newVal} : ${oldVal}`); }) unWatch(); // 手动注销watch
watch监听路由
watch: { '$route'(to,from){ console.log(to); //to表示去往的界面 console.log(from); //from表示来自于哪个界面 if(to.path=="/lifeCycle"){
console.log("生命周期");
}
}
}