需求:字符串转换成大写后合并
1、插值实现
直接在需要展示结果的地方,使用js表达式str.toUpperCase()然后拼接在一起。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>计算属性_插值</title>
<!--引入vue.js,则全局就会多了一个vue的构造函数-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备一个容器-->
<div id="root">
字符串1:<input type="text" v-model="str1"><br/>
字符串2:<input type="text" v-model="str2"><br/>
<!--1、插值实现方式:缺点:模板中的表达式太长,不够精简-->
转换成大写字母并合并:<span>{{str1.toUpperCase()}} {{str2.toUpperCase()}}</span>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
str1:'Hello',
str2:'World'
}
})
</script>
</body>
</html>
缺点是模板中的表达式太长,不够精简,不符合官网【风格指南】中的强烈推荐【模板中简单的表达式】:组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
2、计算属性实现
模板中直接使用计算属性:
有get,那么就可能有对应的set:
//当fullString被修改时调用set
set(value){
console.log("computed中的set被调用");
const arr = value.toLowerCase().split(" ");
this.str1 = arr[0];
this.str2 = arr[1];
}
3、method实现
模板中调用方法:
4、监视属性实现
watch: {
//当监测到str1改变时,计算
str1: function (val) {
this.fullname = val.toUpperCase() + ' ' + this.str2.toUpperCase()
},
//当检测到str2改变时,计算
str2: function (val) {
this.fullname = this.str1.toUpperCase() + ' ' + val.toUpperCase()
}
代码冗余。
5、对比一下计算属性和method
乍一看,似乎二者都可以实现所需功能,但是,我们在模板中分别使用两次,观察一下console中的信息。
<!--2、计算属性实现方式:-->
【计算属性】转换成大写字母并合并:<span>{{fullString}}</span><br>
【计算属性】转换成大写字母并合并:<span>{{fullString}}</span><br>
<hr>
<!--3、method实现方式:缺点:效率不高-->
【methods】转换成大写字母并合并: <span>{{handleString()}}</span><br>
【methods】转换成大写字母并合并: <span>{{handleString()}}</span>
console中:虽然二者都被使用2次,但是计算属性中的get仅被调用一次,而method被调用了2次。这是因为计算属性有缓存机制,当它所依赖的属性发生变化时,它才会重新计算,否则,使用缓存值。这就使得它的执行效率比methods要高。
6、计算属性的简写方式
如果非常确定计算属性仅用于展示,而不会被修改,那么可以不写setter,使用简写方式仅用于标识getter:
//如果确定该值仅用于展示,不会被修改,则可以不用写setter,那么getter也可以不写,如下:
fullString(){
console.log("computed中的get被调用");
return this.str1.toUpperCase() +" "+ this.str2.toUpperCase();
}
总结
- 当要用的属性不存在,要通过已有的属性计算得来时,可使用计算属性。它借助了Object.defineproperty方法提供的getter/setter来实现双向绑定。其中,getter函数在初始化的时候会读取一次,在其依赖的属性发生改变时会再次调用。
- 若其依赖属性未发生改变,代码中多次使用该属性,不会重复调用getter,而是读取其缓存值。
- 虽然使用methods也可以实现所需要的功能,但是methods对其结果不具备缓存机制,每次调用,不论其依赖的属性是否发生变化,均会重新计算,因此,computed与methods相比,缓存机制的存在使得代码的执行效率更高。
- 不过,计算属性如果可能会被修改,那么一定要自己写set函数来响应用户变更。
- 如果确定计算属性仅用于展示,不会被修改,那么可以使用简写形式。
- 监视属性:每次只能检测一个属性的变化。如果一个值需要依赖于多个属性,那么使用监视属性则会出现重复代码,这时使用计算属性更加合适。
本练习的全部代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>计算属性-方法-监视属性对比</title>
<!--引入vue.js,则全局就会多了一个vue的构造函数-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备一个容器-->
<div id="root">
字符串1:<input type="text" v-model="str1"><br/>
字符串2:<input type="text" v-model="str2"><br/>
<!--1、插值实现方式:缺点:模板中的表达式太长,不够精简-->
【插值方式】转换成大写字母并合并:<span>{{str1.toUpperCase()}} {{str2.toUpperCase()}}</span><br>
<hr>
<!--2、计算属性实现方式:-->
【计算属性】转换成大写字母并合并:<span>{{fullString}}</span><br>
【计算属性】转换成大写字母并合并:<span>{{fullString}}</span><br>
<hr>
<!--3、method实现方式:缺点:效率不高-->
【methods】转换成大写字母并合并: <span>{{handleString()}}</span><br>
【methods】转换成大写字母并合并: <span>{{handleString()}}</span>
<hr>
<!--4、watch实现方式:缺点:代码冗余-->
【watch】转换成大写字母并合并: <span>{{fullname}}</span><br>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
str1:'Hello',
str2:'World',
fullname:'Hello World'
},
computed: {
//计算属性的完整写法
/* fullString:{
get(){
console.log("computed中的get被调用");
return this.str1.toUpperCase() +" "+ this.str2.toUpperCase();
},
//当fullString被修改时调用set
set(value){
console.log("computed中的set被调用");
const arr = value.toLowerCase().split(" ");
this.str1 = arr[0];
this.str2 = arr[1];
}
} */
//计算属性的简写:如果确定该值仅用于展示,不会被修改,则可以不用写setter,那么getter也可以不写,如下:
fullString(){
console.log("computed中的get被调用");
return this.str1.toUpperCase() +" "+ this.str2.toUpperCase();
}
},
methods: {
handleString(){
console.log("调用methods中的方法")
return this.str1.toUpperCase() +" "+ this.str2.toUpperCase();
}
},
watch: {
//当监测到str1改变时,计算
str1: function (val) {
this.fullname = val.toUpperCase() + ' ' + this.str2.toUpperCase()
},
//当检测到str2改变时,计算
str2: function (val) {
this.fullname = this.str1.toUpperCase() + ' ' + val.toUpperCase()
}
}
})
</script>
</body>
</html>