zoukankan      html  css  js  c++  java
  • 674 vue3侦听器watch

    认识侦听器watch


    侦听器案例


    01_侦听器的基本使用.html

    <!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">
        您的问题: <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>
    </body>
    </html>
    

    侦听器watch的配置选项



    02_侦听器的配置选项.html

    <!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">
        <h2>{{info.name}}</h2>
        <button @click="changeInfo">改变info</button>
        <button @click="changeInfoName">改变info.name</button>
        <button @click="changeInfoNbaName">改变info.nba.name</button>
      </template>
    
      <script src="../js/vue.js"></script>
      <script>
        const App = {
          template: '#my-app',
          data() {
            return {
              info: { name: "why", age: 18, nba: {name: 'kobe'} }
            }
          },
          watch: {
            // 默认情况下我们的侦听器只会针对监听的数据本身的改变(内部发生的改变是不能侦听)
            // info(newInfo, oldInfo) {
            //   console.log("newValue:", newInfo, "oldValue:", oldInfo);
            // },
    
            // 深度侦听/立即执行(一定会执行一次)
            info: {
              handler: function(newInfo, oldInfo) {
                // console.log("newValue:", newInfo, "oldValue:", oldInfo);
                // console.log(newInfo == oldInfo)
                console.log("newValue:", newInfo.nba.name, "oldValue:", oldInfo.nba.name);
              },
              deep: true, // 深度侦听
              immediate: true // 立即执行
            }
          },
          methods: {
            changeInfo() {
              this.info = {name: "kobe"};
            },
            changeInfoName() {
              this.info.name = "kobe";
            },
            changeInfoNbaName() {
              this.info.nba.name = "james";
            }
          }
        }
    
        Vue.createApp(App).mount('#app');
      </script>
    </body>
    </html>
    

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


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


    03_侦听器的其他方式.html

    <!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">
        <h2>{{info.name}}</h2>
        <button @click="changeInfo">改变info</button>
        <button @click="changeInfoName">改变info.name</button>
        <button @click="changeInfoNbaName">改变info.nba.name</button>
        <button @click="changeFriendName">改变friends[0].name</button>
      </template>
    
      <script src="../js/vue.js"></script>
      <script>
        const App = {
          template: '#my-app',
          data() {
            return {
              info: { name: "why", age: 18, nba: {name: 'kobe'} },
              friends: [{name: "why"}, {name: "kobe"}]
            }
          },
          watch: {
            "info.name": function(newName, oldName) {
              console.log(newName, oldName);
            },
            "friends[0].name": function(newName, oldName) {
              console.log(newName, oldName);
            }
          },
          methods: {
            changeInfo() {
              this.info = {name: "kobe"};
            },
            changeInfoName() {
              this.info.name = "kobe";
            },
            changeInfoNbaName() {
              this.info.nba.name = "james";
            },
            changeFriendName() {
              this.friends[0].name = "curry";
            }
          },
          created() {
            // 1.有返回值;2.info要用引号包裹。
            const unwatch = this.$watch("info", function(newInfo, oldInfo) {
              console.log(newInfo, oldInfo);
            }, {
              deep: true,
              immediate: true
            })
            // unwatch() // 调用返回值,会取消侦听
          }
        }
    
        Vue.createApp(App).mount('#app');
      </script>
    </body>
    </html>
    

    综合案例


    index.html

    <!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>
      <link rel="stylesheet" href="./style.css">
    </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.date}}</td>
                <td>{{formatPrice(book.price)}}</td>
                <td>
                  <button :disabled="book.count <= 1" @click="decrement(index)">-</button>
                  <span class="counter">{{book.count}}</span>
                  <button @click="increment(index)">+</button>
                </td>
                <td>
                  <button @click="removeBook(index)">移除</button>
                </td>
              </tr>
            </tbody>
          </table>
          <h2>总价格: {{formatPrice(totalPrice)}}</h2>
        </template>
        <template v-else>
          <h2>购物车为空~</h2>
        </template>
      </template>
    
      <script src="../js/vue.js"></script>
      <script src="./index.js"></script>
    
    </body>
    </html>
    

    index.js

    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: {
        // vue2: filter/map/reduce
        totalPrice() {
          let finalPrice = 0;
          for (let book of this.books) {
            finalPrice += book.count * book.price;
          }
          return finalPrice;
        },
        // Vue3不支持过滤器了, 推荐两种做法: 使用计算属性/使用全局的方法
        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) {
          this.books[index].count--
        },
        removeBook(index) {
          this.books.splice(index, 1);
        },
        formatPrice(price) {
          return "¥" + price;
        }
      }
    }).mount("#app");
    

    style.css

    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;
    }
    
    .counter {
      margin: 0 5px;
    }
    

  • 相关阅读:
    数据结构-栈
    virtualenvwrapper 的安装和使用
    MySQL命令行本地登陆,远程登陆MySQL 的快捷键
    关于mysql8授权的问题,mysql萌新小白采坑记录
    史上最直接小白式的Sourcetree的分支创建与合并
    验证两个集合是否相等的方法
    VS开发工具的常用插件
    C# 数据库并发的解决方案(通用版、EF版)
    Jquery实现div左右重复来回走动
    描述符的应用
  • 原文地址:https://www.cnblogs.com/jianjie/p/14793968.html
Copyright © 2011-2022 走看看