Vue快速上手---computed和watch(四)

一、计算属性

概念:基于现有的数据,计算出来的新属性。 依赖的数据变化,自动重新计算。

例如,如果篮球数量变成2个,礼物总数会重新计算

语法:

① 声明在 computed 配置项中,一个计算属性对应一个函数

② 使用起来和普通属性一样使用  {{ 计算属性名 }}

计算属性 → 可以将一段 求值的代码 进行封装,如下所示

computed: {

  计算属性名 () {

    基于现有数据,编写求值逻辑

    return 结果

  }

},

代码举例

<div id="app">
    <h3>小黑的礼物清单</h3>
    <table>
      <tr>
        <th>名字</th>
        <th>数量</th>
      </tr>
      <tr v-for="(item, index) in list" :key="item.id">
        <td>{{ item.name }}</td>
        <td>{{ item.num }}个</td>
      </tr>
    </table>

    <!-- 目标:统计求和,求得礼物总数 -->
    <p>礼物总数:{{ totalCount }} 个</p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        // 现有的数据
        list: [
          { id: 1, name: '篮球', num: 2 },
          { id: 2, name: '玩具', num: 2 },
          { id: 3, name: '铅笔', num: 5 },
        ]
      },
      // 计算属性: 基于现有的数据计算得出的结果, 如果依赖数据发生变化会自动重新计算并渲染
      // 计算属性的语法: 本质是一个方法, 使用时当做属性来用
      computed: {
        totalCount() {
          // 必须要返回一个结果, 这个结果是基于现有的数据计算得来的
          // 计算属性的函数中也可以用 this 访问到实例对象
          return this.list.reduce((sum, item) => sum + item.num, 0)
        }
      }
    })
  </script>

computed 计算属性 vs methods 方法

computed 计算属性:

作用:封装了一段对于数据的处理,求得一个结果。

语法:

① 写在 computed 配置项中  

② 作为属性,直接使用 →   this.计算属性   {{ 计算属性 }}

methods 方法:

作用:给实例提供一个方法,调用以处理业务逻辑。

语法:

① 写在 methods 配置项中  

② 作为方法,需要调用   →   this.方法名( )   {{ 方法名() }}  @事件名="方法名"

computed计算属性很重要的特性:带缓存功能(提升性能):

首次计算后将结果缓存起来,后续如果有依赖的数据变化,就计算一次后继续缓存,多次访问只会计算一次,后面的几次都会从缓存中读取数据

如果依赖的数据更新,也会重新计算,然后重复上述操作

也就是控制台只会打印一次‘我是 computed 里的求和属性’,页面上会打印3次

    <h3>小黑的礼物清单<span>{{ totalCount }}</span></h3>
    <h3>小黑的礼物清单<span>{{ totalCount }}</span></h3>
    <h3>小黑的礼物清单<span>{{ totalCount }}</span></h3>
      computed: {
        totalCount () {
          console.log('我是 computed 里的求和属性')
          return this.list.reduce((sum, item) => sum + item.num, 0)
        }
      }

计算属性会对计算出来的结果缓存,再次使用直接读取缓存,

依赖项变化了,会自动重新计算 → 并再次缓存

计算属性完整写法

计算属性默认的简写,只能读取访问,不能 "修改"。如果要 "修改"  → 需要写计算属性的完整写法。

语法如下图所示

get翻译过来叫获取

set翻译过来叫设置

代码举例

 <div id="app">
    姓:<input type="text" v-model="firstName"> +
    名:<input type="text" v-model="lastName"> =
    <span>{{ fullName }}</span><br><br>

    <button @click="change">改名卡</button>
  </div>
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        firstName: '刘',
        lastName: '备',
      },
      methods: {
        // 需求: 点击改名卡, 将刘备修改成黄忠
        // 计算属性能不能修改? 简写形式是不能修改的, 因为函数无法被赋值成数据
        // 完整写法可以被赋值, 当计算属性被赋值时, 计算属性的 set 会执行
        change() {
          this.fullName = '赵云'
        }
      },
      computed: {
        // 简写:
        // fullName() {
        //   return this.firstName + this.lastName
        // }
        // 完整写法: 计算属性是一个对象
        // 对象中拥有两个方法: get / set
        // get 相当于就是以前的简写函数
        fullName: {
          // 计算属性被访问时, 自动执行 get 函数并返回结果
          // 必须有返回值
          get() {
            // console.log('我是 get 我执行了')
            return this.firstName + this.lastName
          },
          // 当计算属性被修改(赋值)时, 自动执行 set 函数, 并传入赋予的值
          // 参数来接收赋予的值
          set(val) {
            // console.log('我是 set 我执行了', val.substring(0, 1), val.substring(1))
             //substring(索引,截取几个)
            this.firstName = val.substring(0, 1)
            // Substring(1)不传第二个参数 代表截取到末尾,从索引为1开始,一直截取到末尾
            this.lastName = val.substring(1)
          }
        }
      }
    })
  </script>

执行原理:

修改了fullName,一旦修改了fullName,就会执行set()函数,它执行会把‘赵云’传到val里。然后我们 赵 赋值给firstName, 云 赋值给lastName,两个值一改,双向数据绑定,又会把值更新到imput这里,由于firstName和lastName改了,get函数检测到数据的变化,会执行get函数里的内容,重新计算,从而改变最最后的值

                                                         

二、 watch 侦听器

作用:监视数据变化,执行一些 业务逻辑 或 异步操作。

语法:

  • 简单写法  →   简单类型数据,直接监视

watch监听data里的数据,数据的属性名必须和data里的属性名同名(也就是words)

只能监听基本数据类型,如果需要监听引用数据类型 需要使用完整写法

      const app = new Vue({
        el: '#app',
        data: {
          obj: {
            words: ''
          }
        },
        // 具体讲解:(1) watch语法 (2) 具体业务实现
        watch: {
          // 监听 words 数据
          // words() {},
          // 1. 监听器的名字需要和数据名完全相同
          // 2. 当数据变化时自动执行该函数
          // 3. 如果数据是一个对象的属性, 可以把函数名定义成 => 对象.属性
          // 4. 侦听器有两个参数, 参数1 是新值, 参数2 是旧值
          // 绝大部分情况下旧值都不会使用, 仅使用新值即可
          'obj.words'(newVal, oldVal) {
            // console.log('words变了!')
            console.log(newVal, oldVal)
          }
        }
      })

业务实现

     <!-- 翻译框 -->
      <div class="box">
        <div class="input-wrap">
          <textarea v-model="obj.words"></textarea>
          <span><i>⌨️</i>文档翻译</span>
        </div>
        <div class="output-wrap">
          <div class="transbox">{{ result }}</div>
        </div>
      </div>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js"></script>
    <script>

      const app = new Vue({
        el: '#app',
        data: {
          obj: {
            words: ''
          },
          result: ''
        },
        // 具体讲解:(1) watch语法 (2) 具体业务实现
        watch: {
          // 监听 words 数据
          // words() {},
          // 1. 监听器的名字需要和数据名完全相同
          // 2. 当数据变化时自动执行该函数
          // 3. 如果数据是一个对象的属性, 可以把函数名定义成 => 对象.属性
          // 4. 侦听器有两个参数, 参数1 是新值, 参数2 是旧值
          // 绝大部分情况下旧值都不会使用, 仅使用新值即可
          async 'obj.words'() {
            // console.log('words变了!')
            // console.log(newVal, oldVal)
            // console.log(this.obj.words)
            const res = await axios({
              url: 'https://applet-base-api-t.itheima.net/api/translate',
              params: {
                words: this.obj.words
              }
            })
            // console.log(res.data.data)
            // 赋值过去就是渲染
            this.result = res.data.data
          }
        }
      })

  • 完整写法  →   添加额外配置项

比如:监听一整个对象

(1)  deep: true  对复杂类型深度监视 

(2)  immediate: true  初始化立刻执行一次handler方法

完整写法总结:

handler: 当数据变化时自动触发

deep: 开启深度侦听, 默认情况下只能监听基本数据类型, 必须开启它才能监听引用数据类型的变化

immediate: 初次进入页面自动触发一次

完整写法的案例:

 <div id="app">
      <!-- 条件选择框 -->
      <div class="query">
        <span>翻译成的语言:</span>
        <select v-model="obj.lang">
          <option value="italy">意大利</option>
          <option value="english">英语</option>
          <option value="german">德语</option>
        </select>
      </div>

      <!-- 翻译框 -->
      <div class="box">
        <div class="input-wrap">
          <textarea v-model="obj.words"></textarea>
          <span><i>⌨️</i>文档翻译</span>
        </div>
        <div class="output-wrap">
          <div class="transbox">{{ result }}</div>
        </div>
      </div>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js"></script>
<script>

      const app = new Vue({
        el: '#app',
        data: {
          obj: {
            words: '玖月吖',
            lang: 'english'
          },
          result: ''
        },
        // 具体讲解:(1) watch语法 (2) 具体业务实现
        watch: {
          // 对象不能使用简单写法来监视!
          // async obj() {
          // 如果想监视对象的变化, 必须使用完整写法
          // 默认情况下只有在数据变化时才会触发监听器的执行
          // 如果希望进入页面就执行一次函数, 可以再加一个配置: immediate: true
          
          obj: {
            immediate: true, // 初始化时触发一次
            deep: true, // 开启深度侦听, 可以监听引用类型
            // handler 会在数据变化时自动执行
            async handler() {
              // const { words, lang } = this.obj
              // console.log('obj 变了!')
              // console.log(newVal, oldVal)
              // console.log(this.obj.words)
              const res = await axios({
                url: 'https://applet-base-api-t.itheima.net/api/translate',
                params: this.obj
                // params: {
                //   words,
                //   lang
                // }
              })
              // console.log(res.data.data)
              // 赋值过去就是渲染
              this.result = res.data.data
            }
          }
        }
      })
    </script>

ps:翻译器不是真正的翻译器,没有翻译的功能,翻译的结果都不是正确的,这里主要是告诉大家watch的用法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值