计算属性与监听属性(computed和watch)

计算属性

  • 计算属性定义在computed选项中
  • 当计算属性依赖的数据发生变化时,计算属性会自动更新,所有依赖该属性的数据绑定也会同步更新
  • 最重要的一点:计算属性是一个属性,不是一个方法
    简单示例如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <div id="box">
    <p>原字符串:{{str}}</p>
    <p>新字符串:{{netstr}}</p>
    </div>
    <script type="text/javascript">
    var vm = new Vue({
    el: '#box',
    data: {
    str: 'HTML*JavaScript*Vue.js'
    },
    computed: {
    netstr: function () {
    return this.str.split('*').join('+');
    }
    }
    });
    </script>
    注:当data里的str发生变化时,newstr也会自动更新

计算属性+过滤器的一个实例:

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
<div id="box">
<div class="title">
<div>商品名称</div>
<div>单价</div>
<div>数量</div>
<div>金额</div>
</div>
<div class="content" v-for="value in shop">
<div>{{value.name}}</div>
<div>{{value.price}}</div>
<div>{{value.count}}</div>
<div>{{value.price*value.count | twoDecimal}}</div>
</div>
<p>总计:{{totalprice | formatPrice("¥")}}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#box',
data: {
shop: [{
name: 'OPPO R15',
price: 2999,
count: 3,
}, {
name: '华为P20',
price: 3699,
count: 2,
}]
},
computed: {
totalprice: function () {
var total = 0;
this.shop.forEach(function (s) {
total += s.price * s.count;
});
return total;
}
},
filters: {
twoDecimal: function (value) {
return value.toFixed(2);
},
formatPrice: function (value, symbol) {
return symbol + value.toFixed(2);
}
}

});
</script>

getter和setter

  • 每一个计算属性都包含一个getter和setter
  • getter用来执行读取值的操作,setter用来执行设置值的操作
  • 当没有指明方法时(属性名后的function),默认使用getter来读取数据
  • 在未设置setter的情况下给计算属性重新赋值,是不会触发更新的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="box">
<p>{{fullname}}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#box',
data: {
firstname: '张',
lastname: '斯特',
},
computed: {
fullname: {
get: function () {
return this.firstname + this.lastname;
},
set: function (value) {
this.firstname = value.substr(0, 1);
this.lastname = value.substr(1);
}
}
}
});
vm.fullname = '利乌斯';
</script>

上述示例执行过程:

  1. 定义了一个计算属性fullname
  2. 在给fullname重新赋值时会自动调用setter,并将新值作为参数传递给set()方法
  3. 在set()方法中定义去修改data里的属性值,当data属性值改变后,fullname也会跟着改变(而不是直接改变fullname的值,直接改变是无效的)

计算属性缓存

  • 使用计算属性时,每次获取的值都是基于依赖的缓存值(即基础值)
  • 当页面重新渲染时,如果依赖的数据未发生改变,则计算属性值也不会改变。只有依赖的数据改变,才会重新执行getter

下面给出计算属性和方法的区别

计算属性:只有依赖的值发生改变时,计算属性才会变
方法:每当页面重新渲染时,方法就会再次执行

监听属性

  • 定义:监听属性用于监听和响应Vue实例中的数据变化
  • 在监听数据对象中的属性时,每当监听的属性发生变化时,都会执行特定的操作
  • 监听属性的名字和要监听的对象相同,即要监听哪个属性,命名就和那个属性名一样
  • 定义监听属性有两种方式:watch选项实例方法vm.$watch()
  1. watch选项:watch:{}
  2. vm.$watch()在Vue实例后面定义:vm.$watch('监听对象名',function(参数){代码})

两种方法简单示例如下,第一个参数是新值,第二个参数是旧值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script type="text/javascript">
var vm = new Vue({
el: '#box',
data: {
fullname: '张三',
},
watch: {
fullname: function (newValue,oldValue) {
alert('原值:' + oldValue + ' 新值:' + newValue);
}
}
});
vm.fullname = '李四';
</script>
1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript">
var vm = new Vue({
el: '#box',
data: {
fullname: '张三',
},
});
vm.$watch('fullname', function (newValue, oldValue) {
alert('原值:' + oldValue + ' 新值:' + newValue)
});
vm.fullname = '李四';
</script>

deep选项

handler
先简单介绍一下handler,当deep的值为true时,必须使用handler函数

如果监听的属性是一个对象(即字典),为了监听对象内部值的变化,必须在watch选项中设置deep的值为true,简单示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript">
var vm = new Vue({
el: '#box',
data: {
shop: {
name: 'XiaoMi10',
price: 3899,
},
},
watch: {
shop: {
handler: function (val) {
alert(val.name + '新价格为' + val.price);
},
deep: true
}
}
});
vm.shop.price = 4899;
</script>

参考链接

  1. vue中watch的handler,deep,immediate用法详解
  2. vue handler ()的参数是什么