Vue 计算属性和侦听器

本文通过购物车示例,介绍了Vue.js中计算属性与侦听器的使用方法及区别。展示了如何利用计算属性高效地计算总价格,以及如何使用侦听器响应数据变化并给出提示。

本文讨论一下计算属性和侦听器相关的用法
直接上代码

1. 计算属性

	<!-- HTML -->
	<div id="app">
        我的购物车:<br>
        <ul>
            <li v-for="(item, index) in cart" :key="index">
                商品名称:{{item.name}} 商品单价:{{item.price}} 商品库存:{{item.stock}}
                <input type="number" v-model="item.num">
            </li>
        </ul>
        总价:{{ calculateTotalPrice() }}
    </div>
	// JS
	<script>
	
        let app = new Vue({
            el: '#app',
            data: {
                cart: [
                	// stock表示库存
                    { name: '苹果手机', price: 1000, stock: 10, num: 1 },
                    { name: '小米手机', price: 500, stock: 10, num: 1 }
                ],
                text: 'test'
            },
            methods: {
            	// 使用函数来计算总价
                calculateTotalPrice() {
                    console.log('计算总价')
                    let totalPrice = 0;
                    this.cart.forEach(item => {
                        totalPrice += item.price * item.num
                    });
                    return totalPrice
                } 
            }
        })
        
    </script>

运行:
在这里插入图片描述
当然,总价的计算也可以通过计算属性来实现

	<!-- HTML -->
	<div id="app">
        我的购物车:<br>
        <ul>
            <li v-for="(item, index) in cart" :key="index">
                商品名称:{{item.name}} 商品单价:{{item.price}} 商品库存:{{item.stock}}
                <input type="number" v-model="item.num">
            </li>
        </ul>
        总价:{{ totalPrice }}  <!-- 注意计算属性是一个属性,不能像调用方法一样使用:totalPrice() -->
    </div>
	// JS
	<script>
	
        let app = new Vue({
            el: '#app',
            data: {
                cart: [
                    { name: '苹果手机', price: 1000, stock: 10, num: 1 },
                    { name: '小米手机', price: 500, stock: 10, num: 1 }
                ],
                text: 'test'
            },
           computed: {
           		// 计算属性
                totalPrice() {
                    console.log('计算属性重新计算数值')
                    let total = 0;
                    this.cart.forEach(item => {
                        total += item.price * item.num
                    });
                    return total;
                }
            }
        })
        
    </script>

计算属性和函数最大的区别是,只有当相关联的属性发生变化时,计算属性才会被重新计算,也就是说,在本例中,只有cart值发生变化,计算属性才会被重新计算。并且计算属性的值有缓存,取值时无需重复计算;对于函数,我们定义的data中的任意数据发生变化,如果导致节点刷新,函数都会重新执行(比如页面中使用了text属性,当修改了text属性值,此时节点需要刷新,计算总价的函数也会重新执行)。

2. 侦听器

我们想实现一个功能,在num超过stock时进行提示,先通过函数来实现

	<!-- HTML -->
	<div id="app">
        <br>
        我的购物车:<br>
        <ul>
            <li v-for="(item, index) in cart" :key="index">
                商品名称:{{item.name}} 商品单价:{{item.price}} 商品库存:{{item.stock}}
                <input type="number" v-model="item.num">
            </li>
        </ul>

        总价:{{ calculateTotalPrice() }}<br>
        
        <span v-html="refreshMessage()"></span>
    </div>
	// JS
	<script>
	
        let app = new Vue({
            el: '#app',
            data: {
                cart: [
                    { name: '苹果手机', price: 1000, stock: 10, num: 1 },
                    { name: '小米手机', price: 500, stock: 10, num: 1 }
                ],
                text: 'test',
                message: ''
            },
            methods: {
                calculateTotalPrice() {
                    console.log('执行计算函数');
                    let totalPrice = 0;
                    this.cart.forEach(item => {
                        totalPrice += item.price * item.num
                    });
                    return totalPrice;
                },
                refreshMessage() {
                    message = '';
                    this.cart.forEach(element => {
                        if(element.num > element.stock) {
                            message += `${element.name}超出库存了<br>`;
                        }

                    });
                    return message;
                }
            }
        })
        
    </script>

运行:
在这里插入图片描述
通过侦听器来实现信息提示

	<!-- HTML -->
	<div id="app">
        <br>
        我的购物车:<br>
        <ul>
            <li v-for="(item, index) in cart" :key="index">
                商品名称:{{item.name}} 商品单价:{{item.price}} 商品库存:{{item.stock}}
                <input type="number" v-model="item.num">
            </li>
        </ul>

        总价:{{ calculateTotalPrice() }}<br>

        <span v-html="message"></span>

    </div>
	// JS
	<script>
	
        let app = new Vue({
            el: '#app',
            data: {
                cart: [
                    // 
                    { name: '苹果手机', price: 1000, stock: 10, num: 1 },
                    { name: '小米手机', price: 500, stock: 10, num: 1 }
                ],
                text: 'test',
                message: ''
            },
            methods: {
                calculateTotalPrice() {
                    console.log('执行计算函数')
                    let totalPrice = 0;
                    this.cart.forEach(item => {
                        totalPrice += item.price * item.num
                    });
                    return totalPrice
                }
            },
            watch: {
            	// 非数组或对象的属性这样使用即可
                text(newValue, oldValue) {
                    console.log('watch text')
                    console.log(newValue, oldValue)
                },
                cart: {
                    handler(newValue, oldValue) {
                        console.log('watch cart')
                        this.message = '';
                        this.cart.forEach(element => {
                            if(element.num > element.stock) {
                                this.message += `${element.name}超出库存了<br>`;
                            }

                        });
                    },
                    // 注意:如果是侦听数组或者对象应该进行深度侦听.加上此属性
                    deep: true
                }
            }
        })
        
    </script>

注意,在此功能的实现上,使用函数和侦听器有一些差别。对于侦听器来说,只有当所侦听的数据发生变化时才会执行相应代码,如果初始化 cart 的时候,num就已经大于stock,并不会触发执行侦听器中的代码,因为数据并没有发生变化。如果使用函数来实现,初始时num大于stock,可正常触发提示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值