计算属性 VUE的模板语法非常的方便,我们可以轻松地调用和计算数据,但是如果最终结果和依赖数据之间的关系复杂,直接使用模板语法使得代码易读性极具下降,这里我们借用一下官网的例子
1 2 3 <div id ="example" > {{ msg.split('').reverse().join('') }} </div >
如果我们想要在多个地方使用翻转后的字符串,那么这个冗长的代码就会出现在多个地方,这并不是我们所希望看到的
你可以会说可以使用函数,这确实是一个可行的途径
1 2 3 4 5 methods: { revMsg: function ( ) { return this .msg.split('' ).reverse().join('' ) } }
但是在每个位置我们都需要去调用这个函数,并且即使原字符串没有改变,还是要在函数内进行一次计算,为了节省计算时间,我们希望保存一个值,当原字符串变动的时候才调用函数计算更新这个值,ok,VUE提供了这个功能 —— 计算属性
计算属性可以缓存数据,会自动随着依赖数据改变而改变,当依赖数据没变化时,直接调用计算属性不会重复计算,而是直接得到缓存的值
计算属性的写法和methods完全一样,只是放在参数data对象的computed对象中,调用的时候直接写计算对象的名字即可,不需要像函数一样加括号
1 2 3 4 5 computed: { revMsg: function ( ) { return this .msg.split('' ).reverse().join('' ) } }
多重依赖 计算属性是允许多重依赖的,当其中一个依赖数据发生变化时,就会重新计算刷新缓存,举个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 var options = { el: "#app" , data: { xing: "张" , ming: "三" }, computed: { xingming: function ( ) { return this .xing + this .ming } } } var app = new Vue(options)
1 2 3 4 5 <div id ="app1" > 姓:<input type ="text" v-model ="xing" /> 名:<input type ="text" v-model ="ming" /> <h3 > 姓名:{{xingming}}</h3 > </div >
当我们修改姓或者名时,姓名这个计算属性就会刷新
计算属性的修改 有时候我们会有直接修改计算属性的需求,比如让用户直接输入姓名,然后系统拆解为姓和名,修改一下HTML做个试验
1 2 3 4 5 6 <div id ="app1" > 姓:<input type ="text" v-model ="xing" /> 名:<input type ="text" v-model ="ming" /> <h3 > 姓名:{{xingming}}</h3 > 姓名:<input type ="text" v-model ="xingming" /> </div >
当我们尝试在input中直接修改xingming
这个计算属性的时候会发现控制台有个报错
vue.js:634 [Vue warn]: Computed property “xingming” was assigned to but it has no setter.(found in )
意思是存在计算属性xingming
,但是没有setter
计算属性中有两个自带的方法,get和set,之前的写法默认是只有get,也就是只允许获取,不允许修改,如果想要计算属性可以修改,我们需要写一个set方法
实现方法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 computed: { xingming: { get: function ( ) { return this .xing + this .ming }, set: function (val ) { if (val) { this .xing = val[0 ] this .ming = val.slice(1 , val.length) } else { this .xing = "" this .ming = "" } } } }
这样我们修改xingming
这个计算属性,就可以发现依赖属性xing
和ming
也跟着变动了
监听 计算属性可以监听到依赖属性的变化,来改变属性值,也可以监听计算属性的变化来更新依赖属性,除此之外,VUE还提供了一个更通用的方法watch,来监听数据的变化,如果属性值发生变化,就执行对应的函数
举个简单的例子,我们在刚才那段代码的姓名显示dom上绑定一个style,然后监听xing
属性的变化来改变它的style
1 2 3 4 5 6 7 <div id ="app1" > 姓:<input type ="text" v-model ="xing" /> 名:<input type ="text" v-model ="ming" /> <h3 :style = "styleObj" > 姓名:{{xingming}}</h3 > 姓名:<input type ="text" v-model ="xingming" /> </div >
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 var options = { el: "#app" , data: { xing: "张" , ming: "三" , styleObj: { background: "skyblue" } }, computed: { xingming: { get: function ( ) { return this .xing + this .ming }, set: function (val ) { if (val) { this .xing = val[0 ] this .ming = val.slice(1 , val.length) } else { this .xing = "" this .ming = "" } } } }, watch: { xing: function ( ) { let red = parseInt (Math .random() * 255 ) let blue = parseInt (Math .random() * 255 ) let green = parseInt (Math .random() * 255 ) this .styleObj.background = `rgba(${red} ,${green} ,${blue} ,${Math .random()} )` } } }
我们发现每次改变xing
变量,都可以触发dom背景颜色的变化,包括xingming
这个计算属性的变化带动的xing
变量的变化
但是计算属性监听是无法达到理想的效果的,我尝试监听了一下xingming
这个计算属性,发现只能监听到xing
的变化,ming
的变化无法被监听到,也就是说只能watch变量
watch中的函数还有两个自带的参数 newValue
, oldValue
,记录了原值和修改后的值,我们可以通过如下方法来使用这两个参数
1 2 3 4 5 6 7 8 9 10 watch: { xing: function (newValue, oldValue ) { console .log(`${oldValue} ->${newValue} ` ) let red = parseInt (Math .random() * 255 ) let blue = parseInt (Math .random() * 255 ) let green = parseInt (Math .random() * 255 ) this .styleObj.background = `rgba(${red} ,${green} ,${blue} ,${Math .random()} )` } }