Skip to content

8.Vue方法、计算属性及监听器

在vue中处理复杂的逻辑的时候,我们经常使用计算属性、方法及监听器。

  1. methods:方法:它们是挂载在Vue对象上的函数,通常用于做事件处理函数,或自己封装的自定义函数。
  2. computed:计算属性:在Vue中,我们可以定义一个计算属性,这个计算属性的值,可以依赖于某个data中的数据。或者说:计算属性是对数据的再加工处理。
  3. watch:监听器:如果我们想要在数据发生改变时做一些业务处理,或者响应某个特定的变化,我们就可以通过监听器,监听数据的变化,从而做出相应的反应。

8.1.computed 计算属性

计算属性是根据依赖关系进行缓存的计算,并且只在需要的时候进行更新。

html
<div id="app">
    <p>原数据:</p>
    <p>新数据:</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            msg:'hello world!'
        },
        computed:{
            reversedMsg(){
                return this.msg.split('').reverse().join('');
            }
        }
    });
</script>

一个案例:根据商品数量修改总价

html
<div id="app">
    <table width="100%" style="text-align: center;">
        <tr>
            <th>商品编号</th>
            <th>商品名称</th>
            <th>商品单价</th>
            <th>商品数量</th>
            <th>合计</th>
        </tr>
        <tr>
            <td>1</td>
            <td>小米10</td>
            <td></td>
            <td>
                <button @click="subtract">-</button>

                <button @click="add">+</button>
            </td>
            <td></td>
        </tr>
    </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            price:2999,
            quantity:1
        },
        computed:{
            totalPrice(){
                return this.price*this.quantity;
            }
        },
        methods:{
            add(){
                this.quantity++;
            },
            subtract(){
                this.quantity--;
            }
        }
    });
</script>

8.2.methods 方法

在使用vue的时候,可能会用到很多的方法,它们可以将功能连接到事件的指令,甚至只是创建一个小的逻辑就像其他函数一样被重用。接下来我们用方法实现上面的字符串反转。

html
<div id="app" >
    <p>原数据: { { msg } } </p>
    <p>新数据: { { reversedMsg() } } </p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            msg:'hello world!'
        },
        methods:{
            reversedMsg(){
                return this.msg.split('').reverse().join('');
            }
        }
    });
</script>

虽然使用computed和methods方法来实现反转,两种方法得到的结果是相同的,但本质是不一样的。

计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变的时候才会重新求值,这就意味着只要message还没有发生改变,多次访问reversedMessage计算属性立即返回的是之前计算的结果,而不会再次执行计算函数。

而对于methods方法,只要发生重新渲染,methods调用总会执行该函数。

如果某个computed需要的遍历一个极大的数组和做大量的计算,可以减小性能开销,如果不希望有缓存,则用methods。

html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
		<script src="./js/vue.js"></script>

		
	</head>
	<body>
		<div id="app">
			<button @click="clickBtn"> 点我</button>
			<button @click="clickBtn(1)"> 点我2</button>
			
			年龄1 <input type="text" v-model="age1" />
			年龄2 <input type="text" v-model="age2" />
			<button @click="cal()"> 计算</button>
			{{ageSum}}
			
		</div>

		<script>
			
			let vm = new Vue({
				el: '#app',
				data: {
					age1:null,
					age2:null
			
				},
				methods:{
					clickBtn(val){
						alert('clickBtn\t'+val);
						
						this.mt();
					},
					mt(){
						alert("另外一个方法")
					},
					cal(){
						this.ageSum =  parseInt(this.age1) +parseInt(this.age2) ;
					}
				},
				computed:{
					ageSum(){
						return parseInt(this.age1) +parseInt(this.age2) ;
					}
				}
			});
		</script>

	</body>
</html>

s8.3.watch 监听器

watch能够监听数据的改变。监听之后会调用一个回调函数。 此回调函数的参数有两个:

  1. 更新后的值(新值)
  2. 更新前的值(旧值)

8.3.1.监听基本数据类型

下面使用watch来监听商品数量的变化。如果商品数量小于1,就重置成上一个值。

html
<div id="app">
    <table width="100%" style="text-align: center;">
        <tr>
            <th>商品编号</th>
            <th>商品名称</th>
            <th>商品单价</th>
            <th>商品数量</th>
            <th>合计</th>
        </tr>
        <tr>
            <td>1</td>
            <td>小米10</td>
            <td></td>
            <td>
                <button @click="subtract">-</button>

                <button @click="add">+</button>
            </td>
            <td></td>
        </tr>
    </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            price: 2999,
            quantity: 1
        },
        computed: {
            totalPrice() {
                return this.price * this.quantity;
            }
        },
        methods: {
            add() {
                this.quantity++;
            },
            subtract() {
                this.quantity--;
            }
        },
        watch:{
            quantity(newVal,oldVal){
                console.log(newVal,oldVal);
                this.quantity = newVal<=0?oldVal:newVal
            }
        }
    });
</script>

8.3.2.深度监听

在上面的例子中,监听的简单的数据类型,数据改变很容易观察,但是当需要监听的数据变为对象类型的时候,上面的监听方法就失效了,因为上面的简单数据类型属于浅度监听,对应的对象类型就需要用到深度监听,只需要在上面的基础上加上deep: true就可以了。

html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
		<script src="./js/vue.js"></script>


	</head>
	<body>
		<div id="app">
			<table width="100%" style="text-align: center;">
				<tr>
					<th>商品编号</th>
					<th>商品名称</th>
					<th>商品单价</th>
					<th>商品数量</th>
					<th>合计</th>
					<th>操作</th>
				</tr>
				<tr>
					<td>1</td>
					<td>小米10</td>
					<td>{{goods.price}}</td>
					<td>{{goods.quantity}}</td>

					<td>{{totalPrice}}</td>
					<td>
						<button @click="subtract">-</button>

						<button @click="add">+</button>
					</td>
				</tr>
			</table>
		</div>

		<script>
			let vm = new Vue({
				el: '#app',
				data: {
					price: 2999,
					quantity: 1,
					goods: {
						price: 2999,
						quantity: 1
					}
				},
				computed: {
					totalPrice() {
						return this.price * this.quantity;
					},
					deepQuantity(){
						return this.goods.quantity;
					}
					
					
				},
				methods: {
					add() {
						this.goods.quantity++;
					},
					subtract() {
						this.goods.quantity--;
					}
				},
				watch: {
					quantity(newVal, oldVal) {
						console.log(newVal, oldVal);
						this.quantity = newVal < 0 ? 0 : newVal
					},
					goods: {
						deep: true,
						handler:(newVal, oldVal)=> {
							//console.log(newVal, oldVal);
						}
					},
					deepQuantity(newVal, oldVal){
						console.log("侦听器=",newVal, oldVal);
					}
				}
			});
		</script>

	</body>
</html>

Released under the MIT License.