Vue学习笔记2:计算属性,及其简写形式

发布时间 2023-11-05 18:03:45作者: MyMemo

2. 计算属性,及其简写形式

data中的各项就是属性。
所谓计算属性,就是拿已经写好的属性去加工或计算,生成一个全新的属性。
计算属性在computed里,是一个对象。对象里可以有计算属性的getter和setter,他们都是function。与Object.defineProperty方法中的getter和setter是一样的,并且计算属性的底层实现使用的就是Object.defineProperty方法

vm实例身上有data中的各个属性,也有computed中的各个属性。而vm身上有的各个计算属性,在计算属性被取值时(通过vm.xxx取值)会调用计算属性的getter,然后会把getter返回的结果缓存在vm身上的计算属性(vm.xxx)上。

<!--准备好一个容器-->
<div id="root">
    姓:<input type="text" v-model="firstName" /><br /><br />
    名:<input type="text" v-model="lastName" /><br /><br />
    全名:<span>{{fullName}}</span>
</div>

当读取fullName时,Vue就会调用fullName的getter,并且Vue已经把getter内部的this指向调整为了vm实例
下图中,首次调用计算属性fullName的getter时做了一个环境,后续再使用该计算属性的时候都使用了缓存,而没有再调用其getter
如何用methods中的方法替代计算属性fullName,则在下图这种场景下就会被重复调用多次。而计算属性只被调用1次,其他重复使用计算属性的地方使用缓存即可

<!--准备好一个容器-->
<div id="root">
    姓:<input type="text" v-model="firstName" /><br /><br />
    名:<input type="text" v-model="lastName" /><br /><br />
    全名:<span>{{fullName}}</span><br /><br />
    全名:<span>{{fullName}}</span><br /><br />
    全名:<span>{{fullName}}</span><br /><br />
    全名:<span>{{fullName}}</span>
</div>
<script type="text/javascript">
    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        computed: {
            fullName: {
                //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                //get什么时候调用?1. 初次读取fullName时。 2. 所依赖的数据发生变化时
                get() {
                    console.log('get被调用了')
                    console.log(this) //此处的this就是vm
                    return this.firstName + '-' + this.lastName
                },
                set(value) {
                    console.log('set', value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            }

        }
    })
</script>

在data中写的属性,出现在vm身上的时候依然是属性;在methods中写的方法,出现在vm身上的时候依然是方法;
但是在computed中写的计算属性,计算属性都是一个个的对象,但是出现在vm身上的时候不是对象,而是一个通过Object.defineProperty方法注册上去的属性

修改fullName会调用它的setter方法,在setter内修改了firstName和lastName,即data内的属性发生了变化。这就会引发Vue重新解析模板,重新解析模板的时候,会把数据发生了变化的属性和计算属性更新到模板里。
计算属性的getter和setter都是被Vue管理的函数,所以只能写成普通函数的形式,因为普通函数内的this会指向Vue。而不能写成箭头函数(函数内的this会指向window)的形式。

总结

  1. 定义:要用的属性不存在,要通过已有属性计算得来
  2. 原理:底层借助了Object.defineproperty方法提供的getter和setter
  3. get函数什么时候执行?
    • 初次读取时会执行一次
    • 当依赖的数据发生改变时,会被再次调用
  4. 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
  5. 备注:
    • 计算属性最终会出现在vm上,直接读取使用即可。
    • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变

如果计算属性,只需要考虑读取,不需要考虑修改。则可以使用计算属性的简写形式

const vm = new Vue({
    el: '#root',
    data: {
        firstName: '张',
        lastName: '三'
    },
    computed: {
        fullName: {
            //完整写法
            //get() {
            //    console.log('get被调用了')
            //    console.log(this) //此处的this就是vm
            //    return this.firstName + '-' + this.lastName
            //},
            //set(value) {
            //    console.log('set', value)
            //    const arr = value.split('-')
            //    this.firstName = arr[0]
            //    this.lastName = arr[1]
            //}

            //简写形式1
            fullName: function () {
                console.log(this) //此处的this就是vm
                return this.firstName + '-' + this.lastName
            }

            //简写形式2
            fullName() {
                console.log(this) //此处的this就是vm
                return this.firstName + '-' + this.lastName
            }
        }

    }
})