Vue的计算属性、侦听属性与过滤器解析


知识点

  • 计算属性
  • 计算属性中 getter 和 setter
  • 侦听属性
  • 计算属性与侦听属性对比
  • 过滤器的使用

计算属性

在开发中经常会涉及到一种需求,一个数据需要通过其他数据计算而来。例如:购物车,平常开发数据与数据关联计算是非常麻烦的,而 Vue 中的计算属性可以轻松帮你解决,可以像绑定普通属性一样在模板中绑定计算属性,可以直接使用{{}}向页面输出。

计算属性的基本使用

在实例的 computed 选项中定义你的计算属性,直接使用 {{}} 向页面输出。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p>我名字正着写:{{name}}</p>
      <!-- reverseName 计算属性  可以像绑定普通属性一样在模板中绑定计算属性-->
      <p>计算出我名字倒着写:{{reverseName}}</p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          name: "实验楼",
        },
        computed: {
          // reverseName 是一个计算属性
          reverseName: function () {
            return this.name.split("").reverse().join("");
          },
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

这里我们声明了一个计算属性 reverseName,你可以像绑定普通属性一样在模板中绑定计算属性。当你的计算属性的依赖数据发生改变时,你的相关计算属性也会重新计算。上面通过计算属性轻松地实现出展示名字倒着写,你也快看看,你名字倒过来是什么!

重点: 在 Vue 中计算属性是 惰性的,只有当依赖数据发生改变时,才会触发计算,否则,它的值是上一次触发计算的缓存值,下面例子很清楚说明,它是惰性的。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">{{now}}</div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {},
        computed: {
          now: function () {
            return Date.now();
          },
        },
      });
    </script>
  </body>
</html>

在你的理解中界面会一直时间更新,其实我们定义的 now 并没有和实例中数据建立响应式依赖,只是依赖 Date 对象获取系统时间,它只会计算一次,然后将值缓存,要使得他改变只有 刷新 才能触发,运行结果:
在这里插入图片描述

计算属性的 setter 和 getter

计算属性的 setter 和 getter 是它的高级使用,上面的例子只使用到它的 getter 属性,通过其他数据计算而得,其实我们也可以,直接赋值,通过计算属性来改变依赖数据的值。

下面例子我们通过触发计算属性 setter,改变原本关联数据。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p>firstName:{{firstName}}</p>
      <p>lastName:{{lastName}}</p>
      <p>全名是:{{fullName}}</p>
      <button v-on:click="changeName">改姓</button>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          firstName: "王",
          lastName: "花花",
        },
        methods: {
          // changeName 定义一个方法改变 计算属性 fullName 的值
          changeName: function () {
            // 修改计算属性 fullName 等于李花花
            this.fullName = "李花花";
            // 上面一句等于触发了 fullName 属性的 setter
          },
        },
        computed: {
          fullName: {
            // getter
            get: function () {
              return this.firstName + this.lastName;
            },
            // setter  直接改变计算属性 fullName 的值就可以触发 setter this.fullName='XX'
            set: function (newName) {
              var name = newName;
              this.firstName = name.slice(0, 1); // 取新值的第一个字符
              this.lastName = name.slice(1); // 从新值的第二个字符开始取值
            },
          },
        },
      });
    </script>
  </body>
</html>

侦听属性

在开发我们需要监听数据的变化,Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动,侦听属性。在实例 watch 选项中确定监听项。

下面这个例子,我们通过按钮点击改变 msg 的值,并且监听新旧值改变,并输出新旧值。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p>{{msg}}</p>
      <!-- v-on:click 简写为 @click -->
      <button @click="handleClick('hello syl')">改变msg</button>
    </div>

    <script>
      var app = new Vue({
        el: "#app",
        data: {
          msg: "hello",
        },
        methods: {
          // 改变 msg 的值
          handleClick: function (val) {
            this.msg = val;
          },
        },
        // watch 监听属性
        watch: {
          // 监听新旧值  监听属性有两个参数,第一个新值,第二个旧值
          msg: function (newVal, oldVal) {
            alert("新值" + newVal + "----" + "旧值" + oldVal);
          },
        },
      });
    </script>
  </body>
</html>

计算属性与侦听属性对比

计算属性和侦听属性两者在很多场景都是共同,都可以实现同样的需求。

我们使用侦听属性,改写计算属性例子:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p>firstName:{{firstName}}</p>
      <p>lastName:{{lastName}}</p>
      <p>全名是:{{fullName}}</p>
      <button v-on:click="changeName">改姓</button>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          firstName: "王",
          lastName: "花花",
          fullName: "王花花",
        },
        methods: {
          // changeName 定义一个方法改变  fullName 的值
          changeName: function () {
            this.fullName = "李花花";
          },
        },
        watch: {
          // fullName 侦听属性,监听 fullName 值的改变
          fullName: function (val) {
            var name = val;
            this.firstName = name.slice(0, 1);
            this.lastName = name.slice(1);
          },
        },
      });
    </script>
  </body>
</html>

过滤器

计算属性和侦听属性,在数据处理环节中很有作用,但是用它来处理数据过滤不是最优的,在 Vue 中我们有一个专门处理数据过滤的东西:过滤器。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持),用法示例:

<p>{{msg2|getString}}</p>
<p v-bind:class="msg2|getString"></p>

过滤器使用方法

在双花括号插值和 v-bind 表达式中把需要过滤的数据用 | 与过滤器分割 (data|filter)

例子:

使用 filters 过滤器实现大写转换和自动去除字符串中的数字。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <!-- toUpperCase   getString  为自定义的过滤器-->
      <p>小写转换大写:过滤前:{{msg}} 过滤后: {{msg|toUpperCase}}</p>
      <p>去除数字:过滤前:{{msg2}} 过滤后: {{msg2|getString}}</p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          msg: "hello",
          msg2: "1s2y3l",
        },
        // filters 过滤器选项
        filters: {
          // toUpperCase 定义一个字符串转大写的过滤器
          toUpperCase: function (val) {
            return val.toUpperCase();
          },
          // getString 定义一个获取去除数字的过滤器
          getString: function (val) {
            let newVal = "";
            val.split("").map(function (item) {
              if (9 >= item && item >= 0) {
                return;
              } else {
                return (newVal += item);
              }
            });
            return newVal;
          },
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

过滤器应用场景

应用比较多的商品价格过滤、表单数据过滤等。

我们从后台获取的数据一般是这样:

{ courseName:'xxx', price:199, coupon:8 }

我们请求到的数据并没有 ¥,在开发中直接去操作数据源是不推荐的,此时我们的过滤器就派上用场,定义一个拼接 ¥ 的过滤器,只是在视图层面实现了效果。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <!-- joint 为自定义的过滤器-->
      <p>不要¥899,只要{{price|joint}}</p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          // 后台价格数据
          price: 199,
        },
        // filters 过滤器选项
        filters: {
          // joint 定义 ¥ 拼接过滤器
          joint: function (price) {
            return "¥" + price;
          },
        },
      });
    </script>
  </body>
</html>

综合小练习

综合计算属性和过滤器,实现一个简易的购物车:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .price {
        font-size: 22px;
        color: brown;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <!-- joint 为自定义的过滤器-->
      <p>单价<span class="price">{{price|joint}}</span></p>
      数量:<input type="number" v-model="goodsNum" />
      <p>总价:<span class="price">{{allPrice|joint}}</span></p>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          goodsNum: 0,
          price: 199,
        },
        computed: {
          allPrice: function () {
            return this.goodsNum * this.price;
          },
        },
        // filters 过滤器选项
        filters: {
          // joint 定义 ¥ 拼接过滤器
          joint: function (price) {
            return "¥" + price;
          },
        },
      });
    </script>
  </body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值