Vue成神之路之選項

前言

記錄平時學到的知識,標題寫的大氣一點,也算是給自己一點鼓勵,希望在技術這條路可以遠走越遠,路越走越寬~

文中代碼地址

PS:如果對你有一點幫助,請順手給個小星星哦,鼓勵我繼續寫下去~

引入的文件文件說明

vue.js——開發版本:包含完整的警告和調試模式 vue.min.js——生產版本:刪除了警告,進行了壓縮

1. propsData Option 全局擴展的數據傳遞

propsData在實際開發中使用的並不多,用在全局擴展時進行傳遞數據,主要搭配Vue.extend使用。

在實際的項目中,使用全局擴展的方式製作自定義標籤比較少用,完全可以使用組件來替代。

<!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>

擴展標籤已經做好了,這時要在掛載時傳遞數據,就用到了propsData。

使用用propsData三步解決傳值:

  1. 在全局擴展里加入props進行接收;
  2. 傳遞時用propsData進行傳遞;
  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 計算選項

computed計算屬性的主要作用是在數據渲染之前,根據實際需求對數據進行處理,比如:大小寫轉換,順序重排,添加符號……。爲了不污染data中定義的數據源,在computed裏需要新聲明一個對象保存處理之後的數據。

computed計算屬性的所有getter和setter的this上下文自動地綁定爲 Vue 實例。注意如果你爲一個計算屬性使用了箭頭函數,則 this 不會指向這個組件的實例,不過你仍然可以將其實例作爲函數的第一個參數來訪問。

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

計算屬性的結果會被緩存,除非依賴的響應式屬性變化纔會重新計算。注意,如果某個依賴 (比如非響應式屬性) 在該實例範疇之外,則計算屬性是不會被更新的。

用計算屬性反轉新聞數據數組,讓最近發生的新聞放在前面顯示,demo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../assets/js/vue.js"></script>
    <title>computed 計算選項</title>
</head>
<body>
    <h1>computed 計算選項</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:'香港或就“裝甲車被扣”事件追責 起訴涉事運輸公司',date:'2017/3/10'},
            {title:'日本第二大準航母服役 外媒:針對中國潛艇',date:'2017/3/12'},
            {title:'中國北方將有明顯雨雪降溫天氣 南方陰雨持續',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 計算屬性是非常有用並且在實際的項目開發中經常使用,它在輸出數據前可以根據實際項目需求對數據進行處理,改變數據。

3. methods Option 方法選項

在Vue中,可以使用v-on給元素綁定事件,在methods選項中處理一些邏輯方面的事情。在Vue中的邏輯處理,一般都在Vue的methods選項中來處理,那是因爲很多事件處理邏輯代碼都很複雜,如果直接把JavaScript代碼寫在v-on指令中有時並不可行,所以在methods中定義方法,讓v-on指令來接收(調用)。

一個數字,每點擊一下按鈕加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中參數的傳遞:

使用方法和正常的javascript傳遞參數的方法一樣,分爲兩步:

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

給add添加num參數,並在按鈕上調用傳遞:

<!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>

這時,再點擊按鈕時結果每次加2。

methods中的$event參數:

傳遞的$event參數都是關於你點擊鼠標的一些事件和屬性。傳遞方法:

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

這時候可以打印一下,看看event到底是個怎樣的對象。你會發現,它包含了大部分鼠標事件的屬性:

<!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 給組件綁定構造器裏的原生事件:

在實際開發中經常需要把某個按鈕封裝成組件,然後反覆使用,如何讓組件調用構造器裏的方法,而不是組件裏的方法。就需要用到.native修飾器了。

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

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

在構造器裏註冊組件:

components:{
    "btn":btn
}

用.native修飾器來調用構造器裏的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>

作用域外部調用構造器裏的方法:

這種不經常使用,如果你出現了這種情況,說明你的代碼組織不夠好。

<button onclick="app.add(4)" >外部調用構造器裏的方法</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')">外部訪問構造器裏的方法</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 選項 監控數據

使用watch選項來監控數據的變化。watch選項對應一個對象,鍵是觀察表達式,值是對應回調。值也可以是方法名,或者是對象,包含選項。在實例化時爲每個鍵調用 $watch() 。

天氣預報的穿衣指數,它主要是根據溫度來進行提示,溫度大於26度時,建議穿T恤短袖,溫度小於26度大於0度時,建議穿夾克長裙,溫度小於0度時建議穿棉衣羽絨服:

<!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 的一個特點是,最初綁定的時候是不會執行的,要等到 temperature 改變時才執行監聽計算。那我們想要一開始就讓它最初綁定的時候就執行改怎麼辦呢?我們需要修改一下我們的 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這個方法之後立即先去執行handler方法
                    immediate: true
                }
            }
        })
    </script>
</body>
</html>

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

而immediate:true代表如果在 wacth 裏聲明瞭 temperature 之後,就會立即先去執行裏面的handler方法,如果爲 false就跟我們以前的效果一樣,不會在綁定的時候就執行。

在上面的事例中把suggestion的初始數據設置爲'T恤短袖',而初始溫度是14°C,這時如果沒有讓watch在最初綁定的時候就執行,那麼推薦的穿衣就有問題,因爲14°C原本是推薦穿'夾克長裙'的,通過讓watch在最初綁定的時候就執行完美解決了這個問題。

deep屬性: watch 裏面還有一個屬性 deep,默認值是 false,代表是否深度監聽,比如我們 data 裏有一個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>

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

默認情況下 handler 只監聽obj這個屬性它的引用的變化,我們只有給obj賦值的時候它纔會監聽到,比如我們在 mounted事件鉤子函數中對obj進行重新賦值:

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

這樣我們的 handler 纔會執行。

如果需要監聽obj裏的屬性temperature的值,這時候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的意思就是深入觀察,監聽器會一層層的往下遍歷,給對象的所有屬性都加上這個監聽器,但是這樣性能開銷就會非常大了,任何修改obj裏面任何一個屬性都會觸發這個監聽器裏的 handler。

優化,可以使用字符串形式監聽:

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纔會一層一層解析下去,直到遇到屬性temperature,然後纔給temperature設置監聽函數。

完整代碼:

<!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
            //     }
            // }

            //優化使用字符串形式監聽
            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>

用實例屬性寫watch監控:

有些時候我們會用實例屬性的形式來寫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:'夾克長裙'
            },
            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?因爲我們的組件是經常要被銷燬的,比如我們跳一個路由,從一個頁面跳到另外一個頁面,那麼原來的頁面的 watch 其實就沒用了,這時候我們應該註銷掉原來頁面的 watch 的,不然的話可能會導致內置溢出。當把 watch 寫在組件的選項中的,它會隨着組件的銷燬而銷燬。

但是,如果我們使用上面的這樣的方式寫 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];
    }
})

那麼就要手動註銷了,這種註銷其實也很簡單:

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(); // 手動註銷watch

app.$watch調用後會返回一個值,就是unWatch方法,你要註銷 watch 只要調用unWatch方法就可以了。

5. mixins 混入選項

混入 (mixins) 是一種分發 Vue 組件中可複用功能的非常靈活的方式。混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被混入該組件本身的選項。

mixins一般有兩種用途:

  1. 在你已經寫好了構造器後,需要增加方法或者臨時的活動時使用的方法,這時用混入會減少源代碼的污染。
  2. 很多地方都會用到的公用方法,用混入的方法可以減少代碼量,實現代碼重用。

現在有個數字點擊遞增的程序,假設已經完成了,這時希望每次數據變化時都能夠在控制檯打印出提示:“數據發生變化”:

<!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">增加數量</button></P>
    </div>
    <script type="text/javascript">
        //額外臨時加入,用於顯示日誌
        var addLog={
            updated:function(){
                console.log("數據放生變化,變化成"+this.num+".");
            }
        }

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

選項合併:

當組件和混入對象含有同名選項時,這些選項將以恰當的方式混合,合併規則:

  1. 值爲對象的選項,例如數據對象data、方法對象methods、組件對象components和自定義指令對象directives,將被混合爲同一個對象。兩個對象鍵名衝突時,取組件對象的鍵值對。
<!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">增加數量</button></P>
    </div>
    <script type="text/javascript">
        //額外臨時加入,用於顯示日誌
        var addLog={
            data: function () {
                return {
                    message: 'hello',
                    foo: 'abc'
                }
            },
            updated () {
                console.log("數據放生變化,變化成"+this.num+".");
            },
            created () {
                console.log('混入對象的鉤子被調用==>', this.$data)
            }
        }

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

打開控制檯可以看到,混入的created鉤子函數和實例的created鉤子函數打印出的this.$data都爲{bar: "def", foo: "abc", message: "goodbye", num: 1}

  1. 由1的例子可以看出,同名鉤子函數將混合爲一個數組,因此都將被調用。另外,混入對象的鉤子將在組件自身鉤子之前調用。

mixins的調用順序:

從執行的先後順序來說,都是混入的先執行,然後構造器裏的再執行,需要注意的是,這並不是方法的覆蓋,而是被執行了兩邊。

同名鉤子函數將混合爲一個數組,因此都將被調用。混入對象的鉤子將在組件自身鉤子之前調用。

全局API混入方式:

可以全局註冊混入對象。但應注意使用!因爲一旦使用全局混入對象,將會影響到所有之後創建的 Vue 實例。

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

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

注意:全局混入的執行順序要前於混入和構造器裏的方法。

完整代碼:

<!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">增加數量</button></P>
    </div>
    <script type="text/javascript">
        //全局混入
        Vue.mixin({
            created () {
                console.log('我是全局混入');
            }
        })

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

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

6. extends Option 擴展選項

通過外部增加對象的形式,對構造器進行擴展。允許聲明擴展另一個組件(可以是一個簡單的選項對象或構造函數),而無需使用 Vue.extend。這主要是爲了便於擴展單文件組件。和 mixins 類似。

選項合併:

當組件和擴展對象含有同名選項時,這些選項將以恰當的方式混合,合併規則:

  1. 值爲對象的選項,例如數據對象data、方法對象methods、組件對象components和自定義指令對象directives,將被混合爲同一個對象。兩個對象鍵名衝突時,取組件對象的鍵值對。
  2. 同名鉤子函數將混合爲一個數組,因此都將被調用。另外,擴展對象的鉤子將在組件自身鉤子之前調用。

完整代碼:

<!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("我是擴展出來的鉤子函數");
            },
            methods:{
                add () {
                    console.log('我是被擴展出來的方法!');
                }
            }
        };

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

打開控制檯可以看到,擴展出來的鉤子函數先執行,然後是實例的鉤子函數;點擊按鈕之後只有實例的方法被執行。

7. delimiters 選項

delimiters的作用是改變插值的符號。Vue默認的插值是雙大括號{{}}。但有時我們會有需求更改這個插值的形式。

比如後臺渲染模板如swig,也使用“{{ }}“作爲渲染,與前端vue的數據綁定“Mustache”語法 (雙大括號)產生衝突,此時只要在新建Vue對象時,添加delimiters: ['${', '}'],就搞定了。

現在插值形式就變成了${}。

<!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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章