计算属性

208 阅读3分钟

计算属性

把computed中的方法当做属性使用,方法会返回一个数据,用方法名就可以使用返回的数据。使用时不需要跟调用的小括号,所以不用传参在计算属性中用this来获取数据源中的数据然后会自动对获取的数据进行处理然后直接将返回的数据当作创建的Vue实例的属性来使用。

计算属性的用法就是在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。

new Vue({
	el:"",//关联界面元素
	data:{},//vm的数据源
	methods:{},//方法
	filters:{yy(){}},//过滤器
	computed:{xx(){}} //xx就是一个计算属性
	
})

计算属性的第1种用法

刷新页面会对模板重新渲染,模板中的变量会重新取值。响应式数据,只要数据改变了就会刷新页面了然后重新渲染,但是数据多次改变只会取最后一次改变的值然后将最后一次的数据渲染在页面上,所以数据多次改变页面也只会刷新渲染最后一次改变的数据。

<div id="app">
        <p>methods---{{age1(birth)}}</p>
        <p>computed----{{age}}</p>
        <p>{{msg}}</p>
        <button @click="change">改变数据刷新页面</button>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                birth:"1996-03-11",
                msg:"jzx"
            },
            methods: {
                change(){
                    this.msg="maomao";
                },
                age1(str){
                    console.log("methods方法,111");
                    return new Date().getFullYear()-new Date(str).getFullYear();
                }
            },
            computed:{
                age(){
                    console.log("computed计算属性,222");
                    return new Date().getFullYear()-new Date(this.birth).getFullYear();
                }
            }
        });

image.png

image.png

计算属性会将返回的数据缓存,然后会监听计算属性中使用到的数据源中的数据是否发生改变,若该数据发生了改变就会重新运行计算属性中的函数,但是该数据没有改变就不会重新运行函数。即使数据源中的其他数据发生了改变导致刷新页面也不会再次运行计算属性中的函数。

new Vue({
            el:"#app",
            data:{
                birth:"1996-03-11",
                msg:"jzx"
            },
            methods: {
                change(){
                    this.msg="maomao";
                },
                change1(){
                    this.birth="1989-05-30";
                },
                age1(str){
                    console.log("methods方法,111");
                    return new Date().getFullYear()-new Date(str).getFullYear();
                }
            },
            computed:{
                age(){
                    console.log("computed计算属性,222");
                    return new Date().getFullYear()-new Date(this.birth).getFullYear();
                }
            }
        });

image.png

计算属性的第2种用法

其实第1种用法就是默认只用了get方法来读取一个计算属性,绝大多数的情况都是直接使用默认的简写写法,不必将get和set都声明。

//计算属性第二种用法
xx:{
    set(oldvalue){},
    get(){}
}
//对xx属性存值时就会执行set函数,取值时就会执行get函数
    <div id="app">
        <p v-show="fullname.first">{{name}}</p>
        <button @click="showname">点击显示名字</button>
    </div>
    <script>
        new Vue({
            el: "#app",
            data: {
                firstName: 'jung',
                lastName: 'jessica',
                fullname:[]
            },
            methods: {
                showname(){
                    this.name={first:this.firstName,last:this.lastName};
                }
            },
            computed:{
                name:{
                    // 存值时调用
                    set(value){
                        this.fullname=value;
                    },
                    // 取值时调用
                    get(){
                        console.log(this.fullname);
                        return this.fullname.last+"-"+this.fullname.first;
                    }
                }
            }
        });
    </script>

image.png

name存值会执行set函数,则fullname存的值就是一个对象,最终显示在页面上的值却不是一个对象。

一个购物车小案例

    <style>
        .shopbox {
            width: 800px;
            display: flex;
            justify-content: flex-start;
            flex-wrap: wrap;
        }

        .goodsbox {
            width: 370px;
            display: flex;
            justify-content: flex-start;
        }

        img {
            width: 100px;
        }

        input {
            width: 50px;
        }
    </style>
    <div id="shopcar">
        <div class="shopbox">
            <div class="goodsbox" v-for="(el,index) in this.goods">
                <div>
                    <img :src="el.img">
                </div>
                <div>
                    商品名称:<p>{{el.name}}</p>
                    <p>商品价格:{{el.price}}</p>
                    <div>
                        <button  @click="add(index)">+</button>
                        <input type="text" :key="el.id" v-model="el.count">
                        <button @click="minus(index)">-</button>
                    </div>
                </div>
            </div>
        </div>
        <p style="color: gold;" v-if="goods.length">购物车总价:{{total}}元</p>
        <p v-if="!goods.length">购物车中无商品,请添加商品</p>
    </div>
    <script>
        new Vue({
            el: "#shopcar",
            data: {
                goods: [
                    { id: 1, name: "SARDINIA (Light Blue & Ivory)", price: 61, img: "img/maozi1.jpg", count: 0 },
                    { id: 2, name: "SARDINIA (Red & Ivory)", price: 61, img: "img/maozi2.jpg", count: 0 },
                    { id: 3, name: "NORAH (Black)", price: 67, img: "img/maozi3.jpg", count: 0 },
                    { id: 4, name: "CAROL (Black)", price: 70, img: "img/baobao.jpg", count: 0 },
                    { id: 5, name: "MINIMAL", price: 22.5, img: "img/iphon1.jpg", count: 0 },
                    { id: 6, name: "MYSTERIOUS", price: 24.5, img: "img/ipon2.jpg", count: 0 },
                ]
            },
            methods: {
                add(index){
                    // 通过数组下标改变数据不会刷新页面,没有劫持数组下标
                    this.goods[index].count++;
                    // Vue.set会强制刷新页面
                    Vue.set(this.goods,index,this.goods[index]);
                },
                minus(index){
                    // 数组为空直接返回函数
                    if(this.goods.length==0){
                        // 改变数据刷新页面
                        this.goods=[];
                        return;
                    }else{
                        // 数组不为空当商品数量减少到小于0个就移除商品,商品从页面上消失
                        this.goods[index].count--;
                        if(this.goods[index].count==-1){
                            // 从index下标位置删除一个元素
                            this.goods.splice(index,1);
                        }
                    }
                }
            },
            computed: {
                total() {
                    // 计算总价
                    return this.goods.reduce((n1, n2) => {
                        return n1 + n2.price * n2.count;
                    }, 0);
                }
            }
        });
    </script>

什么是计算属性

计算属性就是处理数据源中的数据然后用于渲染而且会监听计算属性中使用到的数据源然后把计算的结果缓存,如果监听的数据源发生了变化才会重新计算,否则直接使用缓存的数据。

缺点:如果简单的运算也用计算属性,反而会增加资源消耗因为计算属性会去监听计算的值而且会缓存计算的结果,比如生日转年龄时,可以用过滤器或者方法实现。所以在复杂计算的时候比如购物车中算多个商品的总价就可以使用计算属性就不会因为某个其他数据发生改变而重新在运行一次函数。计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约系统开销。

计算属性和方法的区别

计算属性会把使用到的data中的属性缓存起来,防止页面发生大量重复计算,提升js 运行效率,如果计算属性中使用到的data中那部分数据变了才会重新调用计算属性,如果不是计算属性中的数据发生变化模板会重新渲染。methods方法不会将计算结果缓存起来,data任何数据发生改变,方法都会被重新调用一遍。方法常常是作为事件使用,计算属性常常是动态计算结果时使用