Vue成神之路之選項(xiàng)

前言

記錄平時(shí)學(xué)到的知識(shí),標(biāo)題寫的大氣一點(diǎn),也算是給自己一點(diǎn)鼓勵(lì),希望在技術(shù)這條路可以遠(yuǎn)走越遠(yuǎn),路越走越寬~

文中代碼地址

PS:如果對你有一點(diǎn)幫助,請順手給個(gè)小星星哦,鼓勵(lì)我繼續(xù)寫下去~

引入的文件文件說明

vue.js——開發(fā)版本:包含完整的警告和調(diào)試模式
vue.min.js——生產(chǎn)版本:刪除了警告,進(jìn)行了壓縮

1. propsData Option 全局?jǐn)U展的數(shù)據(jù)傳遞

propsData在實(shí)際開發(fā)中使用的并不多,用在全局?jǐn)U展時(shí)進(jìn)行傳遞數(shù)據(jù),主要搭配Vue.extend使用。

在實(shí)際的項(xiàng)目中,使用全局?jǐn)U展的方式制作自定義標(biāo)簽比較少用,完全可以使用組件來替代。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>propsData Option</title>
</head>
<body>
    <h1>propsData Option</h1>
    <hr>
    <div id="app"></div>

    <script type="text/javascript">
       var  header_a = Vue.extend({
           template:`<p>{{message}}</p>`,
           data:function(){
               return {
                   message:'Hello,I am Header'
               }
           }
       });
       
       new header_a().$mount('#app');
    </script>
</body>
</html>

擴(kuò)展標(biāo)簽已經(jīng)做好了,這時(shí)要在掛載時(shí)傳遞數(shù)據(jù),就用到了propsData。

使用用propsData三步解決傳值:

  1. 在全局?jǐn)U展里加入props進(jìn)行接收;
  2. 傳遞時(shí)用propsData進(jìn)行傳遞;
  3. 用插值的形式寫入模板;

完整代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>propsData Option</title>
</head>
<body>
    <h1>propsData Option</h1>
    <hr>
    <div id="app"></div>

    <script type="text/javascript">
        var  header_a = Vue.extend({
            template:`<p>{{message}}-{{a}}</p>`,
            data:function(){
                return {
                    message:'Hello,I am Header'
                }
            },
            props:['a']
        }); 
        
        new header_a({propsData:{a:1}}).$mount('header');
    </script>
</body>
</html>

2.computed Option 計(jì)算選項(xiàng)

computed計(jì)算屬性的主要作用是在數(shù)據(jù)渲染之前,根據(jù)實(shí)際需求對數(shù)據(jù)進(jìn)行處理,比如:大小寫轉(zhuǎn)換,順序重排,添加符號(hào)……。為了不污染data中定義的數(shù)據(jù)源,在computed里需要新聲明一個(gè)對象保存處理之后的數(shù)據(jù)。

computed計(jì)算屬性的所有g(shù)etter和setter的this上下文自動(dòng)地綁定為 Vue 實(shí)例。注意如果你為一個(gè)計(jì)算屬性使用了箭頭函數(shù),則 this 不會(huì)指向這個(gè)組件的實(shí)例,不過你仍然可以將其實(shí)例作為函數(shù)的第一個(gè)參數(shù)來訪問。

computed: {
  aDouble: vm => vm.a * 2 
}

計(jì)算屬性的結(jié)果會(huì)被緩存,除非依賴的響應(yīng)式屬性變化才會(huì)重新計(jì)算。注意,如果某個(gè)依賴 (比如非響應(yīng)式屬性) 在該實(shí)例范疇之外,則計(jì)算屬性是不會(huì)被更新的。

用計(jì)算屬性反轉(zhuǎn)新聞數(shù)據(jù)數(shù)組,讓最近發(fā)生的新聞放在前面顯示,demo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>computed 計(jì)算選項(xiàng)</title>
</head>
<body>
    <h1>computed 計(jì)算選項(xiàng)</h1>
    <hr>
    <div id="app">
        {{newPrice}}
        <br>
        <br>
        <ul>
            <li v-for="item in reverseNews">{{item.title}} - {{item.date}}</li>
        </ul>
    </div>
    <script type="text/javascript">
        var newsList = [
            {title:'香港或就“裝甲車被扣”事件追責(zé) 起訴涉事運(yùn)輸公司',date:'2017/3/10'},
            {title:'日本第二大準(zhǔn)航母服役 外媒:針對中國潛艇',date:'2017/3/12'},
            {title:'中國北方將有明顯雨雪降溫天氣 南方陰雨持續(xù)',date:'2017/3/13'},
            {title:'起底“最短命副市長”:不到40天落馬,全家被查',date:'2017/3/23'},
        ];

        var app=new Vue({
            el:'#app',
            data:{
                price:100,
                newsList: newsList
            },
            computed:{
                newPrice:function(){
                    return this.price='¥' + this.price + '元';
                },
                reverseNews:function(){
                    return this.newsList.reverse();
                }
            }
        })
    </script>
</body>
</html>

computed 計(jì)算屬性是非常有用并且在實(shí)際的項(xiàng)目開發(fā)中經(jīng)常使用,它在輸出數(shù)據(jù)前可以根據(jù)實(shí)際項(xiàng)目需求對數(shù)據(jù)進(jìn)行處理,改變數(shù)據(jù)。

3. methods Option 方法選項(xiàng)

在Vue中,可以使用v-on給元素綁定事件,在methods選項(xiàng)中處理一些邏輯方面的事情。在Vue中的邏輯處理,一般都在Vue的methods選項(xiàng)中來處理,那是因?yàn)楹芏嗍录幚磉壿嫶a都很復(fù)雜,如果直接把JavaScript代碼寫在v-on指令中有時(shí)并不可行,所以在methods中定義方法,讓v-on指令來接收(調(diào)用)。

一個(gè)數(shù)字,每點(diǎn)擊一下按鈕加2:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>methods Option</title>
    <script type="text/javascript" src="../assets/js/vue.js"></script>
</head>
<body>
    <h1>methods Option</h1>
    <hr>
    <div id="app">
        {{ a }}
        <p><button @click="add">add</button></p>
    </div>
    <script type="text/javascript">
        var app=new Vue({
            el:'#app',
            data:{
                a:1
            },
            methods:{
                add () {
                    this.a++
                }
            }
        })
    </script>
</body>
</html>

methods中參數(shù)的傳遞:

使用方法和正常的javascript傳遞參數(shù)的方法一樣,分為兩步:

  1. 在methods的方法中進(jìn)行聲明,比如給add方法傳入一個(gè)num參數(shù),就要寫出add (num){...};
  2. 調(diào)用方法時(shí)直接傳遞,比如要傳遞2這個(gè)參數(shù),在button上就直接可以寫。<button @click=”add(2)”></button>;

給add添加num參數(shù),并在按鈕上調(diào)用傳遞:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>methods Option</title>
    <script type="text/javascript" src="../assets/js/vue.js"></script>
</head>
<body>
    <h1>methods Option</h1>
    <hr>
    <div id="app">
        {{ a }}
        <p><button @click="add(2)">add</button></p>
    </div>
    <script type="text/javascript">
        var app=new Vue({
            el:'#app',
            data:{
                a:1
            },
            methods:{
                add (num) {
                    this.a += num
                }
            }
        })
    </script>
</body>
</html>

這時(shí),再點(diǎn)擊按鈕時(shí)結(jié)果每次加2。

methods中的$event參數(shù):

傳遞的$event參數(shù)都是關(guān)于你點(diǎn)擊鼠標(biāo)的一些事件和屬性。傳遞方法:

<button @click=”add(2,$event)”>add</button> 。

這時(shí)候可以打印一下,看看event到底是個(gè)怎樣的對象。你會(huì)發(fā)現(xiàn),它包含了大部分鼠標(biāo)事件的屬性:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>methods Option</title>
    <script type="text/javascript" src="../assets/js/vue.js"></script>
</head>
<body>
    <h1>methods Option</h1>
    <hr>
    <div id="app">
        {{ a }}
        <p><button @click="add(2,'每次加2', $event)">add</button></p>
    </div>
    <script type="text/javascript">
        var app=new Vue({
            el:'#app',
            data:{
                a:1
            },
            methods:{
                add (num, msg, event) {
                    console.log('num==>', num)
                    console.log('msg==>', msg)
                    console.log('event==>', event)
                    this.a += num
                }
            }
        })
    </script>
</body>

native 給組件綁定構(gòu)造器里的原生事件:

在實(shí)際開發(fā)中經(jīng)常需要把某個(gè)按鈕封裝成組件,然后反復(fù)使用,如何讓組件調(diào)用構(gòu)造器里的方法,而不是組件里的方法。就需要用到.native修飾器了。

把我們的add按鈕封裝成組件,聲明btn對象:

var btn={
    template:`<button>組件Add</button>`     
}

在構(gòu)造器里注冊組件:

components:{
    "btn":btn
}

用.native修飾器來調(diào)用構(gòu)造器里的add方法:

<p><btn @click.native="add(3)"></btn></p>

完整代碼:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>methods Option</title>
    <script type="text/javascript" src="../assets/js/vue.js"></script>
</head>
<body>
    <h1>methods Option</h1>
    <hr>
    <div id="app">
       {{a}}
       <p><button @click="add(2, '每次加2', $event)">add</button></p>
       <p><btn @click.native="add(3, '每次加3', $event)"></btn></p>
    </div>

    <script type="text/javascript">
       var btn={
           template:'<button>外部組件</button>'
       }
        var app=new Vue({
            el:'#app',
            data:{
                a:1
            },
            methods:{
                add (num, msg, event) {
                    console.log('num==>', num)
                    console.log('msg==>', msg)
                    console.log('event==>', event)
                    this.a += num
                }
            },
            components:{
                "btn":btn
            }
        })
    </script>
</body>
</html>

作用域外部調(diào)用構(gòu)造器里的方法:

這種不經(jīng)常使用,如果你出現(xiàn)了這種情況,說明你的代碼組織不夠好。

<button onclick="app.add(4)" >外部調(diào)用構(gòu)造器里的方法</button>

完整代碼:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>methods Option</title>
    <script type="text/javascript" src="../assets/js/vue.js"></script>
</head>
<body>
    <h1>methods Option</h1>
    <hr>
    <div id="app">
       {{a}}
       <p><button @click="add(2, '每次加2', $event)">add</button></p>
       <p><btn @click.native="add(3, '每次加3', $event)"></btn></p>
    </div>
    <button onclick="app.add(4, '每次加4')">外部訪問構(gòu)造器里的方法</button>

    <script type="text/javascript">
       var btn={
           template:'<button>外部組件</button>'
       }
        var app=new Vue({
            el:'#app',
            data:{
                a:1
            },
            methods:{
                add (num, msg, event) {
                    console.log('num==>', num)
                    console.log('msg==>', msg)
                    console.log('event==>', event)
                    this.a += num
                }
            },
            components:{
                "btn":btn
            }
        })
    </script>
</body>
</html>

4. Watch 選項(xiàng) 監(jiān)控?cái)?shù)據(jù)

使用watch選項(xiàng)來監(jiān)控?cái)?shù)據(jù)的變化。watch選項(xiàng)對應(yīng)一個(gè)對象,鍵是觀察表達(dá)式,值是對應(yīng)回調(diào)。值也可以是方法名,或者是對象,包含選項(xiàng)。在實(shí)例化時(shí)為每個(gè)鍵調(diào)用 $watch() 。

天氣預(yù)報(bào)的穿衣指數(shù),它主要是根據(jù)溫度來進(jìn)行提示,溫度大于26度時(shí),建議穿T恤短袖,溫度小于26度大于0度時(shí),建議穿夾克長裙,溫度小于0度時(shí)建議穿棉衣羽絨服:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>watch Option</title>
</head>
<body>
    <h1>watch Option</h1>
    <hr>
    <div id="app">
        <p>今日溫度:{{temperature}}°C</p>
        <p>穿衣建議:{{suggestion}}</p>
        <p>
            <button @click="add">添加溫度</button>
            <button @click="reduce">減少溫度</button>
        </p>
    </div>

    <script type="text/javascript">
        var suggestion=['T恤短袖','夾克長裙','棉衣羽絨服'];
        var app=new Vue({
            el:'#app',
            data:{
                temperature:14,
                suggestion:'夾克長裙'
            },
            methods:{
                add:function(){
                    this.temperature+=5;
                },
                reduce:function(){
                    this.temperature-=5;
                }
            },
            watch:{
                temperature (newVal,oldVal) {
                    if(newVal>=26){
                        this.suggestion=suggestion[0];
                    }else if(newVal<26 && newVal >=0)
                    {
                        this.suggestion=suggestion[1];
                    }else{
                        this.suggestion=suggestion[2];
                    }
                }
            }
        })
    </script>
</body>
</html>

handler方法和immediate屬性:

這里 watch 的一個(gè)特點(diǎn)是,最初綁定的時(shí)候是不會(huì)執(zhí)行的,要等到 temperature 改變時(shí)才執(zhí)行監(jiān)聽計(jì)算。那我們想要一開始就讓它最初綁定的時(shí)候就執(zhí)行改怎么辦呢?我們需要修改一下我們的 watch 寫法,修改過后的 watch 代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>watch Option</title>
</head>
<body>
    <h1>watch Option</h1>
    <hr>
    <div id="app">
        <p>今日溫度:{{temperature}}°C</p>
        <p>穿衣建議:{{suggestion}}</p>
        <p>
            <button @click="add">添加溫度</button>
            <button @click="reduce">減少溫度</button>
        </p>
    </div>

    <script type="text/javascript">
        var suggestion=['T恤短袖','夾克長裙','棉衣羽絨服'];
        var app=new Vue({
            el:'#app',
            data:{
                temperature:14,
                suggestion:'T恤短袖'
            },
            methods:{
                add:function(){
                    this.temperature+=5;
                },
                reduce:function(){
                    this.temperature-=5;
                }
            },
            watch:{
                temperature: {
                    handler (newVal,oldVal) {
                        if(newVal>=26){
                            this.suggestion=suggestion[0];
                        }else if(newVal<26 && newVal >=0)
                        {
                            this.suggestion=suggestion[1];
                        }else{
                            this.suggestion=suggestion[2];
                        }
                    },
                    // 代表在wacth里聲明了temperature這個(gè)方法之后立即先去執(zhí)行handler方法
                    immediate: true
                }
            }
        })
    </script>
</body>
</html>

注意到handler了嗎,我們給 temperature 綁定了一個(gè)handler方法,之前我們寫的 watch 方法其實(shí)默認(rèn)寫的就是這個(gè)handler,Vue.js會(huì)去處理這個(gè)邏輯,最終編譯出來其實(shí)就是這個(gè)handler。

而immediate:true代表如果在 wacth 里聲明了 temperature 之后,就會(huì)立即先去執(zhí)行里面的handler方法,如果為 false就跟我們以前的效果一樣,不會(huì)在綁定的時(shí)候就執(zhí)行。

在上面的事例中把suggestion的初始數(shù)據(jù)設(shè)置為'T恤短袖',而初始溫度是14°C,這時(shí)如果沒有讓watch在最初綁定的時(shí)候就執(zhí)行,那么推薦的穿衣就有問題,因?yàn)?4°C原本是推薦穿'夾克長裙'的,通過讓watch在最初綁定的時(shí)候就執(zhí)行完美解決了這個(gè)問題。

deep屬性:
watch 里面還有一個(gè)屬性 deep,默認(rèn)值是 false,代表是否深度監(jiān)聽,比如我們 data 里有一個(gè)obj屬性:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>watch Option</title>
</head>
<body>
    <h1>watch Option</h1>
    <hr>
    <div id="app">
        <p>今日溫度:{{obj.temperature}}°C</p>
        <p>穿衣建議:{{obj.suggestion}}</p>
        <p>
            <button @click="add">添加溫度</button>
            <button @click="reduce">減少溫度</button>
        </p>
    </div>

    <script type="text/javascript">
        var suggestion=['T恤短袖','夾克長裙','棉衣羽絨服'];
        var app=new Vue({
            el:'#app',
            data: {
                obj: {
                    temperature: 14,
                    suggestion:'T恤短袖'
                }
            },
            methods:{
                add:function(){
                    this.obj.temperature+=5;
                },
                reduce:function(){
                    this.obj.temperature-=5;
                }
            },
            watch: {
                obj: {
                    handler(newVal, oldVal) {
                        console.log('obj.a changed', newVal.temperature)
                        if(newVal.temperature>=26){
                            this.obj.suggestion=suggestion[0];
                        }else if(newVal.temperature<26 && newVal.temperature >=0)
                        {
                            this.obj.suggestion=suggestion[1];
                        }else{
                            this.obj.suggestion=suggestion[2];
                        }
                        console.log('obj.a 2', newVal.suggestion)
                    },
                    immediate: true
                }
            } 
        })
    </script>
</body>
</html>

當(dāng)我們在點(diǎn)擊添加溫度和減少溫度按鈕改變obj.temperature的值時(shí),發(fā)現(xiàn)是無效的。受現(xiàn)代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到對象屬性的添加或刪除。由于 Vue 會(huì)在初始化實(shí)例時(shí)對屬性執(zhí)行 getter/setter 轉(zhuǎn)化過程,所以屬性必須在 data 對象上存在才能讓 Vue 轉(zhuǎn)換它,這樣才能讓它是響應(yīng)的。

默認(rèn)情況下 handler 只監(jiān)聽obj這個(gè)屬性它的引用的變化,我們只有給obj賦值的時(shí)候它才會(huì)監(jiān)聽到,比如我們在 mounted事件鉤子函數(shù)中對obj進(jìn)行重新賦值:

mounted: {
  this.obj = {
    temperature: 40,
    suggestion:'T恤短袖'
  }
}

這樣我們的 handler 才會(huì)執(zhí)行。

如果需要監(jiān)聽obj里的屬性temperature的值,這時(shí)候deep屬性就派上用場了:

watch: {
    obj: {
        handler(newVal, oldVal) {
            console.log('obj.a changed', newVal.temperature)
            if(newVal.temperature>=26){
                this.obj.suggestion=suggestion[0];
            }else if(newVal.temperature<26 && newVal.temperature >=0)
            {
                this.obj.suggestion=suggestion[1];
            }else{
                this.obj.suggestion=suggestion[2];
            }
            console.log('obj.a 2', newVal.suggestion)
        },
        immediate: true,
        deep: true
    }
} 

deep的意思就是深入觀察,監(jiān)聽器會(huì)一層層的往下遍歷,給對象的所有屬性都加上這個(gè)監(jiān)聽器,但是這樣性能開銷就會(huì)非常大了,任何修改obj里面任何一個(gè)屬性都會(huì)觸發(fā)這個(gè)監(jiān)聽器里的 handler。

優(yōu)化,可以使用字符串形式監(jiān)聽:

watch: {
    'obj.temperature': {
        handler(newVal, oldVal) {
            console.log('obj.a changed', newVal)
            if(newVal>=26){
                this.obj.suggestion=suggestion[0];
            }else if(newVal<26 && newVal >=0)
            {
                this.obj.suggestion=suggestion[1];
            }else{
                this.obj.suggestion=suggestion[2];
            }
            console.log('obj.a 2', this.obj.suggestion)
        },
        immediate: true,
        deep: true
    }
} 

這樣Vue.js才會(huì)一層一層解析下去,直到遇到屬性temperature,然后才給temperature設(shè)置監(jiān)聽函數(shù)。

完整代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>watch Option</title>
</head>
<body>
    <h1>watch Option</h1>
    <hr>
    <div id="app">
        <p>今日溫度:{{obj.temperature}}°C</p>
        <p>穿衣建議:{{obj.suggestion}}</p>
        <p>
            <button @click="add">添加溫度</button>
            <button @click="reduce">減少溫度</button>
        </p>
    </div>

    <script type="text/javascript">
        var suggestion=['T恤短袖','夾克長裙','棉衣羽絨服'];
        var app=new Vue({
            el:'#app',
            data: {
                obj: {
                    temperature: 14,
                    suggestion:'T恤短袖'
                }
            },
            methods:{
                add:function(){
                    this.obj.temperature+=5;
                },
                reduce:function(){
                    this.obj.temperature-=5;
                }
            },
            // watch: {
            //     obj: {
            //         handler(newVal, oldVal) {
            //             console.log('obj.a changed', newVal.temperature)
            //             if(newVal.temperature>=26){
            //                 this.obj.suggestion=suggestion[0];
            //             }else if(newVal.temperature<26 && newVal.temperature >=0)
            //             {
            //                 this.obj.suggestion=suggestion[1];
            //             }else{
            //                 this.obj.suggestion=suggestion[2];
            //             }
            //             console.log('obj.a 2', newVal.suggestion)
            //         },
            //         immediate: true,
            //         deep: true
            //     }
            // }

            //優(yōu)化使用字符串形式監(jiān)聽
            watch: {
                'obj.temperature': {
                    handler(newVal, oldVal) {
                        console.log('obj.a changed', newVal)
                        if(newVal>=26){
                            this.obj.suggestion=suggestion[0];
                        }else if(newVal<26 && newVal >=0)
                        {
                            this.obj.suggestion=suggestion[1];
                        }else{
                            this.obj.suggestion=suggestion[2];
                        }
                        console.log('obj.a 2', this.obj.suggestion)
                    },
                    immediate: true,
                    deep: true
                }
            } 
        })
    </script>
</body>
</html>

用實(shí)例屬性寫watch監(jiān)控:

有些時(shí)候我們會(huì)用實(shí)例屬性的形式來寫watch監(jiān)控。也就是把我們watch卸載構(gòu)造器的外部,這樣的好處就是降低我們程序的耦合度,使程序變的靈活:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>watch Option</title>
</head>
<body>
    <h1>watch Option</h1>
    <hr>
    <div id="app">
        <p>今日溫度:{{temperature}}°C</p>
        <p>穿衣建議:{{suggestion}}</p>
        <p>
            <button @click="add">添加溫度</button>
            <button @click="reduce">減少溫度</button>
        </p>
    </div>

    <script type="text/javascript">
        var suggestion=['T恤短袖','夾克長裙','棉衣羽絨服'];
        var app=new Vue({
            el:'#app',
            data:{
                temperature:14,
                suggestion:'夾克長裙'
            },
            methods:{
                add:function(){
                    this.temperature+=5;
                },
                reduce:function(){
                    this.temperature-=5;
                }
            }
        })

        app.$watch('temperature',function(newVal,oldVal){
            if(newVal>=26){
                this.suggestion=suggestion[0];
            }else if(newVal<26 && newVal >=0)
            {
                this.suggestion=suggestion[1];
            }else{
                this.suggestion=suggestion[2];
            }
        })
    </script>
</body>
</html>

注銷watch:

為什么要注銷 watch?因?yàn)槲覀兊慕M件是經(jīng)常要被銷毀的,比如我們跳一個(gè)路由,從一個(gè)頁面跳到另外一個(gè)頁面,那么原來的頁面的 watch 其實(shí)就沒用了,這時(shí)候我們應(yīng)該注銷掉原來頁面的 watch 的,不然的話可能會(huì)導(dǎo)致內(nèi)置溢出。當(dāng)把 watch 寫在組件的選項(xiàng)中的,它會(huì)隨著組件的銷毀而銷毀。

但是,如果我們使用上面的這樣的方式寫 watch:

app.$watch('temperature',function(newVal,oldVal){
    if(newVal>=26){
        this.suggestion=suggestion[0];
    }else if(newVal<26 && newVal >=0)
    {
        this.suggestion=suggestion[1];
    }else{
        this.suggestion=suggestion[2];
    }
})

那么就要手動(dòng)注銷了,這種注銷其實(shí)也很簡單:

var unwatch = app.$watch('temperature',function(newVal,oldVal){
    if(newVal>=26){
        this.suggestion=suggestion[0];
    }else if(newVal<26 && newVal >=0)
    {
        this.suggestion=suggestion[1];
    }else{
        this.suggestion=suggestion[2];
    }
})

unWatch(); // 手動(dòng)注銷watch

app.$watch調(diào)用后會(huì)返回一個(gè)值,就是unWatch方法,你要注銷 watch 只要調(diào)用unWatch方法就可以了。

5. mixins 混入選項(xiàng)

混入 (mixins) 是一種分發(fā) Vue 組件中可復(fù)用功能的非常靈活的方式?;烊雽ο罂梢园我饨M件選項(xiàng)。當(dāng)組件使用混入對象時(shí),所有混入對象的選項(xiàng)將被混入該組件本身的選項(xiàng)。

mixins一般有兩種用途:

  1. 在你已經(jīng)寫好了構(gòu)造器后,需要增加方法或者臨時(shí)的活動(dòng)時(shí)使用的方法,這時(shí)用混入會(huì)減少源代碼的污染。
  2. 很多地方都會(huì)用到的公用方法,用混入的方法可以減少代碼量,實(shí)現(xiàn)代碼重用。

現(xiàn)在有個(gè)數(shù)字點(diǎn)擊遞增的程序,假設(shè)已經(jīng)完成了,這時(shí)希望每次數(shù)據(jù)變化時(shí)都能夠在控制臺(tái)打印出提示:“數(shù)據(jù)發(fā)生變化”:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>Mixins Option</title>
</head>
<body>
    <h1>Mixins Option Demo</h1>
    <hr>
    <div id="app">
        <p>num: {{ num }}</p>
        <P><button @click="add">增加數(shù)量</button></P>
    </div>
    <script type="text/javascript">
        //額外臨時(shí)加入,用于顯示日志
        var addLog={
            updated:function(){
                console.log("數(shù)據(jù)放生變化,變化成"+this.num+".");
            }
        }

        var app=new Vue({
            el:'#app',
            data:{
                num:1
            },
            methods:{
                add:function(){
                    this.num++;
                }
            },
            //混入
            mixins:[addLog]
        })
    </script>
</body>
</html>

選項(xiàng)合并:

當(dāng)組件和混入對象含有同名選項(xiàng)時(shí),這些選項(xiàng)將以恰當(dāng)?shù)姆绞交旌?,合并?guī)則:

  1. 值為對象的選項(xiàng),例如數(shù)據(jù)對象data、方法對象methods、組件對象components和自定義指令對象directives,將被混合為同一個(gè)對象。兩個(gè)對象鍵名沖突時(shí),取組件對象的鍵值對。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>Mixins Option</title>
</head>
<body>
    <h1>Mixins Option Demo</h1>
    <hr>
    <div id="app">
        <p>num: {{ num }}</p>
        <P><button @click="add">增加數(shù)量</button></P>
    </div>
    <script type="text/javascript">
        //額外臨時(shí)加入,用于顯示日志
        var addLog={
            data: function () {
                return {
                    message: 'hello',
                    foo: 'abc'
                }
            },
            updated () {
                console.log("數(shù)據(jù)放生變化,變化成"+this.num+".");
            },
            created () {
                console.log('混入對象的鉤子被調(diào)用==>', this.$data)
            }
        }

        var app=new Vue({
            el:'#app',
            data:{
                num:1,
                message: 'goodbye',
                bar: 'def'
            },
            methods:{
                add:function(){
                    this.num++;
                }
            },
            created () {
                console.log('實(shí)例鉤子被調(diào)用==>', this.$data)
            },
            //混入
            mixins:[addLog]
        })
    </script>
</body>
</html>

打開控制臺(tái)可以看到,混入的created鉤子函數(shù)和實(shí)例的created鉤子函數(shù)打印出的this.$data都為{bar: "def", foo: "abc", message: "goodbye", num: 1}。

  1. 由1的例子可以看出,同名鉤子函數(shù)將混合為一個(gè)數(shù)組,因此都將被調(diào)用。另外,混入對象的鉤子將在組件自身鉤子之前調(diào)用。

mixins的調(diào)用順序:

從執(zhí)行的先后順序來說,都是混入的先執(zhí)行,然后構(gòu)造器里的再執(zhí)行,需要注意的是,這并不是方法的覆蓋,而是被執(zhí)行了兩邊。

同名鉤子函數(shù)將混合為一個(gè)數(shù)組,因此都將被調(diào)用。混入對象的鉤子將在組件自身鉤子之前調(diào)用。

全局API混入方式:

可以全局注冊混入對象。但應(yīng)注意使用!因?yàn)橐坏┦褂萌只烊雽ο螅瑢?huì)影響到所有之后創(chuàng)建的 Vue 實(shí)例。

定義全局的混入,然后在需要這段代碼的地方直接引入js,就可以擁有這個(gè)功能了:

Vue.mixin({
    updated:function(){
        console.log('我是全局被混入的');
    }
})

注意:全局混入的執(zhí)行順序要前于混入和構(gòu)造器里的方法。

完整代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>Mixins Option</title>
</head>
<body>
    <h1>Mixins Option Demo</h1>
    <hr>
    <div id="app">
        <p>num: {{ num }}</p>
        <P><button @click="add">增加數(shù)量</button></P>
    </div>
    <script type="text/javascript">
        //全局混入
        Vue.mixin({
            created () {
                console.log('我是全局混入');
            }
        })

        //額外臨時(shí)加入,用于顯示日志
        var addLog={
            data: function () {
                return {
                    message: 'hello',
                    foo: 'abc'
                }
            },
            updated () {
                console.log("數(shù)據(jù)放生變化,變化成"+this.num+".");
            },
            created () {
                console.log('混入對象的鉤子被調(diào)用==>', this.$data)
            }
        }

        var app=new Vue({
            el:'#app',
            data:{
                num:1,
                message: 'goodbye',
                bar: 'def'
            },
            methods:{
                add:function(){
                    this.num++;
                }
            },
            created () {
                console.log('實(shí)例鉤子被調(diào)用==>', this.$data)
            },
            //混入
            mixins:[addLog]
        })
    </script>
</body>
</html>

6. extends Option 擴(kuò)展選項(xiàng)

通過外部增加對象的形式,對構(gòu)造器進(jìn)行擴(kuò)展。允許聲明擴(kuò)展另一個(gè)組件(可以是一個(gè)簡單的選項(xiàng)對象或構(gòu)造函數(shù)),而無需使用 Vue.extend。這主要是為了便于擴(kuò)展單文件組件。和 mixins 類似。

選項(xiàng)合并:

當(dāng)組件和擴(kuò)展對象含有同名選項(xiàng)時(shí),這些選項(xiàng)將以恰當(dāng)?shù)姆绞交旌?,合并?guī)則:

  1. 值為對象的選項(xiàng),例如數(shù)據(jù)對象data、方法對象methods、組件對象components和自定義指令對象directives,將被混合為同一個(gè)對象。兩個(gè)對象鍵名沖突時(shí),取組件對象的鍵值對。
  2. 同名鉤子函數(shù)將混合為一個(gè)數(shù)組,因此都將被調(diào)用。另外,擴(kuò)展對象的鉤子將在組件自身鉤子之前調(diào)用。

完整代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Extends Optin</title>
    <script type="text/javascript" src="../assets/js/vue.js"></script>
</head>
<body>
    <h1>Extends Optin Demo</h1>
    <hr>
    <div id="app">
        {{message}}
        <p><button @click="add">add</button></p>
    </div>
    <script type="text/javascript">
        var bbb={
            created () {
                console.log("我是擴(kuò)展出來的鉤子函數(shù)");
            },
            methods:{
                add () {
                    console.log('我是被擴(kuò)展出來的方法!');
                }
            }
        };

        var app=new Vue({
            el:'#app',
            data:{
                message:'hello Vue!'
            },
            methods:{
                add () {
                    console.log('我是原生方法');
                }
            },
            created () {
                console.log("我是原生的鉤子函數(shù)");
            },
            extends:bbb
        })
    </script>
</body>
</html>

打開控制臺(tái)可以看到,擴(kuò)展出來的鉤子函數(shù)先執(zhí)行,然后是實(shí)例的鉤子函數(shù);點(diǎn)擊按鈕之后只有實(shí)例的方法被執(zhí)行。

7. delimiters 選項(xiàng)

delimiters的作用是改變插值的符號(hào)。Vue默認(rèn)的插值是雙大括號(hào){{}}。但有時(shí)我們會(huì)有需求更改這個(gè)插值的形式。

比如后臺(tái)渲染模板如swig,也使用“{{ }}“作為渲染,與前端vue的數(shù)據(jù)綁定“Mustache”語法 (雙大括號(hào))產(chǎn)生沖突,此時(shí)只要在新建Vue對象時(shí),添加delimiters: ['${', '}'],就搞定了。

現(xiàn)在插值形式就變成了${}。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>delimiters Option</title>
</head>
<body>
    <h1>delimiters Option</h1>
    <hr>
    <div id="app">
        <ul>
            <li v-for=" aa in arr">${aa}</li>
        </ul>
    </div>
    <script type="text/javascript">

        var outData={
            arr:['aaa','bbb','ccc'],
        };

        var app=new Vue({
            delimiters: ['${', '}'],
            el: '#app',
            data: outData
        })
    </script>
</body>
</html>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,067評論 0 29
  • Vue 實(shí)例 屬性和方法 每個(gè) Vue 實(shí)例都會(huì)代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,231評論 0 6
  • # 傳智播客vue 學(xué)習(xí)## 1. 什么是 Vue.js* Vue 開發(fā)手機(jī) APP 需要借助于 Weex* Vu...
    再見天才閱讀 3,582評論 0 6
  • VUE Vue :數(shù)據(jù)驅(qū)動(dòng)的M V Vm框架 m :model(后臺(tái)提供數(shù)據(jù)),v :view(頁面),vM(模板...
    wudongyu閱讀 5,416評論 0 11
  • 2018-06-05 姓名:姜潔 揚(yáng)州市方圓建筑工程有限公司 377期利他2組 【日精進(jìn)打卡第45天】 【知~背誦...
    若塵_fca9閱讀 197評論 0 0