Vue 系列一 之 Vue 基礎

Create by jsliang on 2018-11-8 13:34:30
Recently revised in 2019-1-12 19:23:17javascript

Hello 小夥伴們,若是以爲本文還不錯,記得給個 star , 大家的 star 是我學習的動力!GitHub 地址css


【2019-08-16】Hello 小夥伴們,因爲 jsliang 對文檔庫進行了重構,這篇文章的一些連接可能失效,而 jsliang 沒有精力維護掘金這邊的舊文章,對此深感抱歉。請須要獲取最新文章的小夥伴,點擊上面的 GitHub 地址,去文檔庫查看調整後的文章。html


推薦經過 目錄 以及使用 返回目錄 按鈕,得到更好的閱讀體驗。前端

一 目錄

不折騰的前端,和鹹魚有什麼區別~vue

目錄
一 目錄
二 正文
2.1 初識 Vue
2.2 掛載數據 - data
2.3 進一步優化 el
2.4 插值表達式 - {{ }}
2.5 指令 - v-*
2.6 事件 - methods
2.7 模板 - template
  2.7.1 初識組件
  2.7.2 父子組件通信
  2.7.3 共用組件
2.8 過濾器 - filter
  2.8.1 局部過濾
  2.8.2 全局過濾
2.9 監聽數據
  2.9.1 偵聽屬性 - watch
  2.9.2 計算屬性 - computed
  2.9.3 watch、computed 與 methods 對比
2.10 傳遞 DOM - slot
  2.10.1 slot 單個傳遞
  2.10.2 具名 slot
2.11 Vue 組件生命週期
  2.11.1 beforeCreate & created
  2.11.2 beforeMount & mounted
  2.11.3 beforeUpdate & updated
  2.11.4 beforeDestory & destory
  2.11.5 activated & deactivated
2.12 獲取 DOM 元素
  2.12.1 單個 DOM 元素獲取
  2.12.2 組件 DOM 元素獲取
  2.12.3 Vue.nextTick()
三 實戰
四 總結

二 正文

返回目錄java

飲水思源:Vue 官方文檔ios

Vue (讀音 /vjuː/,相似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不一樣的是,Vue 被設計爲能夠自底向上逐層應用。Vue 的核心庫只關注視圖層,不只易於上手,還便於與第三方庫或既有項目整合。另外一方面,當與現代化的工具鏈以及各類支持類庫結合使用時,Vue 也徹底可以爲複雜的單頁應用提供驅動。git

學習版本:v2.5.21
編寫時間:2019-1-10github

如版本更迭太大或者時間小夥伴們看到這篇文章過久沒更新,小夥伴們請查看 Vue 官方文檔學習最新的 Vue。ajax

2.1 初識 Vue

返回目錄

那麼,Vue 是怎麼折騰的呢?

話很少說,咱們直接來看代碼實現:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: '#app',
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <div>
          <p>Hello World</p>
        </div>
      `
    })

  </script>
</body>

</html>
複製代碼

如今,咱們解析下代碼運行:

  1. 首先,建立一個空白的 html 模板文件,經過 CDN 引用 Vue:

Vue 通常分兩個版本:
開發版本:開發中有友好的錯誤提示。
生產版本:上線部署使用的版本,代碼包比較小

index.html 代碼片斷

<!-- 1. 引用 Vue -->
<!-- Vue CDN - 提供 Vue 服務 -->
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
複製代碼
  1. 而後,咱們編寫一個掛載點,即咱們的 Vue,最終會在哪一個 DOM 裏面進行操做:
<!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
<!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
<div id="app"></div>
複製代碼
  1. 最後,咱們經過 New 一個 Vue 實例對象,對咱們 id 爲 app 的 DOM 節點進行操做:
new Vue({
  // 3. el - 掛載目標,即渲染在哪一個掛載點
  el: document.getElementById('app'),
  // 4. template - 模板,即渲染到掛載點的內容。
  // 最外層必須有一層包裹,例如 <div>
  template: `
    <div>
      <p>Hello World</p>
    </div>
  `
})
複製代碼

這樣,咱們最終就顯示了 Vue 的簡單引用,是否是以爲很是簡單:

2.2 掛載數據 - data

返回目錄

若是 Vue 僅僅是隻有 template 這個模板裝載,那麼它跟 jQuery 就顯得沒多大差異了,下面咱們使用下 Vue 的 data 進行數據渲染:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: '#app',
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <div>
          <p>{{ text }}</p>
        </div>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
          text: 'Hello World!'
        }
      }
    })

  </script>
</body>

</html>
複製代碼

在這裏,咱們能夠看到,咱們在 template 中加了一個 <p> 標籤,經過 {{ text }} 形式,引入了一個叫 textdata 數據:

<p>{{ text }}</p>
複製代碼

接着咱們在 <scirpt> 中定義了 text 的內容,從而實現數據渲染:

data() {
  return {
    // template 中要使用的數據
    text: 'Hello World!'
  }
}
複製代碼

這樣,咱們就知道了,咱們不只能夠經過模板 template 來渲染 <div> 標籤,咱們也能夠將 js 中定義的數據或者變量,經過操做 data 從而改變 html 裏面的內容。

2.3 進一步優化 el

返回目錄

2.1 章節 及 2.2 章節中,咱們使用 el 的方式是:

el: '#app',
複製代碼

el 掛載形式,在 Vue 內部運行機制中,它會根據你傳入的值,進行查找:

  • 若是傳入的是 #app,那它就判斷查找 idapp 的節點;
  • 若是傳入的是 .app,那它就查找 classapp 的節點;
  • 若是傳入的是節點名 div,那它就查找節點名……

你們應該清楚,這樣判斷查找是須要時間的,多執行一個判斷都是罪惡。

因此咱們能夠:

el: document.getElementById('app'),
複製代碼

這般操做,使得 Vue 直接將掛載點掛載到 id 上去,從而得到更好的加載速度。這算是對 el 的一個小優化。

2.4 插值表達式 - {{ }}

返回目錄

若是小夥伴有點印象,應該還記得,咱們在章節 2.2 中經過 {{}} 這個插值表達式的使用,在 data 中對其裏面的數據進行操做。

下面,咱們進一步講解這個插值表達式 {{}} 還能夠進行哪一種騷操做:

  • 對象:{{ {name: 'jack'} }}
  • 字符串 {{ 'Hello World!' }}
  • 布爾值: {{ isTrue == -1 }}
  • 三元表達式: {{ isTrue ? '正確' : '錯誤' }}

光字面理解是不夠的,咱們經過代碼進行操做演示:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <div>
          <p>{{ text }}</p>
          <p>{{ {name: 'jack'} }}</p>
          <p>{{ 'Hello World!' }}</p>
          <p>{{ isTrue == -1 }}</p>
          <p>{{ isTrue ? '真' : '假' }}</p>
        </div>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
          text: 'Hello World!',
          isTrue: true
        }
      }
    })

  </script>
</body>

</html>
複製代碼

它在瀏覽器的展現爲:

關鍵代碼講解:

<div>
  <!-- 賦值 text 到 <p> 標籤中 -->
  <p>{{ text }}</p>
  
  <!-- 賦值對象到標籤中 -->
  <p>{{ {name: 'jack'} }}</p>
  
  <!-- 直接賦值字符串到標籤中 -->
  <p>{{ 'Hello World!' }}</p>

  <!-- 
    直接進行布爾判斷,isTrue 在 data 中設置爲 true,
    而 -1 轉爲 布爾值 是 false,因此二者不相等
    輸出值爲 false 
  -->
  <p>{{ isTrue == -1 }}</p>

  <!-- 運行三元表達式,isTrue 爲 true,輸出 真 -->
  <p>{{ isTrue ? '真' : '假' }}</p>
</div>
複製代碼

經過三元表達式的運用,咱們能夠作到一些判斷:數組最後一個元素、是否動態顯示隱藏等。

2.5 指令 - v-*

返回目錄

在 Vue 中,若是單單使用 {{}} 這種插值表達式,是知足不了咱們對數據的操做慾望的。因此,Vue 以 v-ifv-bind 等形式,提供了一些對於頁面 + 數據的更爲方便的操做:指令

  • v-text
  • v-html
  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-bind
  • v-on
  • v-model
  • v-for

這裏採用一個頁面展現全部指令,若是小夥伴想逐個詳細瞭解指令,推薦去官網查看學習:Vue 指令

那麼,上面的指令都是怎麼使用的呢?這裏經過一個 index.html 及一張圖向你們演示其基本用法:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

  <style>
    /* 顏色樣式:紅、綠、藍 */
    .color-red {
      color: red;
    }

    .color-blue {
      color: blue;
    }

    .color-green {
      color: green;
    }
  </style>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <div>

          <p>v-text 演示</p>
          <p v-text='vTextOrHtml'></p>

          <br/>

          <p>v-html 演示</p>
          <p v-html='vTextOrHtml'></p>

          <br/>

          <p>v-if -> v-else-if -> v-else 演示</p>
          <p v-if='vIf == 1'>Hello v-If</p>
          <p v-else-if='vIf == 2'>Hello v-else-if</p>
          <p v-else>Hello v-else</p>

          <br/>

          <p>v-show 演示</p>
          <p v-show='isTrue'></p>

          <br/>

          <p>v-bind:××× -> :××× 演示</p>
          <input v-bind:value="vBind" v-bind:class="colorRed" type="text"/>
          <input v-bind:other1="other1" :other2="other2" :other3=" 'other3' " value="Hello :屬性值" type="text"/><br/>

          <br/>

          <p>v-on:click -> @click 演示</p>
          <button v-on:click=" vBind= 'Hello v-on:click' ">v-on:click - 點擊直接改變 vBind 的值</button><br>
          <button @click="changevBindValue">v-on:click - 點擊經過事件改變 vBind 的值</button><br>

          <br/>

          <p>v-model 演示</p>
          <input v-model="vModel" type="text" />
          <p>{{ vModel }}</p>

          <br/>

          <p>v-for 演示</p>
          <ul v-for="(item, index) in vFor" :class="item.classStyle">
            <li>{{index+1}}. {{item.name}} - {{item.age}}</li>
          </ul>

        </div>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據

          // v-text 及 v-html 使用數據
          vTextOrHtml: '<span style="color: red">我是紅的</p>',
          
          // v-if 使用數據
          vIf: 2,
          
          // v-show 使用數據
          isTrue: false,
          
          // v-bind 使用數據
          vBind: "Hello v-bind",
          
          // v-bind 經過動態綁定 class 修改樣式
          colorRed: 'color-red',
          
          // v-bind 的 :屬性 的使用形式
          other1: 'other1',
          
          // 同上
          other2: 'other2',
          
          // v-model 使用數據
          vModel: 'Hello v-model',
          
          // v-for 使用數據
          vFor: [{
              name: '張三', // 姓名
              age: 22, // 年齡
              classStyle: "color-red" // 樣式
            },
            {
              name: '李四',
              age: 23,
              classStyle: "color-blue"
            },
            {
              name: '王五',
              age: 24,
              classStyle: "color-green"
            }
          ]
          
        }
      }
    })

  </script>
</body>

</html>
複製代碼

咱們看下頁面:

在這裏,咱們對代碼進行下講解:

<div>
  <!-- 
    1. v-html
    這裏直接將 vTextOrHtml 中的文本
    當成 string 渲染到頁面中去
   -->
  <p v-text='vTextOrHtml'></p>

  <br/>

  <!-- 
    2. v-html
    這裏在渲染 vTextOrHtml 的過程當中,
    若是遇到標籤,則對標籤頁進行渲染 
   -->
  <p v-html='vTextOrHtml'></p>

  <br/>

  <!-- 
    3. v-if/v-else-if/v-if
    判斷 data 中 vIf 的值是多少,
    這裏有三種狀況:v-if、v-else-if、v-else。
    若是項目中有更多狀況,則再添加 v-else-if 便可
  -->
  <p v-if='vIf == 1'>Hello v-If</p>
  <p v-else-if='vIf == 2'>Hello v-else-if</p>
  <p v-else>Hello v-else</p>

  <br/>

  <!-- 
    4. v-show
    判斷 isTrue 是真仍是假,
    它不一樣於 v-if 的方面是:
    v-if 若是是假,則在 Element 中沒有渲染
    v-show 若是是假,則該標籤爲 display: none
  -->
  <p v-show='isTrue'></p>

  <br/>

  <!-- 
    5. v-bind
    v-bind 有兩種格式:
    1. v-bind:value - 全寫
    2. :value - 簡寫
    咱們還能夠經過 v-bind:class 來動態賦值
    v-bind:other1="other1" 在頁面中顯示就是:
    <input other1="other1" />>
   -->
  <input v-bind:value="vBind" v-bind:class="colorRed" type="text"/>
  <input v-bind:other1="other1" :other2="other2" :other3=" 'other3' " value="Hello :屬性值" type="text"/><br/>

  <br/>

  <!-- 
    6. v-on
    v-on:click 有兩種格式:
    1. v-on:click - 全寫
    2. @click - 簡寫
    v-on:click 除了能夠直接在裏面寫表達式,還能夠填寫方法
   -->
  <button v-on:click=" vBind= 'Hello v-on:click' ">v-on:click - 點擊直接改變 vBind 的值</button><br>
  <button @click="changevBindValue">v-on:click - 點擊經過事件改變 vBind 的值</button><br>

  <br/>

  <!-- 
    7. v-model
    v-model 是雙向數據綁定,
    在這裏,上面 input 的修改
    會影響到下面 p 顯示的內容
   -->
  <input v-model="vModel" type="text" />
  <p>{{ vModel }}</p>

  <br/>

  <!-- 
    8. v-for
    v-for 循環體遍歷輸出
   -->
  <ul v-for="(item, index) in vFor" :class="item.classStyle">
    <li>{{index+1}}. {{item.name}} - {{item.age}}</li>
  </ul>
</div>
複製代碼

v-bind 和 v-model 的區別:

  • v-bind:將 Vue 中的數據同步到頁面,即該值大部分用於前端向瀏覽器傳固定數據。v-bind 能夠給任何屬性賦值,是從 Vue 到頁面的單向數據流,即 Vue -> html。
  • v-model:雙向數據綁定,前端向瀏覽器傳數據,用戶操做瀏覽器的更改前端能夠察覺到。v-model 只能給具備 value 屬性的元素進行雙向數據綁定(必須使用的是有 value 屬性的元素),即 Vue -> html -> Vue

關於 Vue 的指令,這裏咱先對它進行了個全面的簡單瞭解,知道它是如何使用的。
想詳細學習的小夥伴,記得前往官方文檔:Vue 文檔

2.6 事件 - methods

返回目錄

在上一章 2.5 中,咱們經過在 button 中使用 v-on:click 時,給它綁定了事件方法。

可是,在 2.5 中,咱們大致講述了事件方法的使用,可是咱們只是只知其一;不知其二。

在這裏,咱們抽取出來作下講解:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <button @click="addStyle">添加行內樣式</button>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        addStyle(e) {
          e.toElement.style.background = "red"
        }
      }
    })

  </script>
</body>

</html>
複製代碼

此時頁面的點擊效果以下所示:

此刻咱們分析下頁面:

  1. 首先,在上面的 <button> 中,咱們經過 @click 綁定了事件 addStyle
<button @click="addStyle">添加行內樣式</button>
複製代碼
  1. 接着,方法的編寫,須要寫到與 data 同級的 methods 中:
methods: { // 方法
  addStyle: function(e) {
    e.toElement.style.background = "red"
  }
}
複製代碼
  1. 而後,咱們經過傳遞參數 e,能夠獲取到點擊的時候的元素,經過查找,咱們發現它的樣式所在的目錄結構以下:
- button
  - toElement
    - style
      - background
複製代碼
  1. 最後,咱們在用戶點擊按鈕的時候,直接修改了它的背景。

2.7 組件 - components

返回目錄

敲黑板!敲黑板!敲黑板!

組件是 Vue 學習的重點,組件化的 SPA 或者 SSR 頁面的製做,使得咱們開發起來更加隨心應手。

2.7.1 初始組件

返回目錄

在上面的章節中,咱們一直使用 template: `` 的形式,編寫 html 標籤。可是,隨着項目的不斷擴大,若是所有代碼都寫在一個 template 中,那麼咱們修改起來就複雜了。因此,咱們應該想辦法對它進行劃分,例如將一個頁面劃分爲 headercontentfooter 三部分。這樣,咱們須要修改 nav 的時候,只須要在 header 中修改就能夠了。

頁面結構

- app
 - header
 - content
 - footer
複製代碼

這樣的思想,在 Vue 中體現爲組件(組合起來的部件)。那麼,在 Vue 中,須要如何作,才能比較好的作到組件的劃分呢?

首先,咱們捋捋邏輯:

在前面的章節中,在 Vue 的定義上,咱們將首個 template 掛載到了 id 爲 app 的節點上。而後將 template 劃分爲三個塊:headercontentfooter

在這裏,咱們將 #apptemplate 叫作父組件,header 等叫子組件,就比如父親下面有三個兒子同樣。

而後,咱們嘗試從 new Vue 中抽離單個組件出來:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 聲明入口組件
    var App = {
      template: `<h1>我是入口組件</h1>`
    }

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: '<app/>',
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象
        app: App
      }
    })

  </script>
</body>

</html>
複製代碼

這時候頁面以下所示:

接着,咱們分析下進行的三部曲:

  1. component 中定義並抽離 App
  2. new Vue 外定義 App
  3. template 中使用 App

這樣,咱們就作到了單個組件的抽離,及 new VueApp 的父組件,Appnew Vue 的子組件。

最後,既然上面作到了單個組件的抽離,如今咱們實現多個組件的抽離:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vue學習</title>
</head>

<body>
  <div id="app"></div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    // 聲明頭部組件
    var MyHeader = {
      template: `<div>我是頭部</div>`
    };
    
    // 聲明內容組件
    var MyContent = {
      template: `<div>我是軀體</div>`
    };

    // 聲明底部組件
    var myFooter = {
      template: `<div>我是底部</div>`
    }

    new Vue({
      el: document.getElementById('app'),
      components: { // 聲明要用的組件們
        // key 是組件名,value 是組件對象
        'my-header': MyHeader,
        'my-content': MyContent,
        'my-footer': myFooter
      },
      template: `
        <div>
          <my-header/>
          <my-content/>
          <my-footer/>
        </div>
      `
    })
  </script>
</body>

</html>
複製代碼

這樣,咱們就作到了組件的抽離。

注意:template 有且只有一個根節點,若是沒有根節點,Vue 會給你報錯。

template: `
    <my-header/>
    <my-content/>
    <my-footer/>
  `
複製代碼

上面那種寫法是錯誤的,謹記。

作到這裏,咱們又能夠愉快玩耍了,並且 myHeadermyContentmyFooter 中是能夠跟 new Vue 同樣寫 datamethods 的哦~

例如:

var MyHeader = {
  data() {
    return {
      // ... 定義數據
    }
  },
  template: `<h1>我是頭部</h1>`,
  methods: {
    // 定義方法
  }
};
複製代碼

2.7.2 父子組件通信

返回目錄

既然前面章節已經劃分了父子組件,那麼在這裏,咱們講件更有趣的事:父子組件通信。

在組件間,咱們 new Vue 至關於父親(父組件),他有本身的 data。而後,子組件也會有本身的 data

  • 假如某天,父親找到本身的兒子,想告訴他:「其實你不是我親生的,你的姓名是***」

那麼,在 Vue 中,咱們要怎麼作,才能讓它的兒子(子組件),知道它的姓到底是什麼呢?咱們來看代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 子組件
    var Son = {
      template: `
        <div>個人名字:{{name}}</div>
      `,
      props: ['name']
    }

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <son :name="name"></son>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
          name: '皮皮蝦'
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象
        son: Son
      }
    })

  </script>
</body>

</html>
複製代碼

編寫完代碼後,咱們能夠在瀏覽器看到,瀏覽器顯示出了:個人名字:皮皮蝦,這幾個大字。

哦了,原來父親的兒子姓 。同時,咱們也就知道了,在父組件中的數據,經過 v-bind:*** 的形式,將父組件中的 data,發送給子組件。而子組件呢,經過 props 的定義,獲取到了父親的數據。

這樣咱們就作到了父組件傳遞數據給子組件。

2.7.3 共用組件

返回目錄

在上面中,咱們提到:

- App
 - my-header
 - my-content
 - my-footer
複製代碼

App 這個組件上,咱們掛載了三個子組件:myHeadermyContentmyFooter

  • 可是,若是某天,出現了一個女孩(共有組件),這個女孩的名字叫:beautifulGirl。而後不只三個兒子(子組件)想追求她,就連父親(父組件)也想追求她(夠瘋狂)。

那麼,在 Vue 中,是經過什麼方式,使父親和兒子都有機會接觸到這個女孩呢?(父子組件如何可以均可以使用共用組件)

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 聲明頭部組件
    var MyHeader = {
      template: `
        <div>我是頭部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };
    
    // 聲明內容組件
    var MyContent = {
      template: `
        <div>我是內容區,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };

    // 聲明底部組件
    var myFooter = {
      template: `
        <div>我是底部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    }

    // 聲明共用組件
    Vue.component('beautiful-girl', {
      template: `<span>—— 美麗女孩 ——</span>`
    })

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <div>
          <my-header/>
          <my-content/>
          <my-footer/>
        </div>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象
        'my-header': MyHeader,
        'my-content': MyContent,
        'my-footer': myFooter,
      }
    })

  </script>
</body>

</html>
複製代碼

在這裏,咱們經過 Vue.component('組件名',{ }) 的形式,註冊了個全局組件 beautiful-girl,這樣,父子組件均可以直接調用該組件,從而在瀏覽器顯示爲:

如今,父親和兒子均可以和漂亮女孩溝通了。到底是父親給他們的兒子找了個後媽,仍是他們兒子找到本身所愛呢?敬請期待……

2.8 過濾器 - filter

返回目錄

在工做中,咱們常常須要對一些後端傳回來的數據進行過濾。例如:我司 Java 小哥傳回來的金錢,就是分進制的,即:1元 = 100分。因此傳回個 2000,實際上是 20 元。那麼,在 Vue 中,咱們該如何對數據進行過濾呢?

2.8.1 局部過濾

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 聲明頭部組件
    var MyHeader = {
      template: `
        <div>我是頭部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };
    
    // 聲明內容組件
    var MyContent = {
      template: `
        <div>我是內容區,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };

    // 聲明底部組件
    var myFooter = {
      template: `
        <div>我是底部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    }

    // 聲明共用組件
    Vue.component('beautiful-girl', {
      template: `<span>—— 美麗女孩 ——</span>`
    })

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <p>我是錢多多,我有 {{money}} 多一點: ¥{{money | addDot}},跟我混有出息~</p>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
          money: 1000000
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象

      },
      // 8. filters - 組件內的過濾器
      filters: {
        addDot(money) {
          return (money / 1000000 + ".000000");
        }
      }
    })

  </script>
</body>

</html>
複製代碼

在上面,咱們經過 filters 中的 addDot 方法,對數據進行了過濾,將 money 的數據,從 10000000 變成了 1.000000

2.8.2 全局過濾

返回目錄

而後,在嘗試了局部 filters 的好處以後,咱們還能夠試試它的全局過濾器寫法:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 全局過濾器
    Vue.filter('addDot', function(money) {
      return (money / 1000000 + ".000000");
    })
    
    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <p>我是錢多多,我有 {{money}} 多一點: ¥{{money | addDot}},跟我混有出息~</p>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
          money: 1000000
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象

      },
      // 8. filters - 組件內的過濾器
      filters: {
        
      }
    })

  </script>
</body>

</html>
複製代碼

最後在頁面中顯示爲:

2.9 監聽數據

返回目錄

Vue 中,咱們經過 v-model 作了雙向數據綁定,即在頁面的 <input> 中輸入的值,在咱們的 Vue 中能夠得到數據;在 Vue 中定義的數據,也會即時渲染到頁面中。

可是,在代碼中,咱們怎樣才能獲取到它即時輸入的數據呢?

2.9.1 偵聽屬性 - watch

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <div>
          <input type="text" v-model="money" />
          <span>{{money}}</span>
        </div>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據
          money: ''
        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象

      },
      // 8. filters - 組件內的過濾器
      filters: {
        
      },
      // 9. watch - 偵聽屬性
      watch: {
        // key: data 屬性的屬性名
        money(newVal, oldVal) {
          console.log(newVal, oldVal);
        }
      }
    })

  </script>
</body>

</html>
複製代碼

這樣,當咱們輸入 11 個 1 的過程當中,瀏覽器的 Console 對應輸出爲:

2.9.2 計算屬性 - computed

返回目錄

在上面,咱們講了經過 watch 來監聽 datanumberstring 等字段的改變。可是,在 Vue 中,爲了方便咱們的監聽操做,Vue 還定義了個方法:computed,咱們能夠經過 computed,監控咱們在 data 中定義的所有數據。

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vue學習</title>
</head>

<body>
  <div id="app"></div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>

    new Vue({
      el: document.getElementById('app'),
      template: `
        <div>
          <input type="text" v-model="number1" />
          +
          <input type="text" v-model="number2" />
          *
          <input type="text" v-model="number3" />
          =
          {{result}}
        </div>
      `,
      data: {
        number1: 0,
        number2: 0,
        number3: 0,
        result: '',
      },
      computed: {
        // 若是原值不變,緩存不調函數的優化機制
        result: function() {
          // 監視對象,寫在了函數內部,
          // 凡是函數內部有 this. 相關屬性,改變都會觸發當前函數
          let addSum = parseInt(this.number1) + parseInt(this.number2);
          let allSum = addSum * this.number3;
          return allSum;
        }
      }
    })

  </script>
</body>

</html>
複製代碼

其結果以下面 GIF 圖所示:

2.9.3 watch、computed 與 methods 對比

返回目錄

在上面,咱們涉及了兩個知識點:watchcomputed

那麼,又到 「玄學」 的時刻了,都是跟監聽數據打交道,咱們平時使用 Vue 的時候,何時使用 watch,何時使用 computed?而後,若是咱們在加上 methods,那麼何時咱們又用 methods 呢?

首先,咱們對比下 computedmethods

  • computed 是根據 data 中的數據變化,而進行的操做。即 this.任意數據 改變了,那麼,computed 就會進行改變;而若是 this.任務數據 不變,那麼 computed 就會執行它的緩存策略,不會更新
  • methods 通常是根據點擊之類的事件來觸發的,例如用戶經過 @click="方法" 來進行數據的改變。

而後,咱們對比下 computedwatch

若是上面章節的 computed 方法換成 watch

index.html 代碼片斷

// 9. watch - 偵聽屬性
watch: {
  // key: data 屬性的屬性名
  result(newVal, oldVal) {
    console.log(newVal, oldVal);
    this.result = this.number1 + this.number2 * this.number3;
  }
},
複製代碼

你會發現,result 數據不變化了,由於這是 computed 才特有的玩意,若是你須要將上面章節的 computed 方法換成 watch,那麼你須要:

index.html 代碼片斷

// 9. watch - 偵聽屬性
watch: {
  // key: data 屬性的屬性名
  number1(val) {
    this.result = parseInt(this.number1) + parseInt(this.number2) * parseInt(this.number3);
  },
  number2(val) {
    this.result = parseInt(this.number1) + parseInt(this.number2) * parseInt(this.number3);
  },
  number3(val) {
    this.result = parseInt(this.number1) + parseInt(this.number2) * parseInt(this.number3);
  }
},
複製代碼

如此,小夥伴應該瞭解到,watch 若是須要完成 computed 的功能,那麼,它須要監聽每個須要改變的屬性。

最後,在這裏,咱們大體描述下 watchcomputed 的區分:

  • computed 強調計算,例如 c = a + bb 是外界傳來不斷變化的,由於你只要顯示 c,因此使用 computed。而 watch 屬性強調自身值的變化先後的動做,若是須要完成 c = a + b,那麼你須要 watch 數據 ab 的變化,在這二者變化的時候,在方法中執行 c = a + b
  • watch 在處理異步操做或者開銷較大的操做上有優點。
    • 執行異步操做不能串行返回結果,使用 watch
    • 開銷較大的操做,避免堵塞主線程,使用 watch
    • 簡單且串行返回的,使用 computed
  • computed 對綁定的值有依賴,若是每次操做的值不變化,則不進行計算,具備緩存特性。watch 會偵聽先後變化的狀態,不管操做的值是否變化,都會執行定義的函數體,因此會有 data(newVal, oldVal)。

若是小夥伴們較真上了,那麼請查看官方文檔:計算屬性和偵聽器

2.10 傳遞 DOM - slot

返回目錄

在平常工做中,咱們對一些經常使用的功能,例如:側邊欄、頂部導航欄等,會進行經常使用的封裝,等咱們想用的時候,就能夠直接引用。那麼,在 Vue 中,想實現這類功能,咱們還須要瞭解什麼?

2.10.1 slot 單個傳遞

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var myLi = {
      template: `
        <li><slot></slot></li>
      `
    };

    Vue.component('my-li', myLi);

    var App = {
      template: `
        <div>
          <ul>
            <my-li><button>我是第一行 button 按鈕</button></my-li>
            <my-li><h3>我是第二行 h3 標籤</h3></my-li>
            <my-li><a href="javascript:void(0)">我是第三行 a 導航</a></my-li>
            <my-li><span>我是第四行 span 標籤</span></my-li>
          </ul>
        </div>
      `
    };

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <app/>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據

        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象
        app: App
      },
      // 8. filters - 組件內的過濾器
      filters: {
        
      },
      // 9. watch - 偵聽屬性
      watch: {
        // key: data 屬性的屬性名

      },
      // 10. computed - 計算屬性
      computed: {
        // 若是原值不變,computed 會執行緩存,即不調用方法
        
      }
    })

  </script>
</body>

</html>
複製代碼

其結果以下圖所示:

那麼,上面代碼中,咱們幹了什麼?

首先,如上代碼及其結果圖,咱們的 new Vue 中掛載了一個組件 App

new Vue({
  el: document.getElementById('app'),
  components: {
    app: App
  },
  template: `
    <app/>
  `
})
複製代碼

而後,該 App 的目的,是想動態引用一個 li 組件

var App = {
  template: `
    <div>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
    </div>
  `
};
複製代碼

接着,咱們在全局定義 myLi 組件的同時,經過 <slot></slot> 插槽,使它可以動態地加載 dom 節點。

var myLi = {
  template: `
    <li><slot></slot></li>
  `
};

Vue.component('my-li', myLi);
複製代碼

最後,咱們在 App 中,傳遞給它不一樣的 dom 節點,從而動態生成 App

var App = {
  template: `
    <div>
      <ul>
        <my-li><button>我是第一行 button 按鈕</button></my-li>
        <my-li><h3>我是第二行 h3 標籤</h3></my-li>
        <my-li><a href="javascript:void(0)">我是第三行 a 導航</a></my-li>
        <my-li><span>我是第四行 span 標籤</span></my-li>
      </ul>
    </div>
  `
};
複製代碼

這樣,咱們就思路清晰地知道,如何經過 <slot></slot> 來動態地加載 dom 節點,對咱們 Vue 開發又有了更好的幫助。

2.10.2 具名 slot

返回目錄

在上面中,咱們談論到了單個插槽 slot 的用法。可是,若是組件想根據父組件是否傳遞某個變量來存放插槽的數量,要怎麼作呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var mySlot = {
      template: `
        <ul>
          <li>
            <slot></slot>
          </li>
          <li>
            <slot name="one"></slot>
          </li>
          <li>
            <slot name="two"></slot>
          </li>
          <li>
            <slot name="three"></slot>
          </li>
        </ul>
      `
    };

    Vue.component('my-slot', mySlot);

    var App = {
      template: `
        <div>
          <my-slot>
            <p>Helo World!</p>
            <button slot="one">按鈕</button>
            <a href="javascript:void(0)" slot="two">連接</a>
          </my-slot>
        </div>
      `
    };

    new Vue({
      // 3. el - 掛載目標,即渲染在哪一個掛載點
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到掛載點的內容
      // 最外層必須有一層包裹,例如 <div>
      template: `
        <app/>
      `,
      // 5. data - 數據,即在操做中須要用到的數據
      // 能夠理解爲在 jQuery 中 var text = "Hello World!"
      // {{ text }} 爲數據渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的數據

        }
      },
      // 6. methods - 方法,即咱們的頁面事件
      // 能夠理解爲在 jQuery 中定義 Function
      methods: {
        
      },
      // 7. components - 組件名稱
      components: {
        // key 是組件名,value 是組件對象
        app: App
      },
      // 8. filters - 組件內的過濾器
      filters: {
        
      },
      // 9. watch - 偵聽屬性
      watch: {
        // key: data 屬性的屬性名

      },
      // 10. computed - 計算屬性
      computed: {
        // 若是原值不變,computed 會執行緩存,即不調用方法
        
      }
    })

  </script>
</body>

</html>
複製代碼

效果圖以下:

下面咱們分析下,咱們在代碼中作了啥:

首先,咱們經過下面代碼能夠知道,第一個 lislot 是未命名的默認 slot,因此它在頁面中展現爲 p 的數據。

var mySlot = {
  template: `
    <ul>
      <li>
        <slot></slot>
      </li>
    </ul>
  `
};

var App = {
  template: `
    <div>
      <my-slot>
        <p>Helo World!</p>
        <button slot="one">按鈕</button>
        <a href="javascript:void(0)" slot="two">連接</a>
      </my-slot>
    </div>
  `
};
複製代碼

而後,再觀察下 App 中的代碼 <button slot="one">按鈕</button><a href="javascript:void(0)" slot="two">連接</a>,發現它們使用了 slot="***",這說明了它指定了要求組件中 <slot name="***"></slot> 的代碼接收。因此第二行第三行顯示爲按鈕和連接。

最後,因爲最後一個 li<slot name="three"></slot>,這個 name="three"App 組件中沒有用到,因此它表現爲空。

2.11 Vue 組件生命週期

返回目錄

在 Vue 中,何時進行虛擬 dom 渲染成 dom,或者何時銷燬代碼,都是有對應的鉤子的:


  • beforeCreate
  • created

  • beforeMount
  • mounted

  • beforeUpdate
  • updated

  • activated
  • deactivated

  • beforeDestory
  • destory

關於生命週期,Vue 官方文檔是有相關圖示及文檔的:官方文檔 - Vue 生命週期

下面咱們經過代碼演示,講解這 5 組生命週期的用法。

2.11.1 beforeCreate & created

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div>
          我是生命週期組件
        </div>
      `,
      data: function() {
        return {
          text: 'Hello World!'
        }
      },
      beforeCreate: function() {
        // 組件建立以前
        console.log(this.text); // [Console] undefined
      },
      created: function() {
        // 組件建立以後
        console.log(this.text); // [Console] Hello World!
      }

      /*
        * 使用 lifeCycle 組件,就會觸發以上的事件函數(鉤子函數)
        * created 中能夠操做數據,而且能夠實現 Vue -> 頁面 的影響
        * 應用:發起 ajax 請求
      */
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      template: `
        <div>
          <life-cycle></life-cycle>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })
    
  </script>
</body>

</html>
複製代碼

在代碼中能夠看到,咱們在 App 中引用了 lifeCycle 這個組件。

咱們經過鉤子函數 beforeCreate(組件建立以前) 與 created(組件建立以後),結合 console 發現,這兩個鉤子函數對於 data 來講,一個在 data 掛載前(beforeCreate),因此打印出來的是:undefined,而另一個發生在 data 掛載後,因此打印出來的是:Hello World!

2.11.2 beforeMount & mounted

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div>
          我是生命週期組件
        </div>
      `,
      data: function() {
        return {
          text: 'Hello World!'
        }
      },
      beforeMount: function() {
        // Vue 起做用以前
        console.log(document.body.innerHTML);
      },
      mounted: function() {
        // Vue 起做用,裝載數據到 DOM 以後
        console.log(document.body.innerHTML);
      }
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      template: `
        <div>
          <life-cycle></life-cycle>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
複製代碼

那麼,雖然說它們的做用,一個是 Vue 起做用以前,一個是 Vue 起做用,裝載數據到 DOM 以後。

咱們應該怎樣才能觀察到它的做用?

看到上圖的紅框,也許你會恍然大悟:「喔,beforeMount 就是我裝載以前的鉤子函數,而 mounted 是我裝載以後的鉤子函數,它是 Vue 做用之後的 DOM」

2.11.3 beforeUpdate & updated

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div id="update">
          <p>我是生命週期組件</p>
          <p>{{text}}</p>
          <button @click="text = '!dlroW olleH'">點擊改變 text</button>
        </div>
      `,
      data: function() {
        return {
          text: 'Hello World!'
        }
      },
      // 基於數據改變,影響頁面
      beforeUpdate: function() {
        // 改變前
        console.log(document.getElementById('update').innerHTML);
      },
      updated: function() {
        // 改變後
        console.log(document.getElementById('update').innerHTML);
      }

      /*
        * 在平常工做中,咱們能夠在事件先後拿到它的 DOM,從而作一些咱們想要的操做
      */
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      template: `
        <div>
          <life-cycle></life-cycle>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
複製代碼

在解析代碼前,咱們先查看它的輸出:

能夠看出,beforeUpdate 能夠獲取原 DOM,而 updated 能夠獲取新 DOM。

它們在上面代碼中變現爲:獲取 <button> 按鈕觸發的事件先後 DOM 的變化,經過這個變化,咱們能夠在當中作一些操做,從而更好的知足咱們的業務需求。

  • 小結:( beforeMount & mounted ) VS ( beforeUpdate & updated

那麼問題來了,beforeMount 這組和 beforeUpdate 都能監控到 DOM 的變化,它們有什麼區別呢?

答案是,通常咱們若是須要在頁面加載的時候,監控 DOM 的變化,那就使用 beforeMountmounted;可是,若是咱們想監控用戶的操做(點擊事件等),那麼,咱們就須要使用 beforeUpdateupdated,由於它們不像 beforeMountmounted 只會在頁面掛載初期執行一次,它們能夠根據用戶的操做被執行屢次。

2.11.4 beforeDestory & destory

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div id="update">
          <p>我是生命週期組件</p>
        </div>
      `,
      // 對應父組件 v-if == false 的時候,就產生下面鉤子函數,銷燬當前組件
      beforeDestroy: function() { 
        // 銷燬以前
        console.log('實例銷燬以前調用。在這一步,實例仍然徹底可用。');
      },
      destroyed: function() {
        // 銷燬以後
        console.log('Vue 實例銷燬後調用。調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。');
      }
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      data: function() {
        return {
          isExist: true
        }
      },
      template: `
        <div>
          <life-cycle v-if="isExist"></life-cycle>
          <button @click="isExist = !isExist">點擊改變 子組件 狀態</button>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
複製代碼

在這裏,咱們在點擊 <button> 的時候,控制檯顯示爲:

能夠看出,當咱們點擊 <button> 的時候,咱們的 isExist 狀態(第一次時)被改變爲 false,從而觸發了 lifeCycle 的銷燬鉤子函數,在控制檯打印了上面兩行話。

相應的,若是是當 isExist 狀態變爲 true 的時候,會觸發咱們的 beforeCreatecreated 這兩個鉤子函數,有興趣的小夥伴能夠嘗試一下,這裏不作過多演示。

2.11.5 activated & deactivated

返回目錄

通過長期的工做,咱們知道,若是頻繁的操做 DOM,進行影響到鉤子函數 beforeCreatecreatedbeforeDestorydestory 的操做,是對咱們的性能會產生影響的。咱們要如何防止某部分代碼的頻繁操做 DOM,而且監聽到它的操做呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div id="update">
          <p>我是生命週期組件</p>
        </div>
      `,
      activated: function() {
        console.log("組件被激活了");
      },
      deactivated: function() {
        console.log("組件被停用了");
      }
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      data: function() {
        return {
          isExist: true
        }
      },
      template: `
        <div>
          <keep-alive>
            <life-cycle v-if="isExist"></life-cycle>
          </keep-alive>
          <button @click="isExist = !isExist">點擊改變 子組件 狀態</button>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
複製代碼

在代碼中,咱們經過 <keep-alive></keep-alive> 這個 Vue 的內置組件,對咱們子組件進行了包裹。

而後,當咱們進入頁面和點擊按鈕時,作到了 activateddeactivated 這兩個鉤子函數的觸發:

能夠看出,當咱們進來頁面的時候,它就告訴咱們,該組件被激活了。當咱們第一次點擊 <button> 按鈕的時候,isExist 的狀態變成了 false,即該組件被停用了。最後,咱們再次點擊了 <button>,這時候控制檯再次打印 組件被激活了

  • 小結:這時候,但願小夥伴回到生命週期章節的開頭,看官方關於生命週期的解析圖,它將有助於咱們更加理解聲明週期。若是仍是不夠清晰,能夠點擊圖片旁邊的按鈕,進入官方文檔,查看官方關於生命週期的解析。【返回加深學習】

2.12 獲取 DOM 元素

返回目錄

在平常開發中,可能有小夥伴會想到操做 DOM 元素。若是用原生的 document.getElementById 吧,可能太 low 了,因此,有沒有相似於 jQuery 的 $("#id") 之類的呢?

2.12.1 單個 DOM 元素獲取

返回目錄

話很少說,先上代碼:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var App = {
      template: `
        <div>
          <button ref="btn">按鈕</button>
        </div>
      `,
      beforeCreate: function() {
        // 這裏不能操做數據,只是初始化了事件等……
        console.log(this.$refs.btn); // [Console] undefined
      },
      created: function() {
        // 能夠操做數據了
        console.log(this.$refs.btn); // [Console] undefined
      },
      beforeMount: function() {
        // new Vue 發生裝載,替換 <div id="app"></div> 以前
        console.log(this.$refs.btn); // [Console] undefined
      },
      mounted: function() {
        // 裝載數據以後
        console.log(this.$refs.btn.innerHTML); // [Console] 按鈕
      }
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `<app/>`
    })

  </script>
</body>

</html>
複製代碼

咱們先查看下頁面:

首先,咱們在組件的 DOM 部分(<button>),寫上 ref = "btn"。

而後,咱們發現只有在 mounted 數據裝載以後這個鉤子函數中,經過組件對象 this.$refs.btn 能夠獲取到元素

這樣,咱們就知道在一些場景,如何能夠方便地經過 Vue 獲取到 DOM 元素了。

2.12.2 組件 DOM 元素獲取

返回目錄

在上面,咱們獲取到了單個 DOM 節點的部分,假如咱們須要獲取到整個子組件,那麼要怎麼作呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var tempComponent = {
      template: `
        <div>我是臨時組件</div>
      `
    }

    Vue.component('temp', tempComponent);

    var App = {
      template: `
        <div>
          <temp ref="temp" />
        </div>
      `,
      mounted: function() {
        // 裝載數據以後
        console.log(this.$refs.temp.$el);
      }
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `<app/>`
    })

  </script>
</body>

</html>
複製代碼

咱們先不急着分析,先看控制檯打印出了什麼;

在這裏能夠看到它打印出了一堆關於該組件的東西,其中

  • $children - 當前組件的子組件
  • $el - 當前組件的元素節點
  • $parent - 當前組件的父組件
  • $root - 獲取 new Vue 實例

而後發現元素 $el是 DOM 節點的內容,咱們嘗試打印出來看一下:

console.log(this.$refs.temp.$el);
複製代碼

Console

<div>我是臨時組件</div>
複製代碼

經過 Console 能夠看出,$el 就能夠打印出其中的 <button> 元素了。

2.12.3 Vue.nextTick()

返回目錄

固然,咱們有時候操做 DOM,是想在 data 數據變動的時候進行操做,若是是使用上面方法,有些時候是搞不定的。

那麼,咱們應該怎麼作呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 學習</title>

</head>

<body>

  <!-- 2. Vue 掛載點 - Vue 的虛擬 DOM 在這裏操做到實際渲染 -->
  <!-- 簡單理解爲 jQuery 的拼接字符串(並不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服務 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 調用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var App = {
      template: `
        <div>
          <input v-if="isShow" ref="input" />
        </div>
      `,
      data: function() {
        return {
          isShow: true
        }
      },
      mounted: function() {
        // 但願在 Vue 真正渲染 DOM 到頁面以後進行下面操做
        this.$nextTick(function() {
          this.$refs.input.focus();
        })
      }
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `<app/>`
    })

  </script>
</body>

</html>
複製代碼

如上,經過 Vue 的全局 API Vue.nextTick(),咱們在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。

這個操做咱們可想象下 Promise 的執行流程,會得到更好的體驗。

三 實戰

返回目錄

那麼,學到這裏,咱們應該進行一個簡單的操練,來回顧咱們所學知識了:

四 總結

返回目錄

如上,咱們入門了基礎的 Vue,可能小夥伴們會以爲仍是很暈。

可是,不要緊,咱們接下來在講解 VueRouter、VueCli 的時候仍是會使用 Vue 基礎語法的,正如那句話:萬丈高樓平地起,地基還得本身起

多實操,多作筆記,總能熟練上去的,加油~


後記

若是小夥伴須要存放 jsliang.top 這樣的純靜態頁面或者 company.jsliang.top 這樣的具備 Node 後端支持的頁面,推薦購買雲服務器來存放。

若是小夥伴們不知道該怎麼選擇雲服務器,能夠查看 詳細介紹 或者加 jsliang QQ:1741020489 諮詢。

知識共享許可協議

jsliang 的文檔庫 由 梁峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可。
基於 github.om/LiangJunron… 上的做品創做。
本許可協議受權以外的使用權限能夠從 creativecommons.org/licenses/by… 處得到。
相關文章
相關標籤/搜索