- watch:监视单个属性
- computed:监视多个属性
注:v-model是双向绑定数据,但并未将数据与方法挂钩;为了解决这个问题,watch与computed诞生了。
一、watch
watch是一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。
由于watch监视的是单个属性的地址
, 这就意味着 监视简单数据类型 和 监视复杂数据类型做法不同。
模板:
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: [
'handle1',
function handle2 (val, oldVal) { /* ... */ },
{
handler: function handle3 (val, oldVal) { /* ... */ },
/* ... */
}
],
// watch vm.e.f's value: {g: 5}
'e.f': function (val, oldVal) { /* ... */ }
}
})
vm.a = 2 // => new: 2, old: 1
上面看不懂不要紧,往下看····
1、监视简单数据类型:简单监视
watch: {
'属性名': function(newV, oldV) {·····}
}
简单数据类型:Number/String/Boolean/Null/Undefined/Symbol
例:
<div id="app"></div>
<script type="text/javascript">
let App = {
template:
`<div>
<input type="text" v-model="myText"/>
{{ myText }}
</div>`,
data() {
return {myText: ''};
},
watch: {
myText: function(newV, oldV) {
console.log(newV, oldV);
if(newV === 'iloveyou') {
alert('我不爱你');
}
}
},
}
let vm = new Vue({
el: document.getElementById('app'),
components: {'app': App},
template: `<app />`,
});
</script>
在input中输入 iloveyou 后,弹出alert框
你输入 ab
后,控制台会输出:
说明 function(newV, oldV)中,newV为新值,oldV为旧值。
2、监视复杂数据类型:深度监视
watch: {
'属性名': {
deep: true,
handler: function(newV, oldV) {···},
immediate: true, //非必需值
}
}
复杂数据类型:Object / Array
例:
<div id="app"></div>
<script type="text/javascript">
let App = {
template:
`<div>
<button @click="stus[0].name = 'bty';">改变</button>
</div>`,
data() {
return {
stus: [{name: 'jack'}],
};
},
watch: {
stus: {
deep: true,
handler: function(newV, oldV) {
console.log(this.stus[0].name);
}
},
},
}
let vm = new Vue({
el: document.getElementById('app'),
components: {'app': App},
template: `<app />`,
});
</script>
点击button后,控制台输出:bty
注意,不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。
二、computed
与watch不同,computed将监视对象 写在了函数内部,凡是函数内部有 this.相关属性
改变,都会触发当前函数。(注:第一次如进入界面渲染也会触发一次)
computed: {
myData: function() {},
myData2: {
get: function () { return ····;},
set: function (v) {····}
},
}
例1:
<div id="app"></div>
<script type="text/javascript">
let App = {
template:
`<div>
( <input type="text" v-model="n1"/>
+
<input type="text" v-model="n2"/>)
*
<input type="text" v-model="rate"/>
=
{{ result }}
</div>`,
data() {
return {n1:0, n2:0, rate:0};
},
computed: {
result: function() {
//computed将监视对象 写在了函数内部,
//凡是函数内部有 `this.相关属性` 改变,都会触发当前函数。
return ((this.n1-0) + (this.n2-0)) * this.rate;
}
}
}
let vm = new Vue({
el: document.getElementById('app'),
components: {'app': App},
template: `<app />`,
});
</script>
展示:
如果你将第一个值45复制后,再粘贴到第一个位置,你会发现整个过程result都没有发生变化,这就是computed的缓存机制(看下面注)
注:计算属性的结果会被缓存,即:若computed包含的原值不改变,缓存不会调用函数。
例2:
var vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
vm.aPlus // => 2
vm.aPlus = 3
vm.a // => 2
vm.aDouble // => 4
computed所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
methods、filters、watch、computed的使用时机:
- watch:当你要对data里的
一个变量
进行监视
,且当该变量在改变时``要做出一些响应
时使用 - computed: 当你要对data里的
多个变量
进行监视
,且这些变量有一个或多个在改变时
要做出一些响应
时使用 - filters: 当你要对数据进行一些处理,且过程中
不需要使用data里的数据
时使用(纯函数) - methods: 当你要对数据进行一些处理,过程中还
要使用data里的数据
时使用