vue學習之路 - 4.基本操作(下)
vue學習之路 - 4.基本操作(下)
簡述:本章節主要介紹 vue 的一些其他常用指令。
Vue 指令
這裏將 vue 的指令分為系統內部指令(vue 自帶指令)和用戶自定義指令兩種。
系統內部指令
v-if
v-else
v-else-if
v-for
v-on
v-bind
v-model
以上指令前面都已說明其作用,並且使用過,這裏將不再贅述。
下面我們看看 vue 的一些其他常用指令的用法:
在學習 v-text 和 v-cloak 之前我們先看看{{ }}的使用所存在的問題。
{{ }}存在的問題:頁面初始化時,可能會出現閃爍問題。當數據量越大的時候,這個問題就更加明顯。
如下面這段代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue- {{ }} 的閃爍問題</title> </head> <body> <!----------{{ }} 存在的閃爍問題------------------------------> <!-- 為什麽{{ }}會在頁面加載時出現閃爍? 答:瀏覽器自上而下一次對頁面代碼進行解析,當解析到<h1>{{ foo }}</h1>的時候,瀏覽器會直接把{{ foo }} 當做h1標簽的內容直接渲染出來。 然後解析到了Vue之後,Vue就要從入口管理模板,解析{{ foo }}變成了foo的值:hello 中間這個階段就會一閃而過。{{ }}的閃爍問題演示代碼--> <div id="app"> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> // 得到 Vue 實例const app = new Vue({ el: ‘#app‘, data: { foo : ‘hello‘ } }) </script> </body> </html>
運行效果:初次加載或者重新加載界面,都有可能會在界面閃一下顯示出{{ }}的符號。
解決{{ }}閃爍問題的方案有兩種:
① 使用v-text指令,替換{{ }}
② 使用v-cloak指令,作用與整個被vue 管理的 div 塊。
詳情請看下面 v-text 和 v-cloak 指令介紹。
v-text
v-text 的使用效果和{{ }}的作用差不多,但是 v-text 不存在閃爍問題。
v-text使用Demo:
- 和{{ }}一樣的,唯一的區別就是,{{ }}會造成閃爍問題,v-text不會造成閃爍問題
- 如果還想用{{ }}又不想有閃爍問題,則用v-cloak指令來處理。(詳情看v-cloak指令)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue-指令 v-text</title> </head> <body> <!-- 用v-text解決閃爍問題 --> <div id="app"> <h1 v-text="foo"></h1> <h1 v-text="foo"></h1> <h1 v-text="foo"></h1> <h1 v-text="foo"></h1> <h1 v-text="foo"></h1> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> // 得到 Vue 實例 const app = new Vue({ el: ‘#app‘, data: { foo : ‘hello‘ } }) </script> </body> </html>v-text 示例
v-cloak
- 如果想用{{ }}進行數據顯示,又不想有閃爍問題,則使用v-cloak來處理
■ 先在在樣式表添加一個特殊樣式[v-cloak] { display: none }
■ 然後在被vue管理的模板入口節點上作用v-cloak指令。
- 原理:加上這個display:none的屬性後,默認一開始被vue管理的模板時隱藏的,當vue解析處理完DOM模板後,會自動把這個樣式去除,然後顯示出來
Demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue-指令 v-cloak</title> </head> <body> <!-- 如果你還是想要使用{{ }}進行數據顯示的話,可以使用v-cloak解決閃縮問題 --> <!-- 用v-cloak解決閃爍問題 --> <!-- 原理:默認給div內容是display: none的樣式, 但是當vue加載完成後,會自動將v-cloak去除。 --> <style type="text/css"> [v-cloak] { display: none; } </style> <div id="app" v-cloak> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> // 得到 Vue 實例 const app = new Vue({ el: ‘#app‘, data: { foo : ‘hello‘ } }) </script> </body> </html>v-cloak 示例
v-html
把要顯示的字符串當做 html 代碼來進行渲染。
Demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue-指令 v-text</title> </head> <body> <div id="app" v-cloak> <!-- 普通的文本綁定渲染:結果會當做字符串直接渲染 --> <div>{{ htmlStr }}</div> <!-- 使用v-html指令的文本渲染,會將這段文本當做HTML代碼進行渲染 --> <div v-html="htmlStr"></div> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> // 得到 Vue 實例 const app = new Vue({ el: ‘#app‘, data: { htmlStr : ‘<div>我是一段HTML文本</div>‘ } }) </script> </body> </html>v-html 示例
運行效果:
註意:v-html 的文本渲染會對裏面的腳本進行過濾,遇到腳本會忽略過去,不執行。
- Vue在這裏做了安全處理,如果發現有script標簽,則不渲染
- 原因:防止XSS攻擊。
XSS攻擊:XSS攻擊就是利用往網頁註入js腳本,讀取cookie,發送到黑客服務器中或者直接在你訪問的這個網站,當你結算賬單的時候,跳轉到釣魚網站
v-show
根據表達式之真假值,切換元素的 display css 屬性。
作用:條件控制元素的顯示或隱藏
- 無論真假,都會渲染在DOM結構中
■ 條件為真,則讓display顯示
■ 條件為假,則讓display不顯示
建議:如果需要頻繁的顯示或隱藏切換,則使用v-show
v-if 和 v-show的區別:
v-if:
- 真正的條件渲染,不滿足渲染條件都不會渲染在DOM結構中
- 條件為真,則渲染這個DOM
- 條件為假,則移除或不渲染這個DOM
- 建議:如果只是一次顯示和隱藏的控制,則建議使用v-if
v-pre
跳過這個元素和它的子元素的編譯過程。可以用來顯示原始 Mustache 標簽。跳過大量沒有指令的節點會加快編譯。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue-指令 v-pre</title> </head> <body> <!-- v-pre --> <div id="app" v-cloak> <!-- Vue 不處理帶有 v-pre 指令的DOM元素 例如:一個網頁的一篇文章,文章內容就不需要被Vue管理渲染。 所以我們就可以在文章內容節點上加v-pre來忽略這個DOM處理 用以提高性能 --> <!-- 正常的塊內容, vue 都會對其編譯解析 --> <h1>{{ foo }}</h1> <!-- v-pre 內為原生的 html 編譯 --> <div v-pre> <h1>{{ foo }}</h1> </div> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> // 得到 Vue 實例 const app = new Vue({ el: ‘#app‘, data: { foo : ‘hello‘ } }); </script> </body> </html>v-pre 示例
使用效果:
v-once
只渲染元素和組件一次。隨後的重新渲染,元素/組件及其所有的子節點將被視為靜態內容並跳過。這可以用於優化更新性能。
Demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue-指令 v-pre</title> </head> <body> <div id="app"> <!-- v-once內的DOM元素只渲染一次,後面就算數據更新了 v-once內的DOM元素都不會再更新渲染。 --> <div v-once> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> <h1>{{ foo }}</h1> </div> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> // 得到 Vue 實例 const app = new Vue({ el: ‘#app‘, data: { foo : ‘hello‘ } }) </script> </body> </html>v-once 示例
運行效果:
自定義指令
除了核心功能默認內置的指令 (v-model 和 v-show),Vue 也允許註冊自定義指令。註意,在 Vue2.0 中,代碼復用和抽象的主要形式是組件。然而,有的情況下,你仍然需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令。
註冊綁定方式:
- 關於指令的名字
■ 名字中不要加v-前綴(只有使用的時候才加)
■ 如果有多個單詞,則建議使用駝峰命名法
■ 在使用的時候,首先加v-前綴,然後對於駝峰命名法的指令要轉換為小寫,用-拼接起來。
全局註冊
■ Vue.directive(‘指令名稱’, { 配置參數 } );
■ 如果是全局指令,則一定要在實例化Vue之前註冊
■ 全局註冊在所有組件(實例)中都可以使用
■ 建議:如果需要在任何組件中可能使用的指令把其註冊成全局指令
全局註冊Demo:
// 註冊一個全局自定義指令 `v-focus` Vue.directive(‘focus‘, { // 當被綁定的元素插入到 DOM 中時…… inserted: function (el) { // 聚焦元素 el.focus() } })
局部註冊
■ 通過組件中的選項directives來註冊(組件內容在下一章節將介紹)
■ 指令的名字作為directives對象的成員
■ 局部自定義指令只能在這個組件(實例)中使用
■ 建議:如果只是在某個組件中使用(其他組件不可能用到),這個時候註冊為組件局部指令
directives: { focus: { // 指令的定義 inserted: function (el) { el.focus() } } }
自定義指令的使用:
像系統指令一樣的使用方式操作即可使用。
<input v-focus>
指令的生命鉤子函數:
- bind
■ 只調用一次,指令第一次綁定到元素時調用。在這裏可以進行一次性的初始化設置。而且在這個階段拿不到父元素。
- inserted
■ 被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。
■ 如果你需要操作作用指令的父元素,則最起碼寫到這個 inserted 中
- update
■ 指令的綁定的值發生更新的時候才會觸發調用,獲取的是更新的之前的指令所在的 DOM 內容
- componentUpdated
■ 指令的綁定的值發生更新的時候才會觸發調用,獲取的是更新之後的最新 DOM 內容
- unbind
■ 只調用一次,指令與元素解綁時調用。
// bind 和 inserted 的相同之處是一上來都執行一次,以後再也不會執行
// 異同之處在於,bind 拿不到父元素,inserted 可以拿到父元素
鉤子函數參數
el
:指令所綁定的元素,可以用來直接操作 DOM 。binding
:一個對象,包含以下屬性:name
:指令名,不包括v-
前綴。value
:指令的綁定值,例如:v-my-directive="1 + 1"
中,綁定值為2
。oldValue
:指令綁定的前一個值,僅在update
和componentUpdated
鉤子中可用。無論值是否改變都可用。expression
:字符串形式的指令表達式。例如v-my-directive="1 + 1"
中,表達式為"1 + 1"
。arg
:傳給指令的參數,可選。例如v-my-directive:foo
中,參數為"foo"
。modifiers
:一個包含修飾符的對象。例如:v-my-directive.foo.bar
中,修飾符對象為{ foo: true, bar: true }
。
vnode
:Vue 編譯生成的虛擬節點。具體可以參考 VNode API 解更多詳情。oldVnode
:上一個虛擬節點,僅在update
和componentUpdated
鉤子中可用。
註意:除了 el
之外,其它參數都應該是只讀的,切勿進行修改。如果需要在鉤子之間共享數據,建議通過元素的 dataset
來進行。
基本操作:
<script type="text/javascript"> Vue.directive(‘focus‘, { // 只調用一次,指令第一次綁定到元素時調用。在這裏可以進行一次性的初始化設置。 bind (el) { console.log(‘bind 第一次綁定元素‘) }, // 只調用一次,被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。 // 如果需要對父節點進行操作,則代碼寫在此處 inserted (el) { console.log(‘inserted‘, el.parentNode) }, // update 拿到的是數據改變視圖之前的視圖內容,可以通過比較更新前後的值來忽略不必要的模板更新。 update () { console.log(‘update‘) }, // componentUpdated 拿到的是數據改變視圖之後的視圖內容 componentUpdated () { console.log(‘componentUpdated‘) }, // 只調用一次,指令與元素解綁時調用。 unbind () { console.log(‘unbind‘) } }) </script>指令的生命鉤子Demo
函數簡寫:
在很多時候,你可能想在 bind 和 update 時觸發相同行為,而不關心其它的鉤子。
比如這樣寫:
- 模擬v-show
<script type="text/javascript"> // 很多時候,我們都會在 bind 和 update 中執行相同的代碼 // 所以我們可以使用簡寫方式,直接給一個函數,該函數會作為 bind 和 update 的時候執行的函數 Vue.directive(‘my-show‘, function (el, binding) { if (binding.value) { el.style.display = ‘block‘ } else { el.style.display = ‘none‘ } }) </script>
- 模擬v-bind
<script type="text/javascript"> Vue.directive(‘my-bind‘, function (el, binding) { el.setAttribute(binding.arg, binding.value); }) </script>
vue學習之路 - 4.基本操作(下)