computed 和 watch 的异同

computed 和 watch 都可以观察页面的数据变化。

当处理页面的数据变化时,我们有时候很容易滥用watch。
而通常更好的办法是使用computed属性,而不是watch回调。
这里我直接引用vue官网的例子来说明:

html:
我们要实现 第三个表单的值 是第一个和第二个的拼接,并且在前俩表单数值变化时,第三个表单数值也在变化.

1
2
3
4
5
<div id="myDiv">
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
<input type="text" v-model="fullName">
</div>

js: 用watch方法来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new Vue({
el: '#myDiv',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})

js: 利用computed 来写

1
2
3
4
5
6
7
8
9
10
11
12
new Vue({
el:"#myDiv",
data:{
firstName:"Den",
lastName:"wang",
},
computed:{
fullName:function(){
return this.firstName + " " +this.lastName;
}
}
})

很容易看出 computed 在实现上边的效果时,是更简单的。

详解 comouted 计算属性。

在vue的模板内{ { } }是可以写一些简单的js表达式的 ,很便利。但是如果在页面中使用大量或是复杂的表达式去处理数据,对页面的维护会有很大的影响。这个时候就需要用到computed 计算属性来处理复杂的逻辑运算。

  1. 优点:
    在数据未发生变化时,优先读取缓存。computed 计算属性只有在相关的数据发生变化时才会改变要计算的属性,当相关数据没有变化是,它会读取缓存。而不必想 motheds方法 和 watch 方法是的每次都去执行函数。
  2. setter 和 getter方法:(注意在vue中书写时用set 和 get)
    setter 方法在设置值是触发。
    getter 方法在获取值时触发。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    computed:{
    fullName:{
    //这里用了es6书写方法
    set(){
    alert("set");
    },
    get(){
    alert("get");
    return this.firstName + " " +this.lastName;
    },
    }
    }

watch 方法

虽然计算属性在大多数情况下是非常适合的,但是在有些情况下我们需要自定义一个watcher,在数据变化时来执行异步操作,这时watch是非常有用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<template>
<div class="container">
<template v-for='(data,index) of datas'>
<p class="listTop"><span class="col3">{{data.tit}}</span><template v-if='data.num != 100'>(还可输入{{data.num}}字)</template></p>
<div class="feedBack">
<div class="feed-text feed-mini" :class='{ col5 : data.def!==data.txt }'>
<textarea class="limitFeed" @focus='textFocus(index)' @blur='textBlur(index)' v-model.tirm='data.txt'></textarea>
</div>
</div>
</template>
</div>
</template>
<script>
export default {
data () {
return {
datas:[
{tit:'我的简介', txt:'',num:100,def:'请简单介绍您的基本情况。例如:本人在浙江杭州上班,从事的行业是互联网行业。(字数100字以内)'},
{tit:'我的还款能力',txt:'',num:100,def:'请简单介绍您的还款能力。例如:本人在公司任职的岗位是java开发,月收入稳定,能按时归还借款。(字数100字以内)'},
{tit:'本次申请借款的用途',txt:'',num:100,def:'请介绍本次申请借款的用途。例如:本次申请借款主要是因为新家装修,急需用钱。(字数100字以内)'},
]
}
},
methods :{
textFocus(i){
//获取焦点时
if(this.datas[i].txt == this.datas[i].def) this.datas[i].txt = '';
},
textBlur(i){
//失去焦点时
if(this.datas[i].txt == '') this.datas[i].txt = this.datas[i].def;;
},
changeText(i){
//如果当前textarea值不等于默认值的话-->限止字母在100字内
if(this.datas[i].txt.length >100 ){
this.datas[i].txt = this.datas[i].txt.substring(0,100);
}else if(this.datas[i].txt == this.datas[i].def){
this.datas[i].num = 100;
}else{
this.datas[i].num = (100-this.datas[i].txt.length);
}
}
},
computed:{
dataRest:function(){
//计算返回一组新数据格式-->{'0':'xxx','1':'xxx','2':'xxx'}<--[模拟索引号]]
var obj = {};
for(var i = 0; i < this.datas.length; i++) obj[i]=this.datas[i].txt;
return obj;
}
},
watch:{
dataRest:{
handler:function(nowVal,oldVal){
//观擦计算返回的新数据-->对比新旧值返回差异的[“索引号”]
for(var i = 0; i < this.datas.length; i++){
if(nowVal[i] != oldVal[i]) this.changeText(i);
}
},
deep:true
}
},
created:function(){
for(var i=0; i < this.datas.length; i++) this.datas[i].txt = this.datas[i].def; //为textarea赋默认值
}
}
</script>