2021.7.12 Vue学习笔记

211 阅读2分钟

计算属性

以姓名案例为例

目标需求:输入姓,名,页面自动输出全名,以'-'分隔

可用实现方法:

1.原生实现

let p = {
            firstname:'张',
            lastname:'三'
        }
    Object.defineProperty(p,'fullname',{
            set(value){
                const arr = value.split('-');
                this.firstname = arr[0];
                this.lastname = arr[1];
            },
            get(){ 
                return this.firstname + '-' + this.lastname;
            }
        })

当要追加的属性是由其他已有属性加工而来时,使用defineProperty方法。 defineProperty方法中,当fullname属性被调用,则触发get函数,当fullname属性被更改,则会触发set函数,通过设置set函数内部代码可以反过来改变原对象的属性。 Vue的源码中数据监测就是基于set和get函数。

2.插值方法

<div id="root">
        姓:<input type="text" v-model="firstname">
        名:<input type="text" v-model="lastname">
        <span>全名:{{firstname + '-' + lastname}}</span>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                firstname:'张',
                lastname:'三'
            }
        })
    </script>

当只需要计算全名显示全名时可以使用插值方法实现。

3.methods实现

<div id="root">
        姓:<input type="text" v-model="firstname">
        名:<input type="text" v-model="lastname">
        <span>全名:{{getFullName()}}</span>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                firstname:'张',
                lastname:'三'
            },
            methods:{
                getFullName(){
                    return this.firstname + '-' + this.lastname;
                }
            }
        })

4.Computed计算属性实现

const vm = new Vue({
            el:'#root',
            data:{
                firstname:'张',
                lastname:'三'
            },
            computed:{
                fullName:{
                    set(value){
                        const arr = value.split('-');
                        this.firstname = arr[0];
                        this.lastname = arr[1];
                        
                    },get(){
                        return this.firstname + '-' + this.lastname;
                    }
                }
            }
        })

如果只需要计算全名,那么可以将computed属性简写成 fullName(){return this.firstname + '-' + this.lastname;} 因为想要进一步实现更改全名同步改变姓或者名的功能,因此使用完整写法,即调用了set和get函数。其中set函数会获取到更改后的值。 注意:computed中的fullName属性是vm对象在调用,因此它的this指的都是Vue对象。

比较methods实现和computed实现:

通过methods实现时,全局数据只要发生一点变化,methods中的方法都会被调用一次。

而通过computed实现时,只有依赖的属性发生改变时,才会重新调用computed中的方法。 与methods相比,computed拥有缓存机制,效率更高。

数据监视

以姓名案例为例

姓名案例的watch实现

<div id="root">
        姓:<input type="text" v-model="firstname">
        <br><br>
        名:<input type="text" v-model="lastname">
        <br><br>
        <span>全名:{{fullname}}</span>
    </div>

    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                firstname: '张',
                lastname: '三',
                fullname: ''
            },
            watch: {
                firstname: {
                    immediate: true, //若immediate为true,则初始化时就会调用一次
                    handler(newValue, oldValue) {
                        this.fullname = newValue + '-' + this.lastname;
                    }
                },
                lastname(newValue, oldValue) {
                    this.fullname = this.firstname + '-' + newValue;
                }
            }
        })
    </script>

handler函数是完整写法,是为了可以添加immediate属性,使初始化时调用一次watch。如果不需要初始化调用,那么可以进行简写。

watch中的handler函数可以检测到对应数据的变化,并返回新值和旧值,这一点与computed很相似,但是computed中的set函数貌似无法返回旧值(?)总的来说,computed可以实现的功能watch都可以实现,但是watch可以实现的功能computed可能无法实现,比如watch可以异步完成(定时器),但是要注意,定时器的函数一定要写成箭头函数,否则函数内部的this会指向window。

watch可以被封装到Vue的外部,使用vm.$watch('属性',{}) 可以用来应对一开始没有决定监测哪个对象的情况。

Vue中一个很重要的原则:

所有被Vue管理的函数,都不要写箭头函数 例如:computed和watch中的函数。

所有不被Vue管理的函数,都要写箭头函数 --- 例如:定时器的回调,ajax的回调。