美文网首页Vue3.0+TSVue3
Vue3+TS Day04 - 基础指令 computed(计算

Vue3+TS Day04 - 基础指令 computed(计算

作者: 望穿秋水小作坊 | 来源:发表于2021-11-26 10:36 被阅读0次

    一、computed 计算属性

    1、如果 data 要进行复杂转换并在模板中展示,假设直接使用 mustach 语法会臃肿且难以维护,那怎么办呢?

    • 优雅的方式:使用计算属性
    image.png

    2、计算属性使用于什么场景?

    • 对于任何包含响应式数据的复杂逻辑,你都应该使用【计算属性】
    image.png

    3、分别使用 mustache、methods、computed 实现一份需求?

    image.png image.png image.png

    4、计算属性 vs methods 有什么优点?计算属性的缓存在什么时候会刷新?

    image.png image.png

    5、计算属性如何仅仅只写一个方法,默认是 getter,那么它的完整写法是什么?

    • 简写代码如下:
    computed: { 
        fullName() {
                    console.log("computed getFullName")
                    return this.firstName + this.lastName;
                }
            }
    
    • 完整写法如下:
            // 计算属性,使用起来比较优雅,而且能提升性能
            computed: { 
                fullName: {
                    get : function() {
                        console.log("computed getFullName")
                        return this.firstName + this.lastName;
                    }
                }
            },
    

    6、从源码的角度,看一下 Vue 对 computed 属性的解析过程,理解也就更加深刻

    image.png image.png

    二、 watch 侦听器

    1、什么情况下会需要使用侦听器?

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

    2、默认情况下,侦听器只会监听数据本身的改变(数据内部发送的改变是不能被监听到的)对吗?怎么办?

    • 借助 【deep】配置选项,进行深度监听
    image.png

    3、默认情况下,侦听器需要 data 后面值改变了才会生效,如果需要侦听器一进入页面就生效怎么办?

    • 借助 【immediate】 配置可选性即可
    image.png
                data: function () {
                    return {
                        question: "Hello World",
                        person: {
                            firstName: "Kobe",
                            lastName: "Bryant",
                            score: 80,
                        }
                    }
                },
                watch: {
                    person: {
                        handler: function (newValue, oldValue) {
                            console.log("newValue=", newValue, "  oldValue=", oldValue);
                        },
                        deep: true,
                        immediate: true
                    }
                },
    

    4、如果内部数据监听,即使是深度监听,也会出现下图的问题,就是【新值】和【旧值】相同的问题,为什么呢?

    image.png
    • 因为是同一个对象,【新值】和【旧值】指向同一块内存区域,所以无法拿到【旧值】
    • 也可以理解为是浅拷贝的问题

    5、侦听器 watch 的一些其他写法(了解即可)

    image.png image.png
    • $watch 的写法,好处就是可以拿到返回值,在需要的时候进行【取消监听】

    6、侦听器还可以监听对象的某一属性值,那么可以解决上述遇到的【新值===旧值】的问题吗?

    • 可以,监听复杂对象内的具体值,是可以拿到新值和旧值的
    image.png

    三、 综合案例

    1、综合案例需求描述?

    image.png

    2、代码实现?

    • 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;
    }
    
    

    相关文章

      网友评论

        本文标题:Vue3+TS Day04 - 基础指令 computed(计算

        本文链接:https://www.haomeiwen.com/subject/qsdatrtx.html