vue.js基础(4)
2018-03-29 08:39
344 查看
计算属性和侦听器
计算属性
<div id="example"> {{message.split('').reverse().join('')}} </div>
在这里,模版不再是简单的声明式逻辑
对于任何复杂逻辑,都应当使用计算属性
例:
<div id="example"> <p>Original message:"{{message}}"</p> <p>Computed reversed message:"{{reversedMessage}}"</p> </div>
var vm = new Vue({ el:"#example", data:{ message:"Hello" }, computed:{ //计算属性的getter reverseMessage:function(){ //'this'指向VM实例 return this.message.split('').reverse.join('') } } });
这里我们声明了一个计算属性 ++reversedMessage++。我们提供的函数将作用属性++vm.reversedMessage++的++getter++函数
console.log(vm.reverseMessage) //=>"olleH" vm.message = "Goodbye" console.log(vm.reversedMessage) //=>"eybdoG"
注:vm.reversedMessage的值始终取决于vm.message
计算属性缓存VS方法
可以通过在表达式中调用方法来达到同样的效果:<p>Reversed message:"{{reversedMessage()}}"</p> //在组件中 methods:{ reversedMessage:function(){ return this.message.split('').reverse().join('') } }
可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
例:下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:
computed:{ now:function(){ return Date.now() } }
每当触发重新渲染时,调用方法将总会再次执行函数。
计算属性VS监听属性
侦听属性:来观察和响应 Vue 实例上的数据变动。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
<div id="demo">{{fullName}}</div> var vm = new Vue({ el:'#demo'; data:{ firstName:'Foo', lastName:'Bar', fullName:'Foo Bar' }, watch:{ firstName:function(val){ this.fullName = val + ' ' + this.lastName }, lastName:function(val){ this.fullName = this.flrstName + ' ' + val }, } });
将它与计算属性的版本进行比较:
var vm = new Vue({ el:'#demo', data:{ firstName:'foo', lastName:'Bar' }, computed:{ fullName:function(){ return this.firstName + ' ' + this.lastName } } });
现在再运行vm.fullName = “John Doe” 时,setter会被调用,vm.firstName和vm.lastName也会相应的被更新
侦听器
当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。例:
<div id="watch-example"> <p> Ask a yes/no question: <input v-model="question"> </p> <p>{{answer}}</p> </div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 --> <!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 --> <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script> <script> var watchExampleVM = new Vue({ el:'#watch-example', data:{ question:'', answer:'123abc' }, watch:{ //如果 `question` 发生改变,这个函数就运行 question:function(newQuestion,oldQuestion){ this.answer = "456efg", this.getAnswer() } }, methods:{ // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。 // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率 // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于 // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识, // 请参考:https://lodash.com/docs#debounce getAnswer: _.debounce( function () { if (this.question.indexOf('?') === -1) { this.answer = 'Questions usually contain a question mark. ;-)' return } this.answer = 'Thinking...' var vm = this axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function (error) { vm.answer = 'Error! Could not reach the API. ' + error }) }, // 这是我们为判定用户停止输入等待的毫秒数 500 ) } }); </script>
结果:
Ask a yes/no question:
I cannot give you an answer until you ask a question!
在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <div id="app1"> <!--reverse() 方法用于颠倒数组中元素的顺序。 split() 方法用于把一个字符串分割成字符串数组。--> {{ message.split('').reverse().join("") }} </div> <div id="app2"> <p>原始字符串:{{message}}</p> <p>计算后反转字符串:{{reversedMessage}}</p> </div> <div id="app3"> <p>原始字符串 :{{message}}</p> <p>计算后反转字符串:{{reversedMessage}}</p> <p>使用方法后反转字符串:{{reversedMessage2()}}</p> </div> <div id="app4"> <p>{{site}}</p> </div> <div id="computed_props"> 千米:<input type="text" v-model="kilometers"> 米:<input type="text" v-model="meters"> </div> <p id="info"></p> <div id="watch-example"> <p> Ask a yes/no question: <input v-model="question"> </p> <p>{{ answer }}</p> </div> </body> </html> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script> <script type="text/javascript"> new Vue({ el:"#app1", data:{ message:'Runoob!' } }); new Vue({ el:'#app2', data:{ message:'Runoob!' }, //计算属性 computed:{ //计算属性的getter reversedMessage:function(){ //this指向Vm实例 return this.message.split('').reverse().join("") } } }); new Vue({ el:'#app3', data:{ message:'Runoob!' }, computed:{ reversedMessage:function(){ return this.message.split("").reverse().join('') } }, methods:{ reversedMessage2:function(){ return this.message.split('').reverse().join('') } } }); var vm = new Vue({ el:'#app4', data:{ name:"Google", url:"http://www.google.com" }, computed:{ site:{ //getter get:function(){ return this.name + " " + this.url }, //setter set:function(newValue){ var names = newValue.split(' '); this.name = name[0]; this.url = names[names.length - 1] } } } }); // //调用setter,vm.name 和vm.url 也会被对应更新 // vm.site = '菜鸟教程 http://www.runoob.com'; // document.write('name:' + vm.name); // document.write('<br>'); // document.write('url:'+vm.url); // var vm = new Vue({ // el:'#computed_props', // data:{ // kilometers:0, // meters:0 // }, // methods:{}, // computed:{}, // watch:{ // kilometers:function(val){ // this.kilometers = val; // this.meters = val * 1000; // }, // meters:function(val){ // this.kilometers= val/ 1000; // this.meters = val; // } // } // }); // //$watch是一个实例方法 // vm.$watch('kilometers',function(newValue,oldValue){ // //这个回调函数将在vm.kilometers改变后调用 // document.getElementById('info').innerHTML = '修改前值为:' + oldValue +"修改后的值:" + newValue; // }) var watchExampleVM = new Vue({ el: '#watch-example', data: { question: '', answer: 'I cannot give you an answer until you ask a question!' }, watch: { // 如果 `question` 发生改变,这个函数就会运行 question: function (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing...' this.getAnswer() } }, methods: { // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。 // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率 // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于 // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识, // 请参考:https://lodash.com/docs#debounce getAnswer: _.debounce( function () { //indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。 if (this.question.indexOf('?') === -1) { this.answer = 'Questions usually contain a question mark. ;-)' return } this.answer = 'Thinking...' var vm = this axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function (error) { vm.answer = 'Error! Could not reach the API. ' + error }) }, // 这是我们为判定用户停止输入等待的毫秒数 500 ) } }) </script>
相关文章推荐
- Vue.js 基础示例
- vue.js基础-构造器
- vue.js原生组件化开发(一)——组件开发基础
- Node.js和vue-cli构建vueJS基础项目
- VUE.JS——组件基础
- vue.js基础
- Vue.js 运行环境搭建详解及vue、node基础知识普及
- vue.js 一(基础环境搭建)
- vue.js的使用总结(1)基础篇
- 快速上手Vue(适合懂基础html、css和js的人)
- vue.js--基础 数据的双向绑定
- VUE.JS——组件基础
- 半小时入门Vue.js基础
- vue.js基础-构造器
- Vue.js组件——组件的基础知识
- 最细致的vue.js基础语法 值得收藏!
- Vue.js 学习(3) -- 语法基础
- vue.js(基础篇3)
- vue.js,基础用法实例
- Vue.js基础