1. 程式人生 > >vue學習之路 - 4.基本操作(下)

vue學習之路 - 4.基本操作(下)

align 過去 開始 就會 binding 效果 不可 exp 功能

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:指令綁定的前一個值,僅在 updatecomponentUpdated 鉤子中可用。無論值是否改變都可用。
    • 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:上一個虛擬節點,僅在 updatecomponentUpdated 鉤子中可用。

  註意:除了 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.基本操作(下)