Vue.js 學習筆記 第7章 組件詳解

来源:https://www.cnblogs.com/geeksss/archive/2019/05/05/10810698.html
-Advertisement-
Play Games

組件(Component)是Vue.js最核心的功能,也是整個框架設計最精彩的地方,當然也是最難掌握的。本章將帶領你由淺入深地學習組件的全部內容,並通過幾個實戰項目熟練使用Vue組件。 ...


 

本篇目錄:

7.1 組件與復用

7.2 使用props傳遞數據

7.3 組件通訊

7.4 使用slot分發內容

7.5 組件高級用法

7.6 其他

7.7 實戰:兩個常用組件的開發

 

組件(Component)是Vue.js最核心的功能,也是整個框架設計最精彩的地方,當然也是最難掌握的。
本章將帶領你由淺入深地學習組件的全部內容,並通過幾個實戰項目熟練使用Vue組件。

7.1 組件與復用

7.1.1 為什麼使用組件

在正式介紹組件前,我們先來看一個簡單的場景,如圖7-1所示:

圖7-1中是一個很常見的聊天界面,有一些標準的控制項,比如右上角的關閉按鈕、輸入框、發送按鈕等。

你可能要問了,這有什麼難的,不就是幾個<div><input>嗎?
好,那現在需求升級了,這幾個控制項還有別的地方要用到。
沒問題,複製粘貼唄。

那如果輸入框要帶數據驗證,按鈕的圖標支持自定義呢?
這樣用JavaScript封裝後一起複制吧。

那等到項目快完結時,產品經理說,所有使用輸入框的地方,都要改成支持回車鍵提交。
好吧,給我一天的事件,我一個一個加上去。

上面的需求雖然有點變態,但卻是業務中很常見的,那就是一些控制項、JavaScript能力的復用。
沒錯,Vue.js的組件就是提高重用性的,讓代碼可重用。
當學習完組件後,上面的問題就可以分分鐘搞定了,再也不用害怕鏟平經理的奇葩需求。

我們先看一下圖7-1中的示例用組件來編寫是怎麼的,示例代碼如下:

 1 <Card style="width:350px;">
 2     <p slot="title">與 xxx 聊天中</p>
 3     <a href="#" slot="extra">
 4         <Icon type="android-close" size="18"></Icon>
 5     </a>
 6     <div style="height:100px;"></div>
 7     <div>
 8         <Row :gutter="16">
 9             <i-col span="17">
10                 <i-input v-model="value" placeholder="請輸入..."></i-input>
11             </i-col>
12             <i-col span="4">
13                 <i-button v-model="primary" icon="paper-airplane">發送</i-button>
14             </i-col>
15         </Row>
16     </div>
17 </Card>

 

是不是很奇怪,有很多我們從來都沒有見過的標簽,比如<Card><Row><i-col><input><i-button>等。
而且整段代碼除了內聯的幾個樣式外,一句CSS代碼也沒有,但最終實現的UI就是圖7-1的效果。

這些沒見過的自定義標簽就是組件,每個標簽代表一個組件,在任何使用Vue的地方都可以直接使用。
接下來,我們就看看組件的具體用法。

7.1.2 組件用法

回顧一下我們創建Vue實例的方法:

1 var app = new Vue({
2     el: "#app"
3 });

 

組件與之類似,需要註冊之後才可以使用。註冊有全局註冊和局部註冊兩種方式。
全局註冊後,任何Vue實例都可以使用。全局註冊示例代碼如下:

1 Vue.component("my-component", {
2     // 選項
3 });

 

my-component就是註冊的組件自定義標簽名稱,推薦使用小寫加減號分割的形式命名。

要在父實例中使用這個組件,必須要在實例創建前註冊。
之後就可以用<my-component></my-component>的形式來使用組件了。
實例代碼如下:

 1 <div id="app">
 2     <my-component></my-component>
 3 </div>
 4 
 5 <script>
 6     Vue.component("my-component", {
 7         // 選項
 8     });
 9     
10     var app = new Vue({
11         el: "#app"
12     });
13 </script>

 

此時打開頁面還是空白的,因為我們註冊的組件沒有任何內容。
在組件選項中添加template就可以顯示組件內容了。
實例代碼如下:

1 Vue.component("my-component", {
2     template: "<div>這裡是組件的內容</div>"
3 });

 

渲染後的結果是:

1 <div id="app">
2     <div>這裡是組件的內容</div>
3 </div>

 

template的DOM結構必須被一個元素包含,如果直接寫成“這裡是組件的內容”,不帶<div></div>是無法渲染的。

在Vue實例中,使用components選項可以局部註冊組件,註冊後的組件只有在該實例作用域下有效。
組件也可以使用components選項來註冊組件,該組件可以嵌套。
示例代碼如下:

 1 <div id="app">
 2     <my-component></my-component>
 3 </div>
 4 
 5 <script>
 6     var Child = {
 7         template: "<div>局部註冊組件的內容</div>"
 8     };
 9     
10     var app = new Vue({
11         el: "#app",
12         components: {
13             "my-component": Child
14         }
15     });
16 </script>

 

Vue組件的模板在某些情況下回收到HTML的限制,比如<table>內規定只允許是<tr><td><th>等這些表格元素,所以在<table>內直接使用組件是無效的。
這種情況下,可以使用特殊的is屬性來掛載組件,示例代碼如下:

 1 <div id="app">
 2     <table>
 3         <tbody is="my-component"></tbody>
 4     </table>
 5 </div>
 6 
 7 <script>
 8     Vue.component("my-component", {
 9         template: "<div>這裡是組件的內容</div>"
10     });
11     
12     var app = new Vue({
13         el: "#app"
14     });
15 </script>

 

<tbody>在渲染時,會被替換為組件的內容。
常見的限制元素還有<ul><ol><select>

提示:
如果使用的是字元串模板,是不受限制的,比如後面章節介紹的.vue單文件用法等。

除了template選項外,組件還可以像Vue實例那樣使用其他的選項,比如datacomputedmethod等。
但是在使用data時,和實例稍有區別,data必須是函數,然後將數據return出去。
例如:

 1 <div id="app">
 2     <my-component></my-component>
 3 </div>
 4 
 5 <script>
 6     Vue.component("my-component", {
 7         template: "<div>{{message}}</div>",
 8         data: function() {
 9             return {
10                 message: "組件內容"
11             };
12         }
13     });
14     
15     var app = new Vue({
16         el: "#app"
17     });
18 </script>

 

JavaScript對象是引用關係,所以如果return出的對象引用了外部的一個對象,那這個對象就是共用的,任何一方修改都會同步。
比如下麵的示例:

 1 <div id="app">
 2     <my-component></my-component>
 3     <my-component></my-component>
 4     <my-component></my-component>
 5 </div>
 6 
 7 <script>
 8     var data = {
 9         counter: 0
10     };
11     
12     Vue.component("my-component", {
13         template: "<button @click='counter++'>{{counter}}</button>",
14         data: function() {
15             return data;
16         }
17     });
18     
19     var app = new Vue({
20         el: "#app"
21     });
22 </script>

 

組件使用了3次,但是點擊任意一個<button>,3個按鈕的數字都會加1。
那是因為組件的data引用的是外部的對象,這肯定不是我們期望的效果。
所以給組件返回一個新的data對象來獨立,示例代碼如下:

 1 <div id="app">
 2     <my-component></my-component>
 3     <my-component></my-component>
 4     <my-component></my-component>
 5 </div>
 6 
 7 <script>
 8     Vue.component("my-component", {
 9         template: "<button @click='counter++'>{{counter}}</button>",
10         data: function() {
11             return {
12                 counter: 0
13             };
14         }
15     });
16     
17     var app = new Vue({
18         el: "#app"
19     });
20 </script>

 

這樣,點擊3個按鈕就互不影響了,完全達到復用的目的。

7.2 使用props傳遞數據

7.2.1 基本用法

組件不僅僅是要把模板的內容進行復用,更重要的是組件間要進行通信。
通常父組件的模板中包含子組件,父組件要正向地向子組件傳遞數據或參數,子組件接收到後根據參數的不同來渲染不同的內容或執行操作。
這個正向傳遞數據的過程就是通過props來實現的。

在組件中,使用選項props來聲明需要從父級接收的數據。
props的值可以是兩種,一種是字元串數組,一種是對象,本小節先介紹數組的用法。
比如我們構造一個數組,接收一個來自父級的數據message,並把它在組件模板中渲染,示例代碼如下:

 1 <div id="app">
 2     <my-component message="來自父組件的數據"></my-component>
 3 </div>
 4 
 5 <script>
 6     Vue.component("my-component", {
 7         props: ["message"],
 8         template: "<div>{{message}}</div>"
 9     });
10     
11     var app = new Vue({
12         el: "#app"
13     });
14 </script>

 

渲染後的結果為:

1 <div id="app">
2     <div>來自父組件的數據</div>
3 </div>

 

props中聲明的數據與組件data函數return的數據主要區別就是props的來自父級,而data中的是組件自己的數據,作用域是組件本身,這兩種數據都可以在模板template及計算屬性computed和方法methods中使用。
上例的數據message就是通過props從父級傳遞過來的,在組件的自定義標簽上直接寫該props的名稱,如果要傳遞多個數據,在props數組中添加項即可。

由於HTML特性不區分大小寫,當使用DOM模板時,駝峰命名(camelCase)的props名稱要轉為短橫分隔命名(kebab-case)。例如:

 1 <div id="app">
 2     <my-component warning-text="提示信息"></my-component>
 3 </div>
 4 
 5 <script>
 6     Vue.component("my-component", {
 7         props: ["warningText"],
 8         template: "<div>{{warningText}}</div>"
 9     });
10     
11     var app = new Vue({
12         el: "#app"
13     });
14 </script>

 

提示:
如果使用的是字元串模板,仍然可以忽略這些限制。

有時候,傳遞的數據並不是直接寫死的,而是來自父級的動態數據,這是可以使用指令v-bind來動態綁定props的值,當父組件的數據變化時,也會傳遞給子組件。示例代碼如下:

 1 <div id="app">
 2     <input type="text" v-model="parentMessage">
 3     <my-component :message="parentMessage"></my-component>
 4 </div>
 5 
 6 <script>
 7     Vue.component("my-component", {
 8         props: ["message"],
 9         template: "<div>{{message}}</div>"
10     });
11     
12     var app = new Vue({
13         el: "#app",
14         data: {
15             parentMessage: ""
16         }
17     });
18 </script>

 

這裡用v-model綁定了父級的數據parentMessage
當通過輸入框任意輸入時,子組件接收的props(message)也會實時響應,並更新組件模板。

提示:
註意,如果你要直接傳遞數字、布爾值、數組、對象,而且不使用v-bind,傳遞的僅僅是字元串,嘗試下麵的示例來對比。

 1 <div id="app">
 2     <my-component message="[1,2,3]"></my-component>
 3     <my-component :message="[1,2,3]"></my-component>
 4 </div>
 5 <script>
 6     Vue.component("my-component", {
 7         props: ["message"],
 8         template: "<div>{{message.length}}</div>"
 9     });
10     var app = new Vue({
11         el: "#app"
12     });
13 </script>

同一個組件使用了兩次,區別僅僅是第二個使用的是v-bind

渲染後的結果:第一個是7,第二個才是數組的長度3。

7.2.2 單向數據流

Vue 2.x與Vue 1.x比較大的一個改變就是,Vue 2.x通過props傳遞數據是單向的了,也就是父組件數據變化時會傳遞給子組件,但是反過來不行。
而在Vue 1.x里提供了.sync修飾符來支持雙向綁定。
之所以這樣設計,是儘可能將父子組件解耦,避免子組件無意中修改了父組件的狀態。

業務中經常用到兩種需要改變prop的情況,一種是父組件傳遞初始值進來,子組件將它作為初始值保存起來,在自己的作用域下可以隨意使用和修改。
何種情況可以在組件data內再聲明一個數據,引用父組件的prop,實例代碼如下:

 1 <div id="app">
 2     <my-component :init-count="1"></my-component>
 3 </div>
 4 
 5 <script>
 6     Vue.component("my-component", {
 7         props: ["initCount"],
 8         template: "<div>{{count}}</div>",
 9         data: function() {
10             return {
11                 count: this.initCount
12             };
13         }
14     });
15     
16     var app = new Vue({
17         el: "#app"
18     });
19 </script>

 

組件中聲明瞭數據count,它在組件初始化時會獲取來自父組件的initCount,之後就與之無關了,只用維護count,這樣就可以避免直接操作initCount

另一種情況就是prop作為需要轉變的原始值傳入。
這種情況用計算屬性就可以了,示例代碼如下:

 1 <div id="app">
 2     <my-component :width="100"></my-component>
 3 </div>
 4 
 5 <script>
 6     Vue.component("my-component", {
 7         props: ["width"],
 8         template: "<div :style='style'>組件內容</div>",
 9         computed: {
10             style: function() {
11                 return {
12                     width: this.width + "px"
13                 };
14             }
15         }
16     });
17     
18     var app = new Vue({
19         el: "#app"
20     });
21 </script>

 

因為用CSS傳遞寬度要帶單位(px),但是每次都寫太麻煩,而且數值計算一般是不帶單位的,所以統一在組件內使用計算屬性就可以了。

提示:
註意,在JavaScript中對象和數組是引用類型,指向同一個記憶體空間,所以props是對象和數組時,在子組件內改變時會影響父組件的。

7.2.3 數據驗證

我們上面所介紹的props選項的值都是一個數組,一開始也介紹過,除了數組外,還可以是對象,當prop需要驗證時,就需要對象寫法。

一般當你的組件需要提供給別人使用時,推薦都進行數據驗證。
比如某個數據必須是數字類型,如果傳入字元串,就會在控制台彈出警告。

一下是幾個prop的示例:

 1 Vue.component("my-component", {
 2     props: {
 3         // 必須是數字類型
 4         propA: Number,
 5         // 必須是字元串或數字類型
 6         propB: [String, Number],
 7         // 布爾值,如果沒有定義,預設值就是true
 8         propC: {
 9             type: Boolean,
10             default: 
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 下載: https://github.com/MyCATApache/Mycat-download 安裝: 直接解壓 運行命令: linux: ./mycat start 啟動 ./mycat stop 停止 ./mycat console 前臺運行 ./mycat restart 重啟服務 ./m ...
  • SQL中進行轉列 在很多筆試的程式員中會有很多寫SQL的情況,其中很多時候會考察行轉列。那麼這個時候如果能寫出來幾種行轉列的SQL,會給面試官留下比較好的印象。 以下是這次sql轉換的表結構以及數據 數據準備 1、學生表 CREATE TABLE `student` ( `stuid` VARCHA ...
  • OceanBase是阿裡巴巴和螞蟻金服完全自主研發的通用的分散式關係型資料庫,從1.0版本開始OceanBase就支持分區表,功能逐步跟ORACLE分區表相容,並且支持不同分區分佈在集群的不同節點(機器)上。本文是對OceanBase分區表的能力做一個詳細介紹。 ...
  • MySQL的SQL語言是用於訪問資料庫的最常用標準化語言。由於其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,一般中小型網站的開發都選擇MySQL作為網站資料庫。本文主要是入門知識講解,僅供學習分享使用。 ...
  • 原文鏈接 FORMAT() 之後 會滿三位加逗號, 在此基礎上進行數字運算的時候會出現預料之外的結果, 建議使用 : 任意一種 進行代替。 1 ...
  • 一.activity.xml 我這裡主要爬取的愛奇藝首頁的圖片進行輪播,應用了兩個github上的開源庫,一個banner的庫,一個載入網路圖片的庫,用開源庫能夠極大地節省我們編寫代碼的時間。 二.添加相關的庫以及網路許可權 三.activity.java 四.網路圖片載入的新類 代碼一共就這些,全部 ...
  • 最近需要把一個web端的項目做一個app,所以很多後臺代碼就順便複製了,如圖所示,在java代碼有一個簡單的時間戳格式化輸出日期的方法 Java代碼: 輸出結果: 得到的時間是2019-04-29 00:00:00 我們用時間戳轉換工具也得到了同樣的結果(時間戳轉換工具需要去除結尾的三個0) 但是在 ...
  • 一、事件背景: 我最近開源了一個個人耗時半年打造的富文本及一套適用於web後臺的ui框架,在gitee上受到網友們的關註,部分網友對我採用jquery的技術棧提出了質疑。總結起來:無非是jquery已經落後,不久將死。甚至有少數網友很激進:非vue技術棧,你不應該加入我這個群,不管你做得多好。對應這 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...