侦听多个属性时——计算属性 comuted。javascript
模板内的表达式很是便利,可是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板太重且难以维护。例如:css
<body> <div id="computed"> <div> {{msg.split('').reverse().join('')}} </div> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var com = new Vue({ el: "#computed", data:{ msg:"Hello World" } }) </script> </body>
在这个地方,模板再也不是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message
的翻转字符串。显示效果以下:vue
当你想要在模板中屡次引用此处的翻转字符串时,就会更加难以处理。java
因此,对于任何复杂逻辑,都应当使用计算属性。数组
<body> <div id="computed"> <div> <!--{{msg.split('').reverse().join('')}}--> {{reverseStr}} </div> <button @click="clickHandler">修改</button> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var com = new Vue({ el: "#computed", data:{ msg:"Hello World" }, methods:{ clickHandler(){ this.msg = 'Hello Luffy' } }, computed:{ // 计算属性: watch监听 // 计算属性默认只有getter方法,所以必须return reverseStr(){ return this.msg.split('').reverse().join(''); } } }) </script> </body>
当我点击按钮的时候更改了当前的数据,同时h3和p标签中数据也随时改变。缓存
(1)为何会这样呢?app
由于Vue知道com.currentMsg依赖与com.msg,所以当com.msg发生改变时,全部依赖com.currentMsg的绑定也会更新。并且最妙的是咱们已经以声明的方式建立了这种依赖关系。:计算属性的getter函数是没有反作用的,这使它更易于测试和理解。异步
(2)一样的上面操做,咱们不用computed声明的计算属性方法,而仅仅经过methods中声明的方法也能完成上面的效果,那么为何又要使用computed方法呢?函数
由于计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会从新求值。这就意味着只要msg尚未发生变化,屡次访问currentMsg计算属性会马上返回以前计算的结果,而不比再次执行函数。一样的。每当触发从新渲染时,调用方法将总会执行函数。oop
(3)咱们为何须要缓存?
假设咱们有一个性能开销比较大的的计算属性 A,它须要遍历一个巨大的数组并作大量的计算。而后咱们可能有其余的计算属性依赖于 A 。若是没有缓存,咱们将不可避免的屡次执行 A 的 getter!若是你不但愿有缓存,请用方法来替代。
<body> <div id="app"> <h4>{{alexDesc}}</h4> <button @click="clickHandler">修改</button> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> new Vue({ el:'#app', template:'', data(){ return { myName:'alex', age:18 } }, methods:{ clickHandler(){ this.myName='WUSIR'; this.age=28; } }, computed:{ alexDesc:function () { var str = `${this.myName}它的年龄是${this.age} 岁了能够去大保健了`;
// 默认只有getter方法 return str; } } }) </script> </body>
var str = `${this.myName}它的年龄是${this.age} 在实时监听data中声明的数据的变化。
点击事件,对数据属性进行修改,因为计算属性的实时监听,就察觉了数据的修改。
因为计算属性方法用模板插值关联,所以alexDesc函数的返回值就直接显示在模板中了。
计算属性默认只有 getter ,不过在须要时也能够提供一个 setter 。
<body>
<div id="app">
<h4>{{alexDesc}}</h4>
<button @click="clickHandler">修改</button>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
template:'',
data(){
return {
myName:'alex',
age:18
}
},
methods:{
clickHandler(){
console.log(this.alexDesc);
this.alexDesc = 'ALEX IS SB!!!';
}
},
computed:{
alexDesc:{
// setter
set:function (newValue) {
console.log(newValue);
this.myName = newValue;
},
// getter
get:function(){
var str = `${this.myName}它的年龄是${this.age}
岁了能够去大保健了`;
return str;
}
}
}
})
</script>
</body>
computed:{ alexDesc:{ // setter set:function (newValue) { console.log(newValue); this.myName = newValue; }, // getter get:function(){ var str = `${this.myName}它的年龄是${this.age} 岁了能够去大保健了`; return str; } } }
<body> <div id="app"> <input type="text" v-model="alexDesc"> <h4>{{alexDesc}}</h4> <!--<button @click="clickHandler">修改</button>--> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> new Vue({ el:'#app', template:'', data(){ return { myName:'', } }, computed:{ alexDesc:{ // setter,给myName赋新值 set:function (newValue) { this.myName = newValue; }, // getter,实时监听myName属性的变化 get:function(){ return this.myName; } } } }) </script> </body>
在input表单中输入信息,使用v-model进行双向数据绑定,使用setter给myName赋新值。getter监听myName属性的变化,并将值显示在 <h4>{{ alexDesc }} </h4>。
<audio>标签是 HTML5 的新标签。<audio>标签订义声音,好比音乐或其余音频流。
<body> <div id="music"> <audio src="../static/那吾克热-水滴石穿.mp3" controls="" autoplay=""></audio> <ul> <li v-for="(item, index) in musics"> <h3>{{item.id}}--歌曲为:{{item.name}}</h3> <p>歌手:{{item.author}}</p> </li> </ul> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var musicData = [{ id:1, name:"那吾克热-水滴石穿", author:"那吾克热", songSrc:'../static/那吾克热-水滴石穿.mp3' }, { id:2, name:"Inna-10 Minutes", author:"Inna", songSrc:'../static/10 Minutes.mp3' }, { id:3, name:"Devotion-My_Prayer", author:"Devotion", songSrc:'../static/My_Prayer.mp3' } ]; new Vue({ el:'#music', data(){ return { musics:musicData } }, template:'' }); </script> </body>
显示效果:
<body> <div id="music"> <audio v-bind:src="currentSrc" controls="" autoplay=""></audio> <ul> <li v-for="(item, index) in musics" @click="clickHandler(index)"> <!--给每一个li绑定点击事件--> <h3>{{item.id}}--歌曲为:{{item.name}}</h3> <p>歌手:{{item.author}}</p> </li> </ul> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var musicData = [{ id:1, name:"那吾克热-水滴石穿", author:"那吾克热", songSrc:'../static/那吾克热-水滴石穿.mp3' }, { id:2, name:"Inna-10 Minutes", author:"Inna", songSrc:'../static/10 Minutes.mp3' }, { id:3, name:"Devotion-My_Prayer", author:"Devotion", songSrc:'../static/My_Prayer.mp3' } ]; new Vue({ el:'#music', data(){ return { musics:musicData, musicSrc:'../static/那吾克热-水滴石穿.mp3' } }, methods:{ clickHandler(index){ // 声明点击事件 // alert(index); this.musicSrc = this.musics[index].songSrc; // 获取数组musics中对应index的歌曲资源 } }, computed:{ currentSrc(){ // 实时监听musicSrc return this.musicSrc; } }, template:'' }); </script> </body>
<body> <div id="music"> <audio v-bind:src="currentSrc" controls="" autoplay=""></audio> <ul> <li v-for="(item, index) in musics" @click="clickHandler(index)"> <!--给每一个li绑定点击事件--> <h3>{{item.id}}--歌曲为:{{item.name}}</h3> <p>歌手:{{item.author}}</p> </li> </ul> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var musicData = [{ id:1, name:"那吾克热-水滴石穿", author:"那吾克热", songSrc:'../static/那吾克热-水滴石穿.mp3' }, { id:2, name:"Inna-10 Minutes", author:"Inna", songSrc:'../static/10 Minutes.mp3' }, { id:3, name:"Devotion-My_Prayer", author:"Devotion", songSrc:'../static/My_Prayer.mp3' } ]; new Vue({ el:'#music', data(){ return { musics:musicData, currentIndex:0 // musicSrc:'../static/那吾克热-水滴石穿.mp3' } }, methods:{ clickHandler(index){ // 声明点击事件 // alert(index); this.currentIndex = index; // 点击事件修改index } }, computed:{ currentSrc(){ // 实时监听了两个属性:musics、currentIndex return this.musics[this.currentIndex].songSrc // 修改的index会致使获取的歌曲资源不一样 } }, template:'' }); </script> </body>
<head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> *{ padding: 0; margin: 0; } ul{ list-style: none; } ul li{ margin: 30px 20px; padding: 10px; } ul li.active{ background-color: #20FFFF; } </style> </head> <body> <div id="music"> <audio v-bind:src="currentSrc" controls="" autoplay=""></audio> <ul> <li v-for="(item, index) in musics" @click="clickHandler(index)" :class="{active:currentIndex==index}"> <!--给当前歌曲li添加class=active--> <h3>{{item.id}}--歌曲为:{{item.name}}</h3> <p>歌手:{{item.author}}</p> </li> </ul> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var musicData = [{ id:1, name:"那吾克热-水滴石穿", author:"那吾克热", songSrc:'../static/那吾克热-水滴石穿.mp3' }, { id:2, name:"Inna-10 Minutes", author:"Inna", songSrc:'../static/10 Minutes.mp3' }, { id:3, name:"Devotion-My_Prayer", author:"Devotion", songSrc:'../static/My_Prayer.mp3' } ]; new Vue({ el:'#music', data(){ return { musics:musicData, currentIndex:0 // musicSrc:'../static/那吾克热-水滴石穿.mp3' } }, methods:{ clickHandler(index){ // 声明点击事件 // alert(index); this.currentIndex = index; // 点击事件修改index } }, computed:{ currentSrc(){ // 实时监听了两个属性:musics、currentIndex return this.musics[this.currentIndex].songSrc // 修改的index会致使获取的歌曲资源不一样 } }, template:'' }); </script> </body>
点击事件的时候修改currentIndex,本身的li标签监听currentIndex,修改成对应的标签,添加class=active,显示效果以下所示:
虽然计算属性在大多数状况下更合适,但有时也须要一个自定义的侦听器。所以Vue 经过 watch
选项提供了一个更通用的方法,来响应数据的变化。当须要在数据变化时执行异步或开销较大的操做时,这个方式是最有用的。
<body>
<div id="app">
<input type="text" v-model="myName">
<h3>{{myName}}</h3>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
template:'',
data(){
return {
myName:''
}
},
watch:{
// 检测单个属性 命令式
myName:function (value) { // 经过watch来监听myName属性
console.log(value);
if (value === 'alex'){
console.log(value+"是sb");
}
}
}
})
</script>
</body>
经过watch来监听myName属性的变化,当属性值为alex时,控制台打印alex是sb。
<body> <div id="app"> <input type="text" v-model="myName"> <h3>{{myName}}</h3> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> new Vue({ el:'#app', template:'', data(){ return { myName:'', firstName:'wuSir' } }, watch:{ // 检测单个属性 命令式的 myName:function (value) { // 经过watch来监听myName属性 console.log(value); if (value === 'alex'){ console.log(value + " " + this.firstName +"是sb"); } } } }) </script> </body>
显示效果:
侦听器:侦听的是单个属性;
计算属性:侦听多个属性;
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变更:侦听属性。当你有一些数据须要随着其它数据变更而变更时,你很容易滥用 watch
——特别是若是你以前使用过 AngularJS。然而,一般更好的作法是使用计算属性而不是命令式的 watch
回调。
添加按钮,并给按钮绑定事件:
<body> <div id="app"> <input type="text" v-model="myName"> <h3>{{myName}}</h3> <button @click="clickHandler">修改</button> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> new Vue({ el:'#app', template:'', data(){ return { myName:'', firstName:'wuSir' } }, methods:{ clickHandler(){ this.myName = '日天'; } }, watch:{ // 检测单个属性 命令式的 myName:function (value) { // 经过watch来监听myName属性 console.log(value); if (value === 'alex'){ console.log(value + " " + this.firstName +"是sb"); } } } }) </script> </body>
点击按钮显示效果以下:
能够看到控制台也输出“日天”,这个输出的语句是来自:console.log(value);
若是将事件改成:this.myName = 'alex'; 则还会触发检测的if判断,显示效果以下所示:
上面的代码是命令式且重复的,将它与计算属性的版本进行比较:
<body> <div id="app"> <input type="text" v-model="myName"> <h3>{{myName}}</h3> <button @click="clickHandler">修改</button> </div> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data(){ return{ myName: '', firstName: 'wuSir', } }, methods:{ clickHandler(){ this.myName = 'alex'; } }, computed: { fullName: function (value) { // 计算属性的名字不能与data中属性同名 if (value === 'alex') { console.log(value + " " + this.firstName + "是sb!") } } } }) </script> </body>
修改成计算属性的版本,明显比上面命令式的要好得多。显示效果以下所示: