------------------------------------------------------------------------------官网示例------------------------------------------------------------------------------
var vm = new Vue({
data: {
a: 1,
b: 2,
c: 3,
d: 4,
e: {
f: {
g: 5
}
}
},
watch: {
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
// 方法名
b: 'someMethod',
// 深度 watcher
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
// 该回调将会在侦听开始之后被立即调用
d: {
handler: function (val, oldVal) { /* ... */ },
immediate: true
},
e: [
function handle1 (val, oldVal) { /* ... */ },
function handle2 (val, oldVal) { /* ... */ }
],
// watch vm.e.f's value: {g: 5}
'e.f': function (val, oldVal) { /* ... */ }
}
})
vm.a = 2 // => new: 2, old: 1
注意,不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。
什么时候用深度监听
watch:{} 对象,可监听数据,数据发生变化, 处理函数
目的: watch虽可监听,但只是浅监听,只监听数据第一层或者第二层,
何为第二层?
let obj = {name: 'xx', child: {age: 11}};
child之后的值就为第二层或者深层
如果要实现 监听一个对象中的属性,属性最高也是第二层了,watch可能监听不到,所以要使用深度监听。
实现代码:
watch: {
'user.phone ' : {
handler:function() { //特别注意,不能用箭头函数,箭头函数,this指向全局处理函数},
deep: true //深度监听
}
}
--------------------------------------------------------------示例:监听&深度监听----------------------------------------------------------------------------
handler方法
watch 的一个特点是,最初绑定的时候是不会执行的,要等到 被监听的值 改变时才执行监听计算。
那我们想要一开始就让他最初绑定的时候就执行改怎么办呢?
解决办法是:修改一下我们的 watch 写法,给被监听值绑定了一个handler方法。
之前我们写的 watch 方法其实默认写的就是这个handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler。
immediate属性
immediate:true代表如果在 wacth 里声明了 被监听值 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。
deep属性
watch 里面还有一个属性 deep,默认值是 false,代表是否深度监听。
deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大,任何修改 被监听对象 里面任何一个属性 都会触发这个监听器里的 handler。
优化:,可以使用字符串形式监听。
这样Vue.js会一层一层解析下去,直到遇到 属性 x,然后才给 x 设置监听函数。
注销watch
为什么要注销 watch?
因为我们的组件是经常要被销毁的,比如我们跳一个路由,从一个页面跳到另外一个页面,那么原来的页面的 watch 其实就没用了,这时候我们应该注销掉原来页面的 watch 的,不然的话可能会导致内置溢出。
不过我们平时 watch 都是写在组件的选项中的,他会随着组件的销毁而销毁
但是,如果我们使用下面这样的方式写 watch,那么就要手动注销了,这种注销其实也很简单
const unWatch = app.$watch('text', (newVal, oldVal) => {
console.log(`${newVal} : ${oldVal}`);
})
unWatch(); // 手动注销watch
app.$watch调用后会返回一个值,就是unWatch方法,你要注销 watch 只要调用unWatch方法就可以了。
------------------------------------------------------------------------------props---------------------------------------------------------------------------------
------------------------------------------------------------------------------props示例---------------------------------------------------------------------------------
--------------------------------------------------------------------------computed---------------------------------------------------------------------------------
--------------------------------------------------------------------------computed示例---------------------------------------------------------------------------------
-----------------------------------------------------------------------method--------------------------------------------------------------------------------------
---------------------------------------------------------------------------method示例----------------------------------------------------------------------------
-----------------------------------------------------------浅析Vue中computed与method的区别-----------------------------------------------------------
一、在官方文档中,强调了computed区别于method最重要的两点
- computed是属性调用,而methods是函数调用
- computed带有缓存功能,而methods不是
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<p class="test1">{{methodTest}}</p>
<p class="test2-1">{{methodTest()}}</p>
<p class="test2-2">{{methodTest()}}</p>
<p class="test2-3">{{methodTest()}}</p>
<p class="test3-1">{{computedTest}}</p>
<p class="test3-2">{{computedTest}}</p>
</div>
<script>
var vm2=new Vue({
el:"#app",
data:{message: '我是消息'},
computed: {
computedTest() {
return this.message + '现在我用的是computed'
}
},
methods:{
methodTest() {
return this.message + '现在我用的是methods'
}
}
});
</script>
</body>
</html>
二、computed的属性调用
在HTML的插值里,computed定义的方法我们是以属性访问的形式调用的,{{computedTest}}
但是methods定义的方法,我们必须要加上()来调用,如{{methodTest()}},否则,视图会出现
function () { [native code] }
三、 computed的缓存功能
首先,我们要明白缓存究竟有什么用?
相比大家都知道HTTP缓存,其核心作用就是对一些服务端未更新的资源进行复用,避免一些无谓的请求,优化了用户的体验
对于computed也是一样的:
在上面的例子中, methods定义的方法是以函数调用的形式来访问的,那么test2-1,test2-2,test2-3是反复地将methodTest方法运行了三遍,如果我们碰到一个场景,需要1000个methodTest的返回值,那么毫无疑问,这势必造成大量的浪费
更恐怖的是,如果你更改了message的值,那么这1000个methodTest方法每一个又会重新计算。。。。
所以,官方文档反复强调对于任何复杂逻辑,你都应当使用计算属性
computed依赖于data中的数据,只有在它的相关依赖数据发生改变时才会重新求值
如上例,在Vue实例化的时候,computed定义computedTest方法会做一次计算,返回一个值,在随后的代码编写中,只要computedTest方法依赖的message数据不发生改变,computedTest方法是不会重新计算的,也就是说test3-1,test3-2是直接拿到了返回值,而非是computedTest方法重新计算的结果。
同样,如果我们碰到一个场景,需要1000个computedTest的返回值,那么毫无疑问,对于methods而言,将调用计算1000次,大大消耗内存,对于computed而言,哪怕你改变了message的值,computedTest也只会计算一次而已
四、. computed的其它说明
- computed其实是既可以当做属性访问也可以当做方法访问
- computed的由来有一个重要原因,就是防止文本插值中逻辑过重,导致不易维护
------------------------------------------------------------------------------data---------------------------------------------------------------------------------
------------------------------------------------------------------------------官网示例---------------------------------------------------------------------------------
var data = { a: 1 }
// 直接创建一个实例
var vm = new Vue({
data: data
})
vm.a // => 1
vm.$data === data // => true
// Vue.extend() 中 data 必须是函数
var Component = Vue.extend({
data: function () {
return { a: 1 }
}
})
注意,如果你为 data 属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。
data: vm => ({ a: vm.myProp })