Vue 0基础学习路线(5)—— 图解深度详述Vue.js计算属性computed和监视器watch及详细案例(附详细案例代码解析过程及版本迭代过程)

1. Vue.js计算属性和watch重点提炼

  • computed
    • 派生数据
    • 缓存特性
    • get
    • set
  • watch
    • 异步的派生数据
    • . 语法: ‘a.b.c’
    • deep

2. 引例

在用户列表中筛选性别:

根据性别,对数据进行过滤,显示出用户想看到的数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <label><input type="radio" v-model="gender" value="" @change="changeGender" /> 所有</label>
    <label><input type="radio" v-model="gender" value="" @change="changeGender" /></label>
    <label><input type="radio" v-model="gender" value="" @change="changeGender" /></label>

    <hr>

    <ul>
        <li v-for="user of users">
            {{user.username}}
        </li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>


    let users = [
        {id: 1, username: 'zs', gender: '男'},
        {id: 2, username: 'ls', gender: '男'},
        {id: 3, username: 'xm', gender: '男'},
        {id: 4, username: 'ww', gender: '男'},
        {id: 5, username: 'xh', gender: '女'},
        {id: 6, username: 'xl', gender: '女'}
    ];
    let app = new Vue({
        el: '#app',
        data: {
            gender: '',
            users
        },
        methods: {
            changeGender() {
                console.log(this.gender);
                this.users = this.users.filter( user => user.gender === this.gender );
            }
        }
    });

</script>

</body>
</html>

因为改了原有的数据,所以程序数据挂了。操作数据,尽量别修改原数据,原数据进行备份。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.69
Branch: branch02

commit description:a0.69(引例——直接修改原始数据的巨大风险)

tag:a0.69

2.1 example01

2.1.1 example01-1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <label><input type="radio" v-model="gender" value="" @change="changeGender" /> 所有</label>
    <label><input type="radio" v-model="gender" value="" @change="changeGender" /></label>
    <label><input type="radio" v-model="gender" value="" @change="changeGender" /></label>

    <hr>

    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>


    let users = [
        {id: 1, username: 'zs', gender: '男'},
        {id: 2, username: 'ls', gender: '男'},
        {id: 3, username: 'xm', gender: '男'},
        {id: 4, username: 'ww', gender: '男'},
        {id: 5, username: 'xh', gender: '女'},
        {id: 6, username: 'xl', gender: '女'}
    ];
    let app = new Vue({
        el: '#app',
        data: {
            gender: '',
            users,  // 原始数据
            showUsers: users  // 过滤后的显示数据
        },
        methods: {
            changeGender() {
                console.log(this.gender);
                if (this.gender === '') {
                    this.showUsers = this.users;
                } else {
                    this.showUsers = this.users.filter( user => user.gender === this.gender );
                }
            }
        }
    });

</script>

</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.70
Branch: branch02

commit description:a0.70(example01-1——备份数据并保留原始数据)

tag:a0.70

2.1.2 example01-2

radio换成按钮会出一些问题。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <button @click="changeGender('')">所有</button>
    <button @click="changeGender('')"></button>
    <button @click="changeGender('')"></button>

    <hr>

    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>


    let users = [
        {id: 1, username: 'zs', gender: '男'},
        {id: 2, username: 'ls', gender: '男'},
        {id: 3, username: 'xm', gender: '男'},
        {id: 4, username: 'ww', gender: '男'},
        {id: 5, username: 'xh', gender: '女'},
        {id: 6, username: 'xl', gender: '女'}
    ];
    let app = new Vue({
        el: '#app',
        data: {
            users,
            showUsers: users
        },
        methods: {
            changeGender(gender) {
                console.log(gender);
                if (gender === '') {
                    this.showUsers = this.users;
                } else {
                    this.showUsers = this.users.filter( user => user.gender === gender );
                }
            }
        }
    });

</script>

</body>
</html>

我们发现点一次执行一次,哪怕数据不发生任何变化。即根据某个数据的变化,过滤得到一组新的数据,如果使用函数调用这样的方式去处理,无论过滤的条件是否发生改变(无论过滤的出来的数据是否改变),该函数都会被调用。照样还执行整个流程,这样的逻辑,如果代码庞大的话,势必损失很多性能。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.71
Branch: branch02

commit description:a0.71(example01-2——备份数据并保留原始数据,原生调用函数方式产生的问题)

tag:a0.71

那这种问题如何解决呢?为了解决该问题,vue提供了一个概念:计算属性

3. computed

在实际的应用中,我们会有一些原始数据,同时在应用中又会有一些数据是根据某些原始数据派生出来的,针对这样的一种情况,vue 定义了一个专门用来处理这种派生数据的选项:computed

/**
 * 派生数据(有以下需求考虑计算属性)
 *   - 有原始的数据
 *   - 有过滤的条件
 *   - 需要缓存结果
 */
<div id="app">
  <label><input type="radio" v-model="gender" value="" /> 所有</label>
  <label><input type="radio" v-model="gender" value="" /></label>
  <label><input type="radio" v-model="gender" value="" /></label>
  <hr>
  <ul>
    <li v-for="user of showUsers">
      {{user.username}}
    </li>
  </ul>
</div>
let app = new Vue({
  el: '#app',
  data: {
    gender: '',
    users: [
        {id: 1, username: 'zs', gender: '男'},
        {id: 2, username: 'ls', gender: '男'},
        {id: 3, username: 'xm', gender: '男'},
        {id: 4, username: 'ww', gender: '男'},
        {id: 5, username: 'xh', gender: '女'},
        {id: 6, username: 'xl', gender: '女'}
    ]
  },
  computed: {
    showUsers() {
      return this.gender === '' ? [...this.users] : this.users.filter(user=>user.gender===this.gender);
    }
  }
});
  • 计算属性类似 gettersetter ,当访问某个计算属性的时候,就会调用 computed 中同名的函数,函数的返回值将作为该计算属性的值
  • 计算属性的值依赖计算函数中依赖的其它响应式数据
  • 计算属性的值可以缓存,如果依赖的其它响应式数据没有发生变化,但多次访问该计算属性,得到结果是最近一次变化产生的值(相对于调用方法得到结果在某些时候性能要好一些)
<div id="app">
  <p>{{now}}</p>
  <button @click="showDate=true">showDate</button>
  <p v-if="showDate">{{now}}</p>
</div>
let app = new Vue({
  el: '#app',
  data: {
		showDate: false
  }
  computed: {
    now() {
      return Date.now();
    }
  }
});

3.1 计算属性的 gettersetter

默认情况下,计算属性函数是一个 getter 函数,如果计算属性只有 get 需求,则可以简写

computed: {
  now() {
    return Date.now();
  }
  // 等于
  now: {
    get() {
      return Date.now();
    }
  }
}

但是有的时候,这种派生数据既有 get 需求,也有 set 需求

<div id="app">
  <label><input type="radio" v-model="gender" value="" /> 所有</label>
  <label><input type="radio" v-model="gender" value="" /></label>
  <label><input type="radio" v-model="gender" value="" /></label>
  <hr>
  <ul>
    <li v-for="user of showUsers">
      <input type="checkbox" v-model="user.checked" />
      {{user.username}}
    </li>
  </ul>
  <label><input type="checkbox" v-model="checkAll">全选</label>
</div>
let app = new Vue({
  el: '#app',
  data: {
    gender: '',
    users: [
        {id: 1, username: 'zs', gender: '男'},
        {id: 2, username: 'ls', gender: '男'},
        {id: 3, username: 'xm', gender: '男'},
        {id: 4, username: 'ww', gender: '男'},
        {id: 5, username: 'xh', gender: '女'},
        {id: 6, username: 'xl', gender: '女'}
    ]
  },
  computed: {
    showUsers() {
      return this.gender === '' ? [...this.users] : this.users.filter(user=>user.gender===this.gender);
    },
    checkAll: {
      get() {
        return this.users.every(user=>user.checked);
      },
      set(newValue) {
        this.users = this.users.map(user=>{
          return {
            ...user,
            checked: newValue
          }
        });
      }
    }
  }
});

3.2 example02

3.2.1 example02-1

以下用到派生数据,有以下需求,就可考虑用到vue中的computed了。

  • 派生数据

    • 有原始的数据

    • 有过滤的条件

    • 需要缓存结果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <button @click="changeGender('')">所有</button>
    <button @click="changeGender('')"></button>
    <button @click="changeGender('')"></button>

    <hr>

    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>

</div>

<script src="./js/vue.js"></script>
<script>
    let users = [
        {id: 1, username: 'zs', gender: '男'},
        {id: 2, username: 'ls', gender: '男'},
        {id: 3, username: 'xm', gender: '男'},
        {id: 4, username: 'ww', gender: '男'},
        {id: 5, username: 'xh', gender: '女'},
        {id: 6, username: 'xl', gender: '女'}
    ];
    let app = new Vue({
        el: '#app',
        data: {
            // 过滤条件
            gender: '',
            // 原始数据
            users,
            // 派生数据
            // showUsers: users
        },
        computed: {
            // 类似是一个对象(包含getter、setter对象<get、set>)
            // 派生数据
            showUsers: {
                get() {
                    console.log('...');
                    // showUsers根据过滤条件得到,this.users数据变化都会导致showUsers变化
                    if (this.gender === '') {
                        return this.users;
                    }
                    return this.users.filter( user => user.gender === this.gender );
                }
            }
        },
        methods: {
            changeGender(gender) {
                this.gender = gender;
            }
        }
    });

</script>

</body>
</html>

showUsers当其依赖的数据发生变化后,均可能会导致showUsers发生变化,因为其内部有watch

如果数据没变化,就没执行get函数了,是因为它有缓存,如果依赖的数据没有变化,直接返回上一次的缓存,不会再重新处理一遍逻辑的。

特别数据量大的时候,可以减少很多性能上的损耗。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.72
Branch: branch02

commit description:a0.72(example02-1——computed的使用)

tag:a0.72

3.2.2 example02-2

官网上的缓存演示案例:

通过函数实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <button @click="showDate=!showDate">showDate</button>
    <hr>
    <p v-if="showDate">{{getNow()}}</p>

</div>

<script src="./js/vue.js"></script>
<script>


    let app = new Vue({
        el: '#app',
        data: {
            showDate: false  // 控制时间显示与隐藏
        },
        computed: {
            now:{
                get() {
                    return Date.now();
                }
            }
        },
        methods: {
            getNow() {
                return Date.now();
            }
        }
    });

</script>

</body>
</html>

每次渲染p标签的时候,都会重新拿数据,通过函数调用方式,都会调用函数,因此每次点击的时间点不同。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.73
Branch: branch02

commit description:a0.73(example02-2——官网上的缓存演示案例-函数实现)

tag:a0.73

3.2.3 example02-3

另一种方式:缓存实现 => 只要时间变量没有发生变化,就不会重新获取时间,即调用get函数。如果后续开发中,对数据有缓冲依赖需求的话,就可以使用计算属性了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    
    <button @click="showDate=!showDate">showDate</button>
    <hr>
    <p v-if="showDate">{{now}}</p>

</div>

<script src="./js/vue.js"></script>
<script>


    let app = new Vue({
        el: '#app',
        data: {
            showDate: false
        },
        computed: {
            now:{
                get() {
                    return Date.now();
                }
            }
        },
        methods: {
            getNow() {
                return Date.now();
            }
        }
    });

</script>

</body>
</html>

此时时间就不会发生变化了。因为依赖数据没变化,始终是固定的时间。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.74
Branch: branch02

commit description:a0.74(example02-3——官网上的缓存演示案例-缓存实现)

tag:a0.74

3.2.4 example02-4

set案例:

实现单选和全选相互影响,即它俩构成双向数据流。

我们需要给全选的v-model绑定一个属性,这个属性应该绑定谁呢?

我们第一可能想到在data中设置一个checkedAll属性,初始化为false

但是实际上根据我们的需求,这个全选的数据实际上是根据原始数据派生而得到的,这就满足了派生数据的需求,它根据showUsers的数据,来决定是否全部选中为依据,派生过滤出的一种值。

所以使用派生数据会更加的合适,而且showUsers的数据发生变化,它也需要跟着发生变化。这是其一,同时如果showUsers的数据没发生变化,我们也希望有缓存特性的。

因此我们平时处理这些数据时,分析规律就能够得出应该用哪种方式来处理数据了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <button @click="changeGender('')">所有</button>
    <button @click="changeGender('')"></button>
    <button @click="changeGender('')"></button>

    <hr>

    <ul>
        <li v-for="user of showUsers">
            <input type="checkbox" v-model="user.checked" />
            {{user.username}}
        </li>
    </ul>

    <hr>
    <input type="checkbox" v-model="checkedAll" /> 全选

</div>

<script src="./js/vue.js"></script>
<script>


    let users = [
        {id: 1, username: 'xm', gender: '男', checked: false},
        {id: 2, username: 'zs', gender: '男', checked: false},
        {id: 3, username: 'ls', gender: '男', checked: false},
        {id: 4, username: 'ww', gender: '男', checked: false},
        {id: 5, username: 'xh', gender: '女', checked: false},
        {id: 6, username: 'mm', gender: '女', checked: false}
    ];
    let app = new Vue({
        el: '#app',
        data: {
            // 过滤
            gender: '',
            // 原始数据
            users,
            // 派生数据
            // checkedAll: false
        },
        computed: {
            // 类似是一个对象(getter、setter)
            showUsers: {
                get() {
                    // console.log('...');
                    if (this.gender === '') {
                        return this.users;
                    }
                    return this.users.filter( user => user.gender === this.gender );
                }
            },
            // 该数据是根据原先数据派生得到的,因此马上使用计算属性
            checkedAll: {
                get() {
                    return this.users.every( user => user.checked );
                }
            }
        },
        methods: {
            changeGender(gender) {
                this.gender = gender;
            }
        }
    });

</script>

</body>
</html>

但是点击全选,报错了。因为我们没写set函数。

这里是v-model双向数据绑定,因此我们改变input状态时,它就会去修改checkedAll属性(不需要写代码),但是问题来了,我们尝试修改计算属性的值,又没写set方法,则报错。

image-20200729153737537

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.75
Branch: branch02

commit description:a0.75(example02-4——set案例实现全选双向数据绑定-改变计算属性时没有设置set方法会报错)

tag:a0.75

3.2.5 example02-5

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <button @click="changeGender('')">所有</button>
    <button @click="changeGender('')"></button>
    <button @click="changeGender('')"></button>

    <hr>

    <ul>
        <li v-for="user of showUsers">
            <input type="checkbox" v-model="user.checked" />
            {{user.username}}
        </li>
    </ul>

    <hr>
    <input type="checkbox" v-model="checkedAll" /> 全选

</div>

<script src="./js/vue.js"></script>
<script>


    let users = [
        {id: 1, username: 'xm', gender: '男', checked: false},
        {id: 2, username: 'zs', gender: '男', checked: false},
        {id: 3, username: 'ls', gender: '男', checked: false},
        {id: 4, username: 'ww', gender: '男', checked: false},
        {id: 5, username: 'xh', gender: '女', checked: false},
        {id: 6, username: 'mm', gender: '女', checked: false}
    ];
    let app = new Vue({
        el: '#app',
        data: {
            // 过滤
            gender: '',
            // 原始数据
            users,
            // 派生数据
            // checkedAll: false
        },
        computed: {
            // 类似是一个对象(getter、setter)
            showUsers: {
                get() {
                    // console.log('...');
                    if (this.gender === '') {
                        return this.users;
                    }
                    return this.users.filter( user => user.gender === this.gender );
                }
            },
            // 该数据是根据原先数据派生得到的,因此马上使用计算属性
            checkedAll: {
                get() {
                    return this.users.every( user => user.checked );
                },
                set(newVal) {
                    console.log(newVal);
                    this.users = this.users.map( user => {
                        return {
                            ...user, // 解构
                            checked: newVal
                        }
                    } );
                }
            }
        },
        methods: {
            changeGender(gender) {
                this.gender = gender;
            }
        }
    });

</script>

</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.76
Branch: branch02

commit description:a0.76(example02-5——set案例实现全选双向数据绑定-设置set)

tag:a0.76

4. watch

有的时候,我们需要的派生数据是通过异步的方式处理的,这个时候,计算属性就不太好用了(不能处理异步),并且更多情况下,数据请求来自后端接口,因此需要异步处理。

我们可以使用另外一个选项:watch

<div id="app">
  <input type="text" v-model="keyWord">
  <hr>
  <ul>
    <li v-for="user of showUsers">
      {{user.username}}
    </li>
  </ul>
</div>
let app = new Vue({
  el: '#app',
  data: {
    keyWord: '',
    users: [
        {id: 1, username: 'xm', gender: '男', checked: false},
        {id: 2, username: 'zs', gender: '男', checked: false},
        {id: 3, username: 'ls', gender: '男', checked: false},
        {id: 4, username: 'ww', gender: '男', checked: false},
        {id: 5, username: 'xh', gender: '女', checked: false},
        {id: 6, username: 'mm', gender: '女', checked: false}
    ],
    showUsers: []
  },
  watch: {
    keyWord(newVal, oldVal) {
      // 模拟网络请求
      setTimeout(_=>{
        this.showUsers = this.users.filter(user=>user.username.includes(newVal));
      }, 1000);
    }
  }
});

4.1 example03

4.1.1 example03-1

实现一个模糊检索的例子。

注意:计算属性简化写法,当不需要set时候,可以直接将数据属性写成函数,默认是get函数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <input type="text" v-model="keyWord">
    <hr>
    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>


</div>

<script src="./js/vue.js"></script>
<script>


    let app = new Vue({
        el: '#app',
        data: {
            keyWord: '',
            users: [
                {id: 1, username: 'zsaa', gender: '男',checked:false},
                {id: 2, username: 'lsdsad', gender: '男',checked:false},
                {id: 3, username: 'wwdsad', gender: '男',checked:false},
                {id: 4, username: 'xmdsadsa', gender: '男',checked:false},
                {id: 5, username: 'xhdasdasdasdas', gender: '女',checked:false},
                {id: 6, username: 'xlzxczxczx', gender: '女',checked:false}
            ]
        },
        computed: {
            // 简化写法,当不需要set时候,可以直接写,默认是get函数
            showUsers() {
                // 模糊匹配
                if (this.keyWord !== '') {
                    return this.users.filter( user => user.username.includes(this.keyWord) );
                }
                return [];
            }
        }
    });

</script>

</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.77
Branch: branch02

commit description:a0.77(example03-1——简单实现实现模糊检索)

tag:a0.77

4.1.2 example03-2

这些数据很可能是从后端某个接口调用得到的,就涉及异步请求(会花一些时间请求)问题。

不写后台代码了,用定时器模拟。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<div id="app">
 
    <input type="text" v-model="keyWord">
    <hr>
    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>
 
 
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
    let app = new Vue({
        el: '#app',
        data: {
            keyWord: '',
            users: [
                {id: 1, username: 'zsaa', gender: '男',checked:false},
                {id: 2, username: 'lsdsad', gender: '男',checked:false},
                {id: 3, username: 'wwdsad', gender: '男',checked:false},
                {id: 4, username: 'xmdsadsa', gender: '男',checked:false},
                {id: 5, username: 'xhdasdasdasdas', gender: '女',checked:false},
                {id: 6, username: 'xlzxczxczx', gender: '女',checked:false}
            ]
        },
        computed: {
            showUsers() {
                setTimeout(_ => {
                    if (this.keyWord !== '') {
                        return this.users.filter( user => user.username.includes(this.keyWord) );
                    }
                    return [];
                }, 1000);
            }
        }
    });
 
</script>
 
</body>
</html>

明显不可行,return返回给的是返回定时器。

如果返回定时器,则返回的是定时器的编号,肯定也不行,如下:

computed: {
            showUsers() {
                return setTimeout(_ => {
                        if (this.keyWord !== '') {
                            return this.users.filter( user => user.username.includes(this.keyWord) );
                        }
                        return [];
                    }, 1000);
            	}
        }

怎么解决呢?用promise

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <input type="text" v-model="keyWord">
    <hr>
    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>


</div>

<script src="./js/vue.js"></script>
<script>


    let app = new Vue({
        el: '#app',
        data: {
            keyWord: '',
            users: [
                {id: 1, username: 'zsaa', gender: '男',checked:false},
                {id: 2, username: 'lsdsad', gender: '男',checked:false},
                {id: 3, username: 'wwdsad', gender: '男',checked:false},
                {id: 4, username: 'xmdsadsa', gender: '男',checked:false},
                {id: 5, username: 'xhdasdasdasdas', gender: '女',checked:false},
                {id: 6, username: 'xlzxczxczx', gender: '女',checked:false}
            ]
        },
        computed: {
            showUsers() {
                // setTimeout(_ => {
                //     // 明显不可行,return返回给的是返回定时器,如果返回定时器,则返回的是定时器的编号也不行
                //     if (this.keyWord !== '') {
                //         return this.users.filter( user => user.username.includes(this.keyWord) );
                //     }
                //     return [];
                // }, 1000);
                // 计算属性不支持 promise 任务,不支持异步任务的处理
                return new Promise(resolve => {
                    setTimeout(_ => {
                        if (this.keyWord !== '') {
                            resolve(this.users.filter( user => user.username.includes(this.keyWord) ));
                        }
                        resolve([]);
                    }, 1000);
                })
            }
        }
    });
</script>

</body>
</html>

但是没有任何效果,其实原因很简单,它不支持promise。计算属性的值必须立刻返回,不能进行任何异步处理。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.78
Branch: branch02

commit description:a0.78(example03-2——计算属性不支持异步)

tag:a0.78

4.1.3 example03-3

使用watch实现异步监听数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <input type="text" v-model="keyWord">
    <hr>
    <ul>
        <li v-for="user of showUsers">
            {{user.username}}
        </li>
    </ul>


</div>

<script src="./js/vue.js"></script>
<script>


    let app = new Vue({
        el: '#app',
        data: {
            keyWord: '',
            users: [
                {id: 1, username: 'zsaa', gender: '男',checked:false},
                {id: 2, username: 'lsdsad', gender: '男',checked:false},
                {id: 3, username: 'wwdsad', gender: '男',checked:false},
                {id: 4, username: 'xmdsadsa', gender: '男',checked:false},
                {id: 5, username: 'xhdasdasdasdas', gender: '女',checked:false},
                {id: 6, username: 'xlzxczxczx', gender: '女',checked:false}
            ],
            showUsers: []
        },
        watch: {
            // 监听keyWord数据变化,如变化就会执行该函数
            keyWord() {
                console.log('....')
                setTimeout(() => {
                    if (this.keyWord !== '') {
                        this.showUsers = this.users.filter( user => user.username.includes(this.keyWord) );
                    } else {
                        this.showUsers = [];
                    }

                    console.log(this.users);
                }, 1000);
            }
        }
    });
</script>

</body>
</html>

watch不需要返回值,而是监听它的值发生变化,而处理一些逻辑。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.79
Branch: branch02

commit description:a0.79(example03-3——watch属性实现异步监听)

tag:a0.79

4.2 多层监听

对于多层数据的监听,可以使用字符串+点语法

a对象里的b属性,再对应b属性对象里的c属性…

watch: {
  'a.b.c': function() {
    //...
  }
}

4.3 深度监听

默认情况下,watch 只对当前指定的值进行一层监听,如果需要对对象进行深度监听

多层数据,对于如上例监听users,其只会监听多一个少一个对象,里面数据变化,如选择还是没选中是不监听的,而只会监听users数组本身的变化。

watch: {
  a: {
    handler() {
      console.log('a deep');
    },
    deep: true
  }
}


(后续待补充)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值