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-屬性、
仰天大笑出門去,我輩豈是蓬蒿人。
