【Vue计算属性】

咱们都知道在Vue构造函数的参数对象中有一个【data】属性,该属性值是一个对象,该对象是对数据的代理,是一个键值对而且时刻与页面表现是一致的,可是这里面只能是简单的键值对,不能拥有业务逻辑,而且因为【data】中的属性属于同一个生命周期,因此若是咱们须要某一个属性是依赖于另一个属性时,在【data】中是作不到的,因而Vue为咱们提供了【计算属性】es6


1、计算属性

1.1 概述

计算属性归根结底也是属性,它也是跟表现层是时刻同步的,虽然咱们能够在插值中对数据进行各类处理,可是插值中的表达式处理毕竟只能用于简单的运算,不能拥有太多的业务逻辑。数据库

<body>
    <div id="app">
        <h1>{{name.toUpperCase()}}</h1>
        <!-- <h1>BLUE</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            name: 'blue'
        }
    })
</script>

上面代码是咱们熟悉的在插值中使用表达式,可是这里面咱们不能写入业务代码。数组

1.2 计算属性语法

在构造函数的参数对象中有一个【computed】属性,该属性就是用于定义计算属性的,该对象中的【键】也就是咱们的计算属性,与【data】不一样的是,计算属性的键值是一个【拥有返回值的函数】,该函数中能够访问到【data】中的全部属性。缓存

<body>
    <div id="app">
        <h1>{{rs}}</h1>
        <!-- <h1>BLUE LOVE PINK</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            hs: 'BLUE',
            wf: "PINK"
        },
        computed: {
            rs:function(){
                return `${this.hs} LOVE ${this.wf}`
            }
        }
    })
</script>

上面代码属性【rs】是定义的一个计算属性,该属性值是经过【data】中的两个属性值计算获得,返回一个拼接的字符串(这儿使用了ES6的【模板字符串】)而且当【data】中的相关值变化以后,【rs】属性都会进行从新计算。app

可能刚开始对计算属性会有些疑惑,好比上面的例子我把代码写成下面这样子也是能够的异步

<body>
    <div id="app">
        <h1>{{hs}} LOVE {{wf}}</h1>
        <!-- <h1>BLUE LOVE PINK</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            hs: 'BLUE',
            wf: "PINK"
        }
    })
</script>

上面的代码运行效果和咱们使用计算属性的效果是同样的,可是这样的写法只适用于简单的处理,【计算属性能够处理更复杂的业务逻辑】,好比咱们根据【data】中的一个属性值进行数据请求用于构建一个属性,咱们就必须使用计算属性了。函数

【注意!!】计算属性虽然是一个方法,可是在Vue内部会被翻译成一个属性,咱们可使用实例【vm.rs】访问到数据的。性能

1.3 计算属性和过滤器的比较

若是用于对【data】中【单个】属性的【简单】处理,推荐使用过滤器,可是若是一个值使用了【data】中至少2个值或者对一个值进行复杂处理,那么就推荐使用计算属性了。this

<body>
    <div id="app">
        <h1>{{hs | lover}}</h1>
        <!-- <h1>BLUE LOVE PINK</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            hs: 'BLUE',
        },
        filters: {
            lover(value){
                return `${value} LOVE PINK`
            }
        }
    })
</script>

上面代码就使用了一个【data】属性值作简单的处理,因此使用过滤器,并且也发现了过滤字符串“LOVE PINK”是不可变的。翻译

1.4 计算属性和Methods的比较

计算属性就是为了定属性的时候处理复杂的业务逻辑,并且在插值中咱们可使用表达式,那么咱们是否能够经过使用在插值中调用一个有返回值的函数呢?它和计算属性又有什么区别呢?

<body>
    <div id="app">
        <h1>{{rs}}</h1>
        <!-- <h1>EULB</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            name: 'BLUE',
        },
        computed: {
            rs: function () {
                return [...this.name].reverse().join('');
            }
        }
    })
</script>

上面代码将数据进行反向处理(使用了【ES6数组字符串扩展】),当咱们改变name的值的时候,计算属性【rs】会跟着改变。下面咱们将它改为一个方法结合插值表达式进行处理,看看区别。

<body>
    <div id="app">
        <h1>{{ rs() }}</h1>
        <!-- <h1>EULB</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            name: 'BLUE',
        },
        methods: {
            rs() {
                return [...this.name].reverse().join('');
            }
        }
    })
</script>

上面代码将计算属性改为了一个方法结合插值表达式,发现效果和计算属性没差异,改变name的值的时候页面也刷新了。那是否是这二者就真的没区别呢,答案固然是否认的,若是没有区别干吗还有计算属性的存在。

【计算属性是基于依赖进行缓存的】,只有计算属性的依赖发生改变时才会从新求值,也就是说若是依赖没有发生改变,那么计算属性会马上返回以前的计算结果,假如咱们有一个性能开销比较大的的计算属性 A ,它须要遍历一个极大的数组和作大量的计算。而后咱们可能有其余的计算属性依赖于 A 。若是没有缓存,咱们将不可避免的屡次执行 A 的 getter!若是你不但愿有缓存,请用 method 替代。

1.5 计算属性和Watch的比较

咱们发现计算属性会监听依赖,若是依赖发生变化则会重新计算属性,那么【监听器】也有这么一个功能,那么咱们应该在何时使用【计算属性】,何时使用【监听器】呢?

<body>
    <div id="app">
        <h1>{{fullName}}</h1>
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            firstName: 'Jack',
            lastName: 'Blue',
            fullName: 'Jack Blue'
        },
        watch: {
            firstName: function (val) {
                this.fullName = val + ' ' + this.lastName
            },
            lastName: function (val) {
                this.fullName = this.firstName + ' ' + val
            }
        }
    })
</script>

上面代码中咱们监听firstName和lastName用于构建fullName,效果很好,当firstName和lastName任意一个值改变的时候fullName都会随之改变。下面咱们看一下计算属性的写法

<body>
    <div id="app">
        <h1>{{fullName}}</h1>
        <!-- <h1>Jack Blue</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            firstName: 'Jack',
            lastName: 'Blue',
        },
        computed: {
            fullName() {
                return this.firstName + ' ' + this.lastName
            }
        }
    })
</script>

上面代码使用计算属性的方式进行了改造,fullName 依赖 firstName和 lastName 两个属性,当这两个属性任意一个发生变化,fullname都会从新进行计算。可是计算属性是否是简洁了不少呢!

【总结!!】当一个属性须要依赖多个【data】中的属性时,建议使用计算属性,若是咱们不是对属性进行操做,只是单纯的依据【data】中的某个值变化后作一些【非属性操做】时或者是在数据变化响应时,【执行异步操做或开销较大的操做】(好比:将变化后的值存入数据库,而不是改变其余属性)就使用Watch。

1.6 计算属性的setter

上面咱们是使用的计算属性都是用于对计算属性的取值,计算属性默认页只给了【getter】,可是在须要的时候咱们能够人为的添加【setter】

<body>
    <div id="app">
        <h1>{{fullName}}</h1>
        <!-- <h1>Jack Blue</h1> -->
    </div>
</body>

<script>
    let vm = new Vue({
        el: "#app",
        data: {
            firstName: 'Jack',
            lastName: 'Blue',
        },
        computed: {
            fullName: {
                //getter
                get() {
                    return this.firstName + ' ' + this.lastName
                },
                //setter
                set(newValue) {
                    var names = newValue.split(' ')
                    this.firstName = names[0]
                    this.lastName = names[names.length - 1]
                }
            }
        }
    })
</script>

上面代码定义了计算属性的一个setter,注意当须要定义setter的时候语法上面是有区别的。