写点什么

Vue3: 认识侦听器 watch🔥

作者:渔戈
  • 2022-10-23
    广东
  • 本文字数:3684 字

    阅读完需:约 12 分钟

Hello,又见面了,我是渔戈!

今天我们来讲讲 Vue 的监听器:watch

1.什么是侦听器呢?

  • 开发中我们在 data 返回的对象中定义了数据,这个数据通过插值语法等方式绑定到 template 中

  • 当数据变化时,template 会自动进行更新来显示最新的数据

  • 但是在某些情况下,我们希望在代码逻辑中监听某个数据的变化,这个时候就需要用侦听器 watch 来完成了

1.1 侦听器的用法如下:

  • 选项:watch

  • 类型:{ [key: string]: string | Function | Object | Array}

1.2 侦听器案例

举个栗子:


比如现在我们希望用户在 input 中输入一个问题,每当用户输入了最新的内容,我们就获取到最新的内容,并且使用该问题去服务器查询答案;


那么,我们就需要实时的去获取最新的数据变化


<div id="app"></div>
<template id="my-app"> 您的问题: <input type="text" v-model="question"> <!-- <button @click="queryAnswer">查找答案</button> --> </template>
<script src="../js/vue.js"></script> <script> const App = { template: '#my-app', data() { return { // 侦听question的变化时, 去进行一些逻辑的处理(JavaScript, 网络请求) question: "Hello World", anwser: "" } }, watch: { // question侦听的data中的属性的名称 // newValue变化后的新值 // oldValue变化前的旧值 question: function(newValue, oldValue) { console.log("新值: ", newValue, "旧值", oldValue); this.queryAnswer(); } }, methods: { queryAnswer() { console.log(`你的问题${this.question}的答案是哈哈哈哈哈`); this.anwser = ""; } } }
Vue.createApp(App).mount('#app'); </script>
复制代码

2.侦听器 watch 的配置选项

  • 我们先来看一个例子:

  • 当我们点击按钮的时候会修改 info.name 的值;

  • 这个时候我们使用 watch 来侦听 info,可以侦听到吗?答案是不可以。

  • 这是因为默认情况下,watch 只是在侦听 info 的引用变化,对于内部属性的变化是不会做出响应的:

  • 这个时候我们可以使用一个选项 deep 进行更深层的侦听;

  • 注意前面我们说过 watch 里面侦听的属性对应的也可以是一个 Object;

  • 还有另外一个属性,是希望一开始的就会立即执行一次:

  • 这个时候无论后面数据是否有变化,侦听的函数都会有限执行一次

2.1 侦听器 watch 的配置选项(代码)

      watch: {        // 默认情况下我们的侦听器只会针对监听的数据本身的改变(内部发生的改变是不能侦听)        // info(newInfo, oldInfo) {        //   console.log("newValue:", newInfo, "oldValue:", oldInfo);        // }
// 深度侦听/立即执行(一定会执行一次) info: { handler: function(newInfo, oldInfo) { console.log("newValue:", newInfo.nba.name, "oldValue:", oldInfo.nba.name); }, deep: true, // 深度侦听 // immediate: true // 立即执行 } }
复制代码

2.2 侦听器 watch 的其他方式(一)

2.3 侦听器 watch 的其他方式(二)

  • 另外一个是 Vue3 文档中没有提到的,但是 Vue2 文档中有提到的是侦听对象的属性:



  • 还有另外一种方式就是使用 $watch 的 API:

  • 我们可以在 created 的生命周期(后续会讲到)中,使用 this.$watchs 来侦听;

  • 第一个参数是要侦听的源;

  • 第二个参数是侦听的回调函数 callback;

  • 第三个参数是额外的其他选项,比如 deep、immediate;


2.4 综合案例

  • 现在我们来做一个相对综合一点的练习:书籍购物车



  • 案例说明:


  1. 在界面上以表格的形式,显示一些书籍的数据;

  2. 在底部显示书籍的总价格

  3. 点击+或者-可以增加或减少书籍数量(如果为 1,那么不能继续-);

  4. 点击移除按钮,可以将书籍移除(当所有的书籍移除完毕时,显示:购物车为空~);


<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head>
<body> <div id="app"></div>
<template id="my-app">
<template v-if="books.length>0"> <table> <thead> <th>序号</th> <th>书籍名称</th> <th>出版日期</th> <th>价格</th> <th>购买数量</th> <th>操作</th> </thead> <tbody>
<tr v-for="(book,index) in books">
<td>{{index+1}}</td> <td>{{book.name}}</td> <td>{{book.data}}</td> <td>{{formaPrice(book.price)}}</td> <td> <button v-bind:disabled="book.count <=1 " @click="decrement(index)">-</button> <span class="counrer">{{book.count}}</span> <button @click="increment(index)">+</button> </td> <td> <button @click="removeBook(index)">移除</button> </td> </tr> </tbody> </table> <h2>总价格:{{formaPrice(totalPrice)}}</h2>
</template> <template v-else> <h2>购物车为空~</h2>
</template> </template>
<script src="../js/vue.js"></script> <script src="./index.js"></script> <link rel="stylesheet" href="./style.css"></body>
</html>
复制代码


Vue.createApp({    template: "#my-app",    data() {        return {            books: [                {                    id: 1,                    name: '《算法导论》',                    date: '2006-9',                    price: 85.00,                    count: 1                },                {                    id: 2,                    name: '《UNIX编程艺术》',                    date: '2006-2',                    price: 59.00,                    count: 1                },                {                    id: 3,                    name: '《编程珠玑》',                    date: '2008-10',                    price: 39.00,                    count: 1                },                {                    id: 4,                    name: '《代码大全》',                    date: '2006-3',                    price: 128.00,                    count: 1                },            ]        }
}, //计算属性: computed: { totalPrice() { let finalPrice = 0; for (let book of this.books) { finalPrice += book.count * book.price; } return finalPrice; }, //vue3不支持过滤器了,推荐两种做法:使用计算属性/使用全局的方法 或者使用添加method方法(如下面的formaPrice方法) filterBooks() { return this.books.map(item => { const newItem = Object.assign({}, item);//创建一个新的对象(防止修改数据,影响到后面总价格的统计) newItem.price = "¥" + item.price; return newItem; }) }
}, methods: { increment(index) { //通过索引值获取到对象 this.books[index].count++;
}, decrement(index) { //通过索引值获取到对象 if (this.books[index].count > 0) { this.books[index].count--; } }, removeBook(index) { this.books.splice(index, 1) }, formaPrice(price) { return "¥" + price; } }}).mount("#app");
复制代码


table {    border: 1px solid #e9e9e9;    border-collapse: collapse;    border-spacing: 0;
}
th,td { padding: 8px 16px; border: 1px solid #e9e9e9; text-align: left;}
th { background-color: #f7f7f7; color: #5c6b77; font-weight: 600;}
.counrer { margin: 0 5px;}
复制代码


案例效果:



相关文章:


原来Vue3的computed属性还能这么用啊🔥


邂逅Vue3


Vue3的基本指令

发布于: 刚刚阅读数: 3
用户头像

渔戈

关注

还未添加个人签名 2022-10-14 加入

还未添加个人简介

评论

发布
暂无评论
Vue3:认识侦听器watch🔥_Vue_渔戈_InfoQ写作社区