Vue.js 內置指令

        Vue.js 的指令是帶有特殊前綴 「v-「 的 HTML 特性。它綁定一個表達式,並將一些特性應用到 DOM 上。javascript

1、基本指令

1.1 v-cloak

        v-cloak 不須要表達式,它會在 Vue 實例結束編譯時從綁定的 HTML 元素上移除,常常和 CSS 的 display: none ;配合使用:css

<div id="app" v-cloak>
        {{ message }}
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: '這是一段文本'
            }
        })
    </script>

        這時雖然已經加了指令 v-cloak ,但其實並無起到任何做用,當網速較慢、Vue.js 文件尚未加載完時,在頁面上會顯示 {{ message }} 的字樣,直到 Vue 建立實例、編譯模板時,DOM 纔會被替換,因此這個過程屏幕是有閃動的。只要加一句 CSS 就能夠解決這個問題了:html

[v-cloak] {
        display: none;
    }

        在通常狀況下,v-cloak 是一個解決初始化慢致使頁面閃動的最佳實踐,對於簡單的項目很實用,可是在具備工程化的項目裏,好比在項目的 HTML 機構只有一個空的 div 元素,剩餘的內容都是由路由去掛載不一樣組件完成的,因此再也不須要 v-cloak 。java

1.2 v-once

        v-once 也是一個不須要表達式的指令,做用是定義它的元素或組件只渲染一次,包括元素或組件的全部子節點。首次渲染後,再也不隨數據的變化從新渲染,將被視爲靜態內容,例如:webpack

<div id="app">
    <span v-once>{{ message }}</span>
    <div v-once>
        <span>{{ message }}</span>
    </div>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: '這是一段文本'
        }
    })
</script>

        v-once 在業務中不多使用,但當須要進一步優化性能時,可能會用到。web

2、條件渲染指令

2.1 v-if,v-else-if,v-else

        與 JavaScript 的條件語句 if、else、else if 相似,Vue.js 的條件指令能夠根據表達式的值在 DOM 中渲染或銷燬元素/組件,例如:數組

<div id="app">
    <p v-if="status === 1">當status爲1時顯示該行</p>
    <p v-else-if="status === 2">當status爲2時顯示該行</p>
    <p v-else>不然顯示該行</p>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            status: 1
        }
    })
</script>

        v-else-if 要緊跟 v-if,v-else 要緊跟 v-else-if 或 v-if ,表達式的值爲真時,當前元素/組件及全部子節點將被渲染,爲假時被移除。若是一次判斷的是多個元素,能夠在 Vue.js 內置的<template>元素上使用條件指令,最終渲染的結果不會包含該元素,例如:app

<div id="app">
    <template v-if="status ==== 1">
        <p>這是一段文本</p>
        <p>這是一段文本</p>
        <p>這是一段文本</p>
    </template>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            status: 1
        }
    })
</script>

        Vue 在渲染元素時,出於效率考慮,會盡量地複用已有的元素而非從新渲染,好比下面的示例:函數

<div id="app">
        <template v-if="type === 'name'">
            <label>用戶名:</label>
            <input placeholder="輸入用戶名"》
        </template>
        <template v-else>
            <label>郵箱:</label>
            <input placeholder="輸入郵箱"》
        </template>
        <button @click="handleToggleClick">切換輸入類型</button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                type: 'name'
            },
            nethods: {
                handleToggleClick: function() {
                    this.type = this.type === 'name' ? 'mail' : 'name';
                }
            }
        })
    </script>

        這樣鍵入內容後,點擊切換按鈕,雖然 DOM 變了,可是以前在輸入框鍵入的內容並無改變,只是替換了 placeholder 的內容,說明 <inpout> 元素被複用了。組件化

        若是不但願這樣複用,可使用 Vue.js 提供的 key 屬性,它可讓你本身決定是否要複用元素,key 的值必須惟一的,例如:

<div id="app">
        <template v-if="type === 'name'">
            <label>用戶名:</label>
            <input placeholder="輸入用戶名" key="name-input">
        </template>
        <template v-else>
            <label>郵箱:</label>
            <input placeholder="輸入郵箱" key="mail-input">
        </template>
        <button @click="handleToggleClick">輸入類型切換</button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                type: 'name'
            },
            methods: {
                handleToggleClick: function() {
                    this.type = this.type === 'name' ? 'mail' : 'name';
                }
            }
        })
    </script>

2.2 v-show

        v-show (v-show 不能在<template>上使用)的用法與 v-if 基本一致,只不過 v-show 是改變元素的 CSS 屬性 display 。當 v-show 表達式的值爲 false 時,元素會隱藏,查看 DOM 結構會看到元素上加載了內聯樣式 display: none;,例如:

<div id="app">
        <p v-show="status === 0">當 status 爲 0 時顯示該行</p>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                status: 1
            }
        })
    </script>

        渲染後的結果爲:

<p style="dispaly: none;">當 status 爲 1 時顯示該行</p>

2.3 v-if 與 v-show 的選擇

        v-if 和 v-show 具備相似的功能,不過 v-if 纔是真正的條件渲染,它會根據表達式適當地銷燬或重建元素及綁定的事件或子組件。若表達式初始值爲 false ,則一開始元素/組件並不會渲染,只有當條件第一次變爲真時纔開始編譯。

        而 v-show 只是簡單的 CSS 屬性切換,不管條件真與否,都會被編譯。相比之下,v-if 更適合條件不常常改變的場景,由於它切換開銷相對較大,而 v-show 適用於頻繁切換條件。

3、列表渲染指令 v-for

3.1 基本用法

        當須要一個數組遍歷或枚舉一個對象循環顯示時,就會用到列表渲染指令 v-for 。它的表達式須要結合 in 來使用,相似 item in items 的形式,例如:

<div id="app">
    <ul>
        <li v-for="book in books">{{ book.name }}</li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                { name: '《Oracle 從刪庫到跑路》'},
                { name: '《MySql 從刪庫到跑路》' },
                { name: '《JavaScript 高級程序設計》' }
            ]
        }
    })
</script>

        在表達式中,books 是數據,book 是當前數組元素的別名,循環出的每一個 <li> 內的元素均可以訪問到對應的當前數據 book 。列表渲染也支持用 of 來代替 in 做爲分割符,它更接近 JavaScript 迭代器的語法:

<li v-for="book of books">{{ book.name }}</li>

        v-for 的表達式支持一個可選參數做爲當前項的索引,例如:

<div id="app">
    <ul>
        <li v-for="book in books">{{ index }} - {{ book.name }}</li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                { name: '《Oracle 從刪庫到跑路》'},
                { name: '《MySql 從刪庫到跑路》' },
                { name: '《JavaScript 高級程序設計》' }
            ]
        }
    })
</script>

        分割符 in 前的語句使用括號,第二項就是 books 當前項的索引 (在 Vue.js 1.x 的版本,這裏的 index 也能夠由內置的 $index 代替,不過,在 2.x 版本里取消了該用法)。

        與 v-if 同樣,v-for 也能夠用在內置標籤 <template> 上,將多個元素進行渲染:

<div id="app">
    <ul>
        <template v-for="book in books">
            <li>書名:{{ book.name }}</li>
            <li>做者:{{ book.author }}</li>
        </template>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    name: '《Oracle 從入門到跑路》',
                    author: 'Mart'
                },
                {
                    name: '《MySql 從入門到跑路》',
                    author: '尹成'
                },
                {
                    name: '《JavaScript 高級程序設計》',
                    author: 'Nicholas C.Zakas'
                }
            ]
        }
    })
</script>

        除數組外,對象的屬性也是能夠遍歷的,例如:

<div id="app">
    <span v-for="value in user">{{ value }}</span>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            user: {
                name: '王麻子',
                gender: '男',
                age: 28
            }
        }
    })
</script>

        渲染後的結果爲:

<span>王麻子</span><span>男</span><span>28</span>

        遍歷對象屬性時,有兩個可選參數,分別是鍵名和索引:

<div id="app">
    <ul>
        <li v-for="(value, key, index) in user" >
            {{ index }} - {{ key }} : {{ value }}
        </li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            user: {
                name: '王麻子',
                gender: '男',
                age: 28
            }
        }
    })
</script>

        v-for 還能夠迭代整數:

<div id="app">
    <span v-for="n in 100">{{ n }}</span>
</div>
<script>
    var app = new Vue({
        el: '#app'
    })
</script>

3.2 數組更新

        Vue 的核心是數據與視圖的雙向綁定,當咱們修改數組時,Vue 會檢測到數據變化,因此用 v-for 渲染的視圖也會當即更新。Vue 包含了一組觀察數組變異的方法,使用它們改變數組也會觸發視圖更新:

        ·    push()

        ·    pop()

        ·    shift()

        ·    unshift()

        ·    splice()

        ·    sort()

        ·    reverse()

        例如,將以前的示例的數據 books 添加一項:

app.books.push({
    name: '《CSS揭祕》',
    author: '[希] Lea Verou'
});

        使用上述方法會改變被這些方法調用的原始數組,有些方法不會改變原數組,例如:

        ·    filter()

        ·    concat()

        ·    slice()

        它們返回的是一個新數組,在使用這些非變異方法時,能夠用新數組來替換原數組,仍是以前展現示例,找出含有 JavaScript 關鍵詞的書目,例如:

        

<div id="app">
    <ul>
        <template v-for="book in books">
            <li>書名:{{ book.name }}</li>
            <li>做者:{{ book.author }}</li>
        </template>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    name: '《Oracle 從入門到跑路》',
                    author: 'Mart'
                },
                {
                    name: '《MySql 從入門到跑路》',
                    author: '尹成'
                },
                {
                    name: '《JavaScript 高級程序設計》',
                    author: 'Nicholas C.Zakas'
                }
            ]
        }
    });

    app.books = app.books.filter(function (item) {
        return item.name.match(/JavaScript/);
    });
</script>

        渲染的結果中,只顯示了書名中含有 JavaScript 的選項。

        Vue 在檢測到數組變化時,並非直接從新渲染整個列表,而是最大化地複用 DOM 元素。替換的數組中,含有相同元素的項不會被從新渲染,所以能夠大膽地用新數組來替換舊數組,不用擔憂性能問題。

        須要注意的是,如下變更的數組中,Vue 是不能檢測到的,也不會觸發視圖更新:

        ·    經過索引直接設置項,好比 app.books[2]={...} 。

        ·    修改數組長度,好比 app.books.length = 1 。

        解決第一個問題能夠用兩種方法實現一樣的效果,第一種是使用 Vue 內置的 set 方法:

Vue.set(app.books, 3, {
    name: '《CSS 揭祕》',
    author: '[希] Lea Verou'
});

        若是是在 webpack 中使用組件化的方式,默認是沒有導入 Vue 的,這是可使用 $set ,例如:

this.$set(app.books, 3, {
    name: '《CSS 揭祕》',
    author: '[希] Lea Verou'
})

        這裏的 this 指向的就是當前組件實例,即 app 。在非 webpack 模式下也能夠用 $set 方法,例如 app.$set(...) 。另外一種方法:

app.books.splice(3, 1, {
    name: '《CSS 揭祕》',
    author: '[希] Lea Verou'
})

        第二個問題也能夠直接用 splice 來解決:

app.books.splice(1);

3.3 過濾與排序

        當你不想改變原數組,想經過一個數組的副原本作過濾或排序的顯示時,可使用計算屬性來返回過濾或排序後的數組,例如:

<div id="app">
    <ul>
        <template v-for="book in filterBooks">
            <li>書名:{{ book.name }}</li>
            <li>做者:{{ book.author }}</li>
        </template>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    name: '《Oracle 從入門到跑路》',
                    author: 'Mart'
                },
                {
                    name: '《MySql 從入門到跑路》',
                    author: '尹成'
                },
                {
                    name: '《JavaScript 高級程序設計》',
                    author: 'Nicholas C.Zakas'
                }
            ]
        },
        computed: {
            filterBooks: function () {
                return this.books.filter(function (book){
                    return book.name.match(/JavaScript/);
                });
            }
        }
    })
</script>

        上例是把書名中包含 JavaScript 關鍵詞的數據過濾出來,計算屬性 filterBooks 依賴 books,可是不會修改 books 。實現排序也是相似的,好比:

sortedBooks: function () {
                return this.books.sort(function (a, b){
                    return a.name.length < b.name.length;
                });
            }

        在 Vue.js 2.x 中廢棄了 1.x 中內置的 limitBy,filterBy 和 orderBy 過濾器,統一改用計算屬性來實現。

4、方法與事件

4.1 基本用法

        Vue 事件處理的概念 v-on ,在事件綁定上,相似原生 JavaScript 的 onclick 等寫法,也是 HTML 上進行監聽的。好比,監聽一個按鈕的點擊事件,設置一個計數器,每次點擊都加 1 :

<div id="app">
    點擊計數:{{ counter }}
    <button @click="counter++">+ 1</button>
</div>
<script>
    new Vew({
        el: '#app',
        data: {
            counter: 0
        }
    })
</script>

        @click 的表達式能夠直接使用 JavaScript 語句,也能夠是一個在 Vue 實例中 methods 選項內的函數名,好比對上例進行擴展,再增長一個按鈕,點擊一次,計數器加100 ;

<div id="app">
    點擊計數:{{ counter }}
    <button @click="handleAdd()">+ 1</button>
    <button @click="handleAdd(100)">+ 100</button>
</div>
<script>
    new Vew({
        el: '#app',
        data: {
            counter: 0
        },
        methods: {
            handleAdd: function (count) {
                count = count || 1;
                // this 指向當前 Vue 實例 app
                this.counter += count;
            }
        }
    })
</script>

        在 methods 中定義了咱們須要的方法供 @click 調用,須要注意的是,@click 調用的方法名後能夠不跟括號「()」。此時,若是該方法有參數,默認會將原生對象 event 傳入。      

        這種在 HTML 元素上監聽事件的設計看似將 DOM 與 JavaScript 緊耦合,違背分離的的原理,實則恰好相反。由於經過HTML 就能夠知道調用的是哪一個方法,將邏輯與 DOM 解耦,便於維護。最重要的是,當 ViewModel 銷燬時,全部的事件處理器都會自動刪除,無須本身清理。

        Vue 提供了一個特殊變量 $event , 用於訪問原生 DOM 事件,好比,能夠阻止連接打開:

<div id="app">
    <a href="https://www.baidu.com" @click="handleClick('禁止打開', $event)">打開連接</a>
</div>
<script>
    var app = new Vue({
        el: '#app',
        methods: {
            handleClick: function (message, event) {
                event.preventDefault();
                window.alert(message);
            }
        }
    })
</script>

4.2 修飾符

        上述使用的 event.preventDefault() 也能夠用 Vue 事件的修飾符來實現,在 @綁定的事件後加小圓點」 . 「,再跟一個後綴來使用修飾符。Vue 支持如下修飾符:

        ·    .stop

        ·    .prevent

        ·    .capture

        ·    .self

        ·    .once

        具體用法以下:

<!-- 阻止單擊事件冒泡  -->
<a @click.stop="handle"></a>
<!-- 提交事件再也不重載頁面 -->
<form @submit.prevent="handle"></form>
<!-- 修飾符能夠串聯 -->
<a @click.stop.prevent="handle"></a>
<!-- 只有修飾符 -->
<form @submit.prevent></form>
<!-- 添加事件監聽器時使用事件捕獲模式 -->
<div @click.capture="handle">...</div>
<!-- 只當事件在該元素自己(而不是子元素)觸發時觸發回調 -->
<div @click.self="handle">...</div>
<!-- 只觸發一次,組件一樣適用 -->
<div @click.once="handle">...</div>

        在表單元素上監聽鍵盤事件時,還可使用按鍵修飾符,好比按下具體某個鍵時才調用方法:

<!-- 只有在 keyCode 是 32 時調用 vm.submit() -->
<input @keyup.32="submit">
<!-- 也能夠本身配置具體按鍵 -->
Vue.config.keyCodes.f1 = 112;       // 全局定義後,就可使用 @keyup.f1

        除了具體的某個 keyCode 外,Vue 還提供了一些快捷名稱,如下是所有的別名:

        ·    .enter

        ·    .tab

        ·    .delate (捕獲 」刪除「 和 」退格「 鍵)

        ·    .esc

        ·    .space

        ·    .up

        ·    .down

        ·    .left

        ·    .right

        這些按鍵修飾符也能夠組合使用,或和鼠標一塊兒配合使用:

        ·    .ctrl

        ·    .alt

        ·    .shift

        ·    .meta (Mac 下是 Command 鍵,Windows 下是窗口鍵)

        例如:

<!-- Shift + S -->
<input @keyup.shift.83="handleSave">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do someting</div>
相關文章
相關標籤/搜索