Vue计算属性以及侦听器(七)

480 阅读3分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

计算属性

介绍

  1. 在Vue开发中,经常需要对项目中的属性进行一些js运算,如果将js运算代码直接插入到Vue的模板中会显得模板代码十分臃肿,并且插值语法内部不能使用if语句的。

  2. Vue为需要处理数据提供了一个新的配置选项,computed计算属性。写在当前计算属性函数内部的所有其他属性都会作为当前计算属性的依赖(计算属性会监听这些数据的变化)。

  3. 如果依赖不发生改变计算属性就不会重复执行,而是返回上一次计算属性执行后的值(计算属性的缓存)

基础例子

<div id="example">
      <p>{{ message.split('').reverse().join('') }}</p>
      <div>{{ message.split('').reverse().join('') }}</div>
</div>

message 字符串翻转代码直接插入到DOM节点中显得代码过于繁琐,并且不能复用导致代码想当的臃肿 解决方法: message属性 字符串的反转运算封装到计算属性中

<div id="example">
      <p>{{reverseMsg}}</p>
      <div>{{reverseMsg}}</div>
</div>

<script>
    new Vue({
        el: '#example',
        data: {
            message: 'Hello world'
        },
        computed: {
           reverseMsg() {
               return  this.message.split('').reverse().join('')
           } 
        }
    })
</script>

实现购买按钮的描述功能

 <div id="app">
    <button>{{payBtnText}}</button>
    <div>{{totalPrice}}</div>
    <div>{{fakedata}}</div>
</div>

<script>
   // 当 totalPrice 为 0 时,购买按钮显示 minPrice元起送
   // 当 totalPrice 大于 0 小于minPrice时,购买按钮显示  还差minPrice-totalPrice元起送
   // 当 totalPrice 大于等于 minPrice时,购买按钮显示  立即购买
   let vm =  new Vue({
        el: '#app',
        data: {
            minPrice: 25,
            totalPrice: 0,
            fakedata: true
        },
        computed: {

            payBtnText() {
                console.log("computed running")
                if(this.totalPrice <= 0 ) {
                    return `${this.minPrice}元起送`
                }else if(this.totalPrice < this.minPrice) {
                    return `还差${this.minPrice - this.totalPrice}元起送`
                }else {
                    return '立即购买'
                }
            }

        }
    })
</script>

计算属性的缓存

上面的计算属性功能使用methods也可以实现,但是为什么我们要使用计算属性呢?

因为计算属性会将当前计算属性函数内调用的所有 data其它计算属性 作为当前计算属性的依赖(当前计算属性会订阅 内部所有属性和其他计算属性变化).,如果依赖发生改变计算属性会自动的重新计算自身的值。

如果内部任何依赖都没有发生变化计算属性将不会执行器内部代码,只会返回上一次计算出的值(缓存上一次的值,若依赖发生改变则重新计算值,若没有改变则返回缓存值。

//下面的计算属性now如果str属性不发生改变的化,下面的计算属性将不再更新,
// 因为 Date.now() 不是响应式依赖
computed: {
  now: function () {
    return this.str + Date.now()
  }
}

相信大家都还记得我们之前的那个Todo案例(传送门)吧,今天搞个升级版哦,利用计算属性加个过滤的功能以及双击更换todo内容的功能。代码就不展示了哦,注释啥的都在代码里面,点击下方的链接查看。

[案例] todo带过滤.html

计算属性的setter

概念: 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter

语法:

计算属性名: {
    get(){return},
    set(val){}
}

栗子:

<div id="app">
    <p>姓: <input type="text" v-model="lastName"></p>
    <p>名: <input type="text" v-model="firstName"></p>

    <p>全名: <input type="text" v-model="fullName"></p>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            firstName: "小明",
            lastName: "李"
        },
        computed: {
            fullName: {
                get() {
                    return `${this.lastName} ${this.firstName}`
                },
                set(val) {
                    console.log(val)
                    let names = val.split(' ')
                    this.firstName = names[1]
                    this.lastName = names[0]
                }
            }
        }
    })
</script>

侦听器

概念: Vue提供了一个对当前实例属性侦听的配置选项,当前被侦听的属性发生改变时,对应侦听器绑定的callback函数就会被触发。

语法: watch:{侦听的属性名:callback(newValue, oldValue)}

  • 参数一:旧值 (oldValue)
  • 参数二:新值 (newValue)
<div id="app">
    <div>{{hours}}</div>
    <button @click="hours++">hours add</button>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            hours: 0
        },
        watch: {
            hours: function(newValue, oldValue) {
                if(newValue !== oldValue) {
                    if(newValue < 4) {
                        console.log('健康游戏时间')
                    }else if(newValue < 6) {
                        // alert(`你已经高强度网上冲浪${this.hours}`)
                        alert(`你已经高强度网上冲浪${newValue}小时请注意休息`)
                    }else {
                        alert(`强制下线`)
                    }
                }
            },
            ccc() {

            } 
        }
    })
</script>

watch.gif

注意: watch中的回调函数不能使用箭头函数,使用箭头函数会导致函数内的this不指向当前实例对象自身

结尾

今天就先到这里啦!我们下期再见!码字不易,觉得不错的可以动动小指头点点赞啥的哟~

系列文章

Vue系列

Vue-Router系列

Vuex系列