之前的文章我们已经对 vue 有了初步认识, 这篇文章我们通过一个例子说一下 vue 的方法 methods, 计算属性 compited 和监听器 watch.
现在我们有一个需求, 变量 firstName = "hello", 变量 lastName = "world", 我们需要将这两个变量拼接到在前端展示, 最基本的我们可以想到的就是:
- <!DOCTYPE html>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- vue
- </title>
- <script src="https://cdn.jsdelivr.net/npm/vue">
- </script>
- </head>
- <body>
- <div id="app">
- <p>
- {{firstName + " " + lastName}}
- </p>
- <p>
- {{firstName}} {{lastName}}
- </p>
- </div>
- <script>
- var App = new Vue({
- el: '#app',
- data: {
- firstName: 'hello',
- lastName: 'world',
- },
- })
- </script>
- </body>
- </HTML>
以上两种写法很明显是可以这么做的, 但是第一种我们在 {{ }} 插值表达式内进行了代码的计算, 这是我们不建议使用方式, 第二种是写两个 {{ }} 插值表达式, 看起来效果不错, 但是如果我们要再拼接多个的话在 HTML 代码中就显得冗余了, 后期也不好维护. 接下来我们看一下如何在方法内实现:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- vue
- </title>
- <script src="https://cdn.jsdelivr.net/npm/vue">
- </script>
- </head>
- <body>
- <div id="app">
- <p>
- {{fullName()}} {{time}}
- </p>
- </div>
- <script>
- var App = new Vue({
- el: '#app',
- data: {
- firstName: 'hello',
- lastName: 'world',
- time: 1
- },
- methods: {
- fullName() {
- console.log("计算了一次");
- return this.firstName + " " + this.lastName
- }
- }
- })
- </script>
- </body>
- </HTML>
上面的代码我们在 methods 里定义了一个 fullName 的方法, 然后通过 {{ }} 插值表达式放在 HTML 里, 当页面加载的时候直接调用, 运行结果如下:
我们在页面加载的时候同时定义了一个 time 的数据, 当我们更新这个 time 数据的时候, 结果如下:
我们发现当我们更新 time 数据的时候, fullName 方法也调用了一次. 这显然不是很理想的.
我们再来看一下利用监听器 watch 方法:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- vue
- </title>
- <script src="https://cdn.jsdelivr.net/npm/vue">
- </script>
- </head>
- <body>
- <div id="app">
- <p>
- {{fullName}} {{time}}
- </p>
- </div>
- <script>
- var App = new Vue({
- el: '#app',
- data: {
- firstName: 'hello',
- lastName: 'world',
- fullName: 'hello world',
- time: 1
- },
- watch: {
- firstName() {
- console.log("firstName 更改了");
- this.fullName = this.firstName + " " + this.lastName;
- },
- lastName() {
- console.log("lastName 更改了");
- this.fullName = this.firstName + " " + this.lastName;
- }
- }
- })
- </script>
- </body>
- </HTML>
结果如下:
我们在 Vue 实例的 watch 属性里定义了两个方法 firstName 和 lastName,watch 属性中方法名和 data 属性里的数据变量名相同, 表示会实时监听该数据的变化, 如果监听到变化时会实时更新 DOM.
我们先来看一下当跟 methods 方法那样更新 time 数据时的变化:
我们可以看出当 time 数据更新时并没有调用 firstName 和 lastName 里的数据. 当我们更新 firstName 和 lastName 的数据时, 结果如下:
我们可以看出当我们更新 firstName 或者 lastName 的数据时, fullName 数据才会更新, 这说明当数据挂载到 DOM 上的时候回缓存起来, 如果数据不更新, 则还会继续使用缓存的数据, 当数据更新时才会调用 watch 里面的方法, 这就比 methods 的方法要好很多.
我们再来看一下计算属性 computed:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- vue
- </title>
- <script src="https://cdn.jsdelivr.net/npm/vue">
- </script>
- </head>
- <body>
- <div id="app">
- <p>
- {{fullName}} {{time}}
- </p>
- </div>
- <script>
- var App = new Vue({
- el: '#app',
- data: {
- firstName: 'hello',
- lastName: 'world',
- time: 1
- },
- computed: {
- fullName() {
- console.log("计算了一次");
- return this.firstName + " " + this.lastName;
- }
- }
- })
- </script>
- </body>
- </HTML>
运行结果如下:
我们可以看出跟 watch 比, 我们并没有在 data 里定义 fullName 数据, 而是在 computed 属性里直接定义 fullName 然后 return 出 firstName 和 lastName 的拼接结果, 当页面呈现时, 从输出结果可以看出会走一次计算属性, 当我们改变 time 数据时:
可以看出 computed 里的方法没有被调用, 当我们改变 firstName 或者 lastName 的数据时, 结果如下:
从上面的结果可以看出 computed 里面的方法被调用了, 这是我们想要的结果, 当跟 fullName 有关的 firstName 和 lastName 数据改变时计算属性才会重新计算, 当跟 fullName 无关的 time 数据变化时会用之前缓存的数据, 这正是我们想要的结果.
以上三种方法进行比较我们可以得知 methods 方法是最不理想的, 监听器 watch 和 计算属性 computed 两种方法的运行结果是一样的, 但是 计算属性 computed 方法更简单一些. 所以在 watch 和 computed 两种方法都能实现的时候我们更推荐使用 computed 方法.
但是上面的 watch 和 computed 两个方法里有个问题, 就是 watch 里我们在 data 里定义了一个 fullName 的数据, 当我们在更改 fullName 的值时 DOM 会跟着改变, 这个跟 firstName 和 lastName 数据更改是一样的. 但是当我们在 computed 里我们并没有定义 fullName, 当我们更改 fullName 的数据时, 如下:
我们发现 DOM 并没有更新, 这跟 watch 比起来就显得不友好了, 其实在 computed 里有 get 和 set 两个属性, 我们 computed 的 fullName 方法改成如下:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- vue
- </title>
- <script src="https://cdn.jsdelivr.net/npm/vue">
- </script>
- </head>
- <body>
- <div id="app">
- <p>
- {{fullName}} {{time}}
- </p>
- </div>
- <script>
- var App = new Vue({
- el: '#app',
- data: {
- firstName: 'hello',
- lastName: 'world',
- time: 1
- },
- computed: {
- fullName: {
- get() {
- console.log("计算了一次");
- return this.firstName + " " + this.lastName;
- },
- set(value) {
- console.log(value);
- var result = value.split(" ");
- this.firstName = result[0];
- this.lastName = result[1];
- }
- }
- }
- })
- </script>
- </body>
- </HTML>
运行结果如下:
可以看出当我们通过 get 和 set 就可以改变 fullName 的值使 DOM 更新了. 当页面更新的时候先触发 fullName 中的 get 方法, 并返回 fullName, 当我们改变 time 时, fullName 所依赖的 firstName 和 lastName 并没有更改, 所以就 fullName 就会去取缓存的值, 在 fullName 的 set 方法里可以传一个 value 的参数, 通过打印我们可以看出 value 值就是我们直接改变 fullName 的值, 我们就可以通过该值来赋值改变 firstName 和 lastName, 这样 fullName 所依赖的 firstName 或 lastName 改变时 DOM 就会实时更新了.
来源: https://www.cnblogs.com/weijiutao/p/10659690.html