[TOC] >[success] # watch/computed/methods ~~~ 1.利用keyup键盘事件抬起改变,通过监听键盘抬起事件改变内容 2.利用watch 监听,监听的是属性,根据属性变更监听触发事件,所以watch中的方法名称对应属性名称 3.利用computed 属性重新计算,他就是一个方法,不过返回的是一个值, 他可以监听到他内部的属性改变,根据改变来决定计算属性是否重新执行返回, 延伸计算属性,可以赋值,但不建议具体用法见文档 4.当 {{}}里面出现了复杂的逻辑算法的时候可以考虑computed 5.在watch 和computed 中不要去更改监听的值最好,这样容易造成无限循 环的情况 6.watch 可以执行任何逻辑,如节流,ajax 异步数据,dom操作,计算属性 也能做ajax 但官方推荐在watch中 ,个人理解第一点计算属性在组件初始化 时候会运行一次,watch不会,很多场景的异步,我们都是想改变在触发, 不想页面加载触发,因此计算属性就变得鸡肋了 ~~~ >[danger] ##### 三者区别 ~~~ 1.computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计 算。主要当作属性来使用;只要依赖的内部监听的data改变, 计算属性会 再次计算一遍,但是在初始化的时候会计算一遍 2.methods方法表示一个具体的操作,主要书写业务逻辑methods为什么不 能作为算属性替代品,因为计算属性监听内容改变才重新计算,但methods 调用就算,如果大量使用对属性的重新赋值的地方会消耗性能。 3.watch一个对象,键是需要观察的表达式,值是对应回调函数。主要用来 监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作 是computed和methods的结合体;不会像computed 初始化计算,而是根据 使用者决定什么时候开始使用,默认新老数据不一样的时候 4.computed 和watch methods,前两者不用绑定事件执行,后者需要绑定 事件才能执行 ~~~ >[info] ## 同一个案例三种写法 ![](https://box.kancloud.cn/4ce3ff023bb409988a226bc086f4e148_558x54.png) >[danger] ##### 计算属性--computed ~~~ 1.在 computed 中,可以定义一些 属性,这些属性,叫做 【计算属性】, 计算属性的,本质,就是 一个方法,只不过,我们在使用 这些计算属性的 时候,是把 它们的 名称,直接当作 属性来使用的;并不会把 计算属性, 当作方法去调用;而且第一次使用就会执行,后续执行是根据计算内部值 变化才会变化因为内部的缓存机制 2.注意1: 计算属性,在引用的时候,一定不要加 () 去调用,直接把它 当作 普通 属性去使用就好了; 3.注意2: 只要 计算属性,这个 function 内部,所用到的 任何 data 中的数据发送了变化,就会 立即重新计算 这个 计算属性的值 4.注意3: 计算属性的求值结果,会被缓存起来,方便下次直接使用; 如果 计算属性方法中,所以来的任何数据,都没有发生过变化,则,不会重新对 计算属性求值; 5.注意4:当给v-model 绑定计算属性的时候,注意这时候我们想做的是既可 以赋值,又可以得到值,但是computed默认只能得到值也就是get,需要手 动添加set方法(具体见前面章节案例篇章中的多选) 6.必须return 返回 ~~~ ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="app"> <input type="text" v-model="firstname"> + <input type="text" v-model="middlename"> + <input type="text" v-model="lastname"> = <input type="text" v-model="fullname"> <p>{{ fullname }}</p> <p>{{ fullname }}</p> <p>{{ fullname }}</p> </div> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { firstname: '', lastname: '', middlename: '' }, methods: {}, computed: { 'fullname': function () { console.log('ok') return this.firstname + '-' + this.middlename + '-' + this.lastname } } }); </script> </body> </html> ~~~ >[danger] ##### watch -- 监听 ~~~ 1.watch 中的方法名对应的是data中的数据名称 2.官方文档案例中还提供了一个案例用来实现,监听用户输入的内容,去后 台查到对应信息的优化方法见'计算属性和侦听器'章节 3. 第一种使用(第一次渲染的时候不会执行) watch{ 要监听的data值:function(newVal, oldVal){ //newVal 变化的值,oldVal 变化之前的值 } } 4.如果想让watch 第一次就监听到内容使用immediate: true属性或者直接计 算属性(其中在handler方法中监听新旧值): watch:{ 要监听的data值:{ handler: function (val, oldVal) { /* ... */ }, immediate: true } } 5.如果想监听对象内部内容时候需要使用deep,因为对象是一个地址,内部 内容改变,但地址没变实际是监听不到的,所以需要deep : c: { handler: function (val, oldVal) { /* ... */ }, deep: true }, 这里要说明一下,比如现在在data中有一个对象类似obj:{a:"123"},但是我们 监听的是obj,实际上当我们改变obj.a的属性的时候,watch是监听不到的, 因此需要我们使用deep:true,但是deep会把这个对象中所有的key都进行, 绑定监听因此会浪费性能,建议如果只要监听一项可以写一个字串'obj.a'的 形式在watch中 ~~~ ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="app"> <input type="text" v-model="firstname"> + <input type="text" v-model="lastname"> = <input type="text" v-model="fullname"> </div> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { firstname: '', lastname: '', fullname: '' }, methods: {}, watch: { // 使用这个 属性,可以监视 data 中指定数据的变化,然后触发这个 watch 中对应的 function 处理函数 'firstname': function (newVal, oldVal) { // console.log('监视到了 firstname 的变化') // this.fullname = this.firstname + '-' + this.lastname // console.log(newVal + ' --- ' + oldVal) this.fullname = newVal + '-' + this.lastname }, 'lastname': function (newVal) { this.fullname = this.firstname + '-' + newVal } } }); </script> </body> </html> ~~~ >[danger] ##### methos -- 事件触发 ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="app"> <input type="text" v-model="firstname" @keyup="getFullname"> + <input type="text" v-model="lastname" @keyup="getFullname"> = <input type="text" v-model="fullname"> </div> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { firstname: '', lastname: '', fullname: '' }, methods: { getFullname() { this.fullname = this.firstname + '-' + this.lastname } } }); </script> </body> </html> ~~~ >[info] ## 更直观的看出computed的缓存机制 ~~~ 1.复制下面案例运行一下看看神奇,计算属性将不再更新,因为 Date.now () 不是响应式依赖 ~~~ ~~~html <!DOCTYPE html> <html lang="zh-cn"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <style> </style> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script> </head> <body> <!-- 验证计算属性是缓存的 --> <div id="app"> <input type='submit' value='切换我带你看计算属性缓存的强大' @click='isShow=!isShow' /> <div v-if='isShow'> 我是计算属性代表: {{CGetData}} <br /> 我是方法代表:{{MGetData()}} </div> <div v-else> 我是计算属性代表: {{CGetData}} <br /> 我是方法代表:{{MGetData()}} </div> </div> <script> var vm = new Vue({ el: '#app', data: { isShow: true, }, methods: { MGetData() { return Date.now() } }, computed: { CGetData() { return Date.now() } } }) </script> </body> </html> ~~~