前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue 3 计算属性和侦听器

Vue 3 计算属性和侦听器

作者头像
公众号---人生代码
发布2020-11-03 16:47:21
6740
发布2020-11-03 16:47:21
举报
文章被收录于专栏:人生代码

计算属性和侦听器

实验介绍

我们都知道,模板内的表达式计算是非常便利的,但是如果涉及到非常复杂的计算方式,一个结算结果如果依赖很多个变量,就会变得难以维护了,所以计算属性就此应运而生了。

计算属性

我们还是之前的项目进行代码实验,还是在 src/views/TemplateM.vue 写代码,假如我们模拟数据有无效果,我们需要通过判断数据的数组的长度是否为 0 来展示不同的效果,如果为 0 我们提示暂无数据,如果数据不为 0 我们就展示数据:

代码语言:javascript
复制
<template>
  <div class="template-m-wrap">
    <div v-if="lists">
      <ul>
        <li :key="index" v-for="(item, index) in list">{{ item }}</li>
      </ul>
    </div>
    <div v-else>暂无数据</div>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      list: [],
    };
  },
  created() {
    let self = this;
    setTimeout(() => {
      self.getLists();
    }, 3000);
  },
  computed: {
    lists() {
      return this.list.length;
    },
  },
  methods: {
    getLists() {
      this.list = ["Ken", "coding", "投资", "谢教程"];
    },
  },
};
</script>

我们还是访问 http://localhost:8080/template_m,查看浏览器效果:

但是如果我们碰到更加复杂的情况,比如说上面这个计算属性如果依赖很多变量,最终计算出来的结果,如果我们直接在模板中计算,其实后期维护是很麻烦的,所以碰到这种需要做大量计算的变量,我们就直接使用计算属性。

代码语言:javascript
复制
computed: {
    lists() {
        return this.list.length;
    },
},

计算属性缓存 vs 方法

你可能会注意到去,其实我们也可以使用函数的方式调用:

代码语言:javascript
复制
<template>
  <div class="template-m-wrap">
    <div v-if="lists()">
      <ul>
        <li :key="index" v-for="(item, index) in list">{{ item }}</li>
      </ul>
    </div>
    <div v-else>暂无数据</div>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      list: [],
    };
  },
  created() {
    let self = this;
    setTimeout(() => {
      self.getLists();
    }, 3000);
  },
  methods: {
    lists() {
      return this.list.length;
    },
    getLists() {
      this.list = ["Ken", "coding", "投资", "谢教程"];
    },
  },
};
</script>

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的反应依赖关系缓存的。计算属性只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 this.list 还没有发生改变,多次访问 lists 计算属性会立即返回之前的计算结果,而不必再次执行函数。

我们还是访问 http://localhost:8080/template_m,查看浏览器效果,从效果上看没有丝毫的变化,但是从机制上看,确实有很大的区别:

计算属性的 Setter

上面说道缓存,我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 lists,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 lists。如果没有缓存,我们将不可避免的多次执行 lists 的 getter!如果你不希望有缓存,请用 method 来替代。

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

代码语言:javascript
复制
<template>
  <div class="template-m-wrap">
    firstName: <input type="text" v-model="firstName" />
    <br />
    lastName: <input type="text" v-model="lastName" />
    <br />
    {{fullName}}
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      firstName: "",
      lastName: "",
    };
  },
  computed: {
    fullName: {
      get() {
        return this.firstName + "" + this.lastName;
      },
      set(newVal) {
        const names = newVal.split(" ");
        this.firstName = names[0];
        this.lastName = names[names.length - 1];
      },
    },
  },
};
</script>

我们还是访问 http://localhost:8080/template_m,查看浏览器效果:

数据监听

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

代码语言:javascript
复制
<template>
  <div class="template-m-wrap">
    firstName: <input type="text" v-model="firstName" />
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      firstName: "",
    };
  },
  watch: {
      firstName(oldName, newName) {
          // 当 firstName 输入变化时,我们适当的做一些请求
          
      }
  }
};
</script>

计算属性 vs 监听器

Vue 提供了一种更通用的方式来观察和响应当前活动的实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。细想一下这个例子:

我们在 src/main.js 写下如下代码

代码语言:javascript
复制
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue' // 暂时注释这行代码
import router from './router'
import store from './store'

// createApp(App).use(store).use(router).mount('#app')
createApp({
    template: `<div id="demo">{{fullName}}</div>`,
    data() {
        return {
          firstName: 'Foo',
          lastName: 'Bar',
          fullName: 'Foo Bar'
        }
      },
      watch: {
        firstName(val) {
          this.fullName = val + ' ' + this.lastName
        },
        lastName(val) {
          this.fullName = this.firstName + ' ' + val
        }
      }
    
}).use(store).use(router).mount('#app')

我们还是访问 http://localhost:8080/template_m,查看浏览器效果:

上面代码是命令式且重复的。将它与计算属性的版本进行比较:

代码语言:javascript
复制
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue' // 暂时注释这行代码
import router from './router'
import store from './store'

// createApp(App).use(store).use(router).mount('#app')
createApp({
    template: `<div id="demo">{{fullName}}</div>`,
    data() {
        return {
          firstName: 'Foo',
          lastName: 'Bar',
          fullName: 'Foo Bar'
        }
      },
      computed: {
        fullName() {
          return this.firstName + ' ' + this.lastName
        }
      }    
}).use(store).use(router).mount('#app')

我们还是访问 http://localhost:8080/template_m,查看浏览器效果:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CryptoCode 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 计算属性和侦听器
    • 实验介绍
      • 计算属性
        • 计算属性缓存 vs 方法
          • 计算属性的 Setter
            • 数据监听
              • 计算属性 vs 监听器
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档