vue中watch的使用
vue中的watch是一个比较重要的概念,通过他我们可以检测data的变化,下面进行详细的介绍。
watch定义方式如下:
{[key: string]: string | Function | Object }
即在watch中,
- 键是一个字符串,它是被观测的对象。
- 值可以是一个字符串,这个字符串是方法名。
- 值还可以是一个函数,但不能使用箭头函数的形式,this会出现问题。
- 值也可以是一个对象,其中包含回调函数可以其他一些选项:比如是否深度遍历。
举例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script> </head> <body> <script> var vm = new Vue({ data: { a: 1, b: 2, c: { name: "JohnZhu" } }, watch: { a: function (val, oldVal) { console.log('new a: %s, old a: %s', val, oldVal) }, // 方法名 b: 'someMethod', // 深度 watcher, 检测到变化,并打印出c.name变化前后的结果 // 'c.name': { // handler: function (val, oldVal) { // console.log('new c: %s, old c: %s', val, oldVal); // }, // deep: true // }, // 报错 必须用c.name,否则在data下不能直接找到name // name: function () { // console.log('new c: %s, old c: %s', val, oldVal); // } // 报错,键值必须是一个字符串,所以用引号括起来 // c.name: { // handler: function (val, oldVal) { // console.log('new c: %s, old c: %s', val, oldVal); // }, // deep: true // } // 这里未检测到变化 // c : { // handler: function (val, oldVal) { // console.log('new c: %s, old c: %s', val, oldVal); // }, // deep: false // }, // 成功检测到变化 // c : { // handler: function (val, oldVal) { // console.log('new c: %s, old c: %s', val, oldVal); // }, // deep: true // }, // 检测不到变化,因为参数 deep 的默认值是false // c : { // handler: function (val, oldVal) { // console.log('new c: %s, old c: %s', val, oldVal); // }, // }, }, methods: { someMethod: function () { alert("b is changed"); } } }) vm.a = 2; // new: 2, old: 1 vm.b = 666; // alert 666 vm.c.name = "HTT"; </script> </body> </html>
函数执行之后,分别在控制台中打印出new: 2, old:1 以及 alert 666。
- 可以看出, watch函数的参数中,第一个是改变之前的值,第二个是改变之后的值, 这两个参数非常有用。
- 这里分别使用了 三种定义函数(或option)的方法。
- 如果要观察data下一个对象的属性,我们可以使用 '对象.属性' 的方式, 注意: 一定要要引号。
- 如果改变了一个对象的属性,就必须使用 deep: true, 否则检测不到变化。
举例:
这样的一个组件,当我想要同级输入的字数并希望在字数达到一定的数目时,给出提示,就可以watch字数, 即v-model实现,当字数的length改变时,我们判断, 然后给出相应的提示:
最后贴出完整的代码:
<template> <div class="add-remark"> <div class="input"> <textarea maxlength="50" placeholder="请输入备注,最多50个字哦" v-model="message"></textarea> <span class="font-number" >{{message.length}}/50</span> </div> <div class="hint-content" v-on:click="handleHint($event)"> <span class="hint">不吃辣</span> <span class="hint">少放辣</span> <span class="hint">多放辣</span> <span class="hint">不吃蒜</span> <span class="hint">不吃香菜</span> <span class="hint">不吃葱</span> </div> <div class="btn" v-on:click="goback">完成</div> </div> </template> <style scoped lang="less"> @main-color: #51B1B0; @sub-color: #eeefef; div.add-remark { div.input { position: relative; padding: 0.2rem 0.5rem; textarea { box-sizing: border-box; width: 100%; height: 4rem; font-size: 0.4rem; padding: 0.3rem; border: 0.0294rem solid @sub-color; &:focus { box-shadow: 0 0 0.0417rem @main-color; } } span.font-number { position: absolute; font-size: 0.4rem; color: #aaa; bottom: 0.5rem; right: 0.7rem; } } div.hint-content { padding: 0.2rem; span.hint { display: inline-block; margin: 0.2rem 0.3rem 0.2rem 0.3rem; padding: 0.25rem; border: 0.02rem solid @sub-color; border-radius: 0.1rem; &:active { background-color: @sub-color; } } } div.btn { width: 9rem; height: 1rem; margin: 0.3rem auto; line-height: 1rem; text-align: center; background-color: @main-color; font-size: 0.45rem; font-weight: bold; color: white; border-radius: 0.2rem; } } </style> <script> export default { data () { return { message: "" } }, watch: { message: function (val, oldValue) { if (val.length == 50) { this.$toast("备注最多输入50字哦"); } } }, methods: { handleHint: function (e) { if (e.target.nodeName.toLowerCase() == "span") { this.message += (" " + e.target.innerHTML ) } }, goback () { this.$router.back(); } } } </script>
https://cn.vuejs.org/v2/api/#watch
http://www.jianshu.com/p/ffe50c5e3368
http://www.cnblogs.com/dupd/p/5887907.html
https://cn.vuejs.org/v2/guide/computed.html#Computed-属性-vs-Watched-属性、
仰天大笑出门去,我辈岂是蓬蒿人。