vue.js學習之組件(下篇)

来源:http://www.cnblogs.com/jasmine-95/archive/2017/08/21/7383707.html
-Advertisement-
Play Games

補充組件分發、動態組件,遞歸組件等剩餘知識點,以及講解了利用組件知識開發樹形demo。 ...


 本文的Demo和源代碼已放到GitHub,如果您覺得本篇內容不錯,請點個贊,或在GitHub上加個星星!

https://github.com/zwl-jasmine95/Vue_test

 以下所有知識都是基於vue.js 2.0版本


 

一、組件編譯作用域

<child-component> {{ message }}</child-component>

message 應該綁定到父組件的數據,組件作用域簡單地說是:

父組件模板的內容在父組件作用域內編譯;子組件模板的內容在子組件作用域內編譯。

組件的模板是在其作用域內編譯的,那麼組件選項對象中的數據也應該是在組件模板中使用的。

 1     <div id="component-demo">
 2         <!--  #component-demo是Vue實例掛載的元素,應該在掛載元素範圍內使用組件-->
 3         <hello-component></hello-component>
 4     </div>
 5 
 6 <script type="text/javascript">
 7     Vue.component('hello-component',{
 8         template:'<h1>hello component!</h1>'
 9     });
10     var vm = new Vue({
11         el:'#component-demo'
12     });
13 
14 </script>

在創建一個Vue實例時,除了將它掛載到某個HTML元素下,還要編譯組件,將組件轉換為HTML片段。
除此之外,Vue實例還會識別其所掛載的元素下的<hello-component>標簽,然後將<hello-component>標簽替換為HTML片段。

實際上瀏覽器仍然是不理解<hello-component>標簽的,

組件在使用前,經過編譯已經被轉換為HTML片段了,組件是有一個作用域的,那麼組件的作用域可以將它理解為組件模板包含的HTML片段,組件模板內容之外就不是組件的作用域了。

例如,hello-component組件的作用域只是下麵這個小片段:

通俗地講,在子組件中定義的數據,只能用在子組件的模板。在父組件中定義的數據,只能用在父組件的模板。如果父組件的數據要在子組件中使用,則需要子組件定義props。

 


 

二、使用slot分發內容

 1、什麼是“內容分發”?

在使用組件時,往往會這樣:

<app>
  <app-header></app-header>
  <app-footer></app-footer>
</app>

註意兩點:

  1. <app> 組件不知道它會收到什麼內容。這是由使用 <app> 的父組件決定的。

  2. <app> 組件很可能有它自己的模版。

為了讓組件可以組合,我們需要一種方式來混合父組件的內容與子組件自己的模板。這個過程被稱為 內容分發。Vue.js 實現了一個內容分發 API,參照了當前 Web 組件規範草案,使用特殊的 <slot> 元素作為原始內容的插槽。

 

2、單個slot

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>單個slot</title>
 6     <script type="text/javascript" src="../lib/js/vue.js"></script>
 7 </head>
 8 <body>
 9     <div id="demo">
10         <h1>我是父組件</h1>
11         <my-component>
12             <p>這是初始內容1</p>
13             <p>這是初始內容2</p>
14         </my-component>
15     </div>
16 
17     <template id="myComponent">
18         <div>
19             <h1>我是子組件的標題</h1>
20             <slot>沒有分發內容的時候才會顯示</slot>
21         </div>
22     </template>
23 
24     <script type="text/javascript">
25 
26         Vue.component('my-component',{
27             template:'#myComponent'
28         });
29 
30         var vm = new Vue({
31             el:'#demo'
32         });
33     </script>
34 
35 </body>
36 </html>
View Code

結果:

 除非子組件模板包含至少一個 <slot> 插口,否則父組件的內容將會被丟棄(其他情況2)當子組件模板只有一個沒有屬性的 slot 時,父組件整個內容片段將插入到 slot 所在的 DOM 位置,並替換掉 slot 標簽本身。

最初在 <slot> 標簽中的任何內容都被視為備用內容。備用內容在子組件的作用域內編譯,並且只有在宿主元素為空,且沒有要插入的內容時才顯示備用內容。

  •  其他情況1:刪除父組件模板中的內容

     

  •  其他情況2:刪除子組件模板里的<slot>

  • 其他情況3:子組件里有多個<slot>

 

(當然,這裡有兩個匿名<slot>會有警告,應該用特殊的屬性 name 來配置如何分發內容。詳見第三節 具名slot)

 

 3、具名slot

<slot> 元素可以用一個特殊的屬性 name 來配置如何分發內容。多個 slot 可以有不同的名字。具名 slot 將匹配內容片段中有對應 slot 特性的元素。

仍然可以有一個匿名 slot,它是預設 slot,作為找不到匹配的內容片段的備用插槽。如果沒有預設的 slot,這些找不到匹配的內容片段將被拋棄。

 demo :

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>具名slot</title>
 6     <script type="text/javascript" src="../lib/js/vue.js"></script>
 7 </head>
 8 <body>
 9     <div id="demo">
10         <h1>我是父組件</h1>
11         <my-component>
12             <h1 slot="header">這裡可能是一個頁面標題</h1>
13             <p>主要內容的一個段落。</p>
14             <p>另一個主要段落。</p>
15             <p slot="footer">這裡有一些聯繫信息</p>
16         </my-component>
17     </div>
18 
19     <template id="myComponent">
20         <div class="container">
21             <header>
22                 <slot name="header"></slot>
23             </header>
24             <main>
25                 <slot>這裡是匿名slot</slot>
26             </main>
27             <footer>
28                 <slot name="footer"></slot>
29             </footer>
30         </div>
31     </template>
32 
33     <script type="text/javascript">
34 
35         Vue.component('my-component',{
36             template:'#myComponent'
37         });
38 
39         var vm = new Vue({
40             el:'#demo'
41         });
42     </script>
43 </body>
44 </html>
View Code

 

 

 4、作用域插槽

2.1.0新增

 作用域插槽是一種特殊類型的插槽,用作使用一個 (能夠傳遞數據到) 可重用模板替換已渲染元素。

 1   <div class="parent">
 2         <child>
 3             <template scope="props">
 4                 <span>hello from parent</span>
 5                 <span>{{ props.text }}</span>
 6             </template>
 7         </child>
 8     </div>
 9 
10     <template id="myComponent">
11         <div class="child">
12             <slot text="hello from child">沒有分發內容的時候才會顯示</slot>
13         </div>
14     </template>
15 
16     <script type="text/javascript">
17         Vue.component('child',{
18             template:'#myComponent'
19         });
20         
21         var vm = new Vue({
22             el:'.parent'
23         });
24     </script>

 

 在子組件中,只需將數據傳遞到插槽,就像你將 props 傳遞給組件一樣

在父級中,具有特殊屬性 scope 的 <template> 元素必須存在,表示它是作用域插槽的模板。scope 的值對應一個臨時變數名,此變數接收從子組件中傳遞的 props 對象

 

 作用域插槽更具代表性的用例是列表組件,允許組件自定義應該如何渲染列表每一項。作用域插槽也可以是具名的。(線上demo

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>作用域插槽-列表</title>
 6     <script type="text/javascript" src="../lib/js/vue.js"></script>
 7 </head>
 8 <body>
 9     <div class="parent">
10         <my-list :items="items">
11             <template slot="item" scope="props">
12                 <li class="my-fancy-item">{{ props.text }}</li>
13             </template>
14         </my-list>
15     </div>
16 
17     <template id="myComponent">
18         <ul>
19             <slot name="item" v-for="item in items" :text="item.text"></slot>
20         </ul>
21     </template>
22 
23     <script type="text/javascript">
24         Vue.component('my-list',{
25             template:'#myComponent',
26             data:function () {
27                 return {
28                     items:[
29                         {id:1,text:'列表1'},
30                         {id:2,text:'列表2'},
31                         {id:3,text:'列表3'},
32                         {id:4,text:'列表4'}
33                     ]
34                 }
35             }
36         });
37 
38         var vm = new Vue({
39             el:'.parent',
40             data:{
41                 items:[]
42             }
43         });
44     </script>
45 
46 </body>
47 </html>
View Code

 

 

(這裡代碼中刪除兩處對效果並沒有什麼影響)


 

三、動態組件

 通過使用保留的 <component> 元素,動態地綁定到它的 is 特性,我們讓多個組件可以使用同一個掛載點,並動態切換:

var vm = new Vue({
  el: '#example',
  data: {
    currentView: 'component1'   //預設選中的組件
  },
  components: {
    component1: { /* ... */ },
    component2: { /* ... */ },
    component13: { /* ... */ }
  }
})
<component v-bind:is="currentView">
  <!-- 組件在 vm.currentview 變化時改變! -->
</component>

也可以直接綁定到組件對象上:

var Home = {
  template: '<p>Welcome home!</p>'
}
var vm = new Vue({
  el: '#example',
  data: {
    currentView: Home
  }
})

通過具體實例來說明:demo

 1   <div class="container">
 2         <!--導航欄-->
 3         <ul class="nav nav-pills">
 4             <li><a href="javascript:void(0)" @click="toggleTab(0)">{{tabText1}}</a></li>
 5             <li><a href="javascript:void(0)" @click="toggleTab(1)">{{tabText2}}</a></li>
 6             <li><a href="javascript:void(0)" @click="toggleTab(2)">{{tabText3}}</a></li>
 7         </ul>
 8         <!-- 點擊導航後要切換的內容容器 -->
 9         <div class="content">
10             <!-- 如果把切換出去的組件保留在記憶體中,可以保留它的狀態或避免重新渲染。為此可以添加一個 keep-alive 指令參數 -->
11             <keep-alive><component :is="currentView"></component></keep-alive>
12         </div>
13     </div>
14 
15     <!-- 點擊導航後要切換的內容 -->
16     <template id="tab-content1">
17         <div>這是第一個選項卡的內容!</div>
18     </template>
19 
20     <template id="tab-content2">
21         <div>這是第二個選項卡的內容!</div>
22     </template>
23 
24     <template id="tab-content3">
25         <div>這是第三個選項卡的內容!</div>
26     </template>
27 
28     <script type="text/javascript">
29         //局部註冊組件(選項卡內容)
30         var tab1 = {
31             template:'#tab-content1'
32         };
33         var tab2 = {
34             template:'#tab-content2'
35         };
36         var tab3 = {
37             template:'#tab-content3'
38         };
39         
40         var vm = new Vue({
41             el:'.container',
42             data:{
43                 tabText1:'選項卡1',
44                 tabText2:'選項卡2',
45                 tabText3:'選項卡3',
46                 currentView:tab1
47             },
48             //註冊局部組件
49             components:{
50                 tabComponent1:tab1,
51                 tabComponent2:tab2,
52                 tabComponent3:tab3
53             },


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如果你對jquery比較熟悉的話,應該用過 eq, first, last, get, prev, next, siblings等過濾器和方法。本文,我們就用迭代設計模式來封裝實現,類似的功能 ...
  • 歡迎各位同學加入: React-Native群:397885169 大前端群:544587175 大神超多,熱情無私幫助解決各種問題。 我想我寫的這篇博文可以幫助到很多人,接下來要分享的東西,對app而言很重要,很常見,我先上圖,大家看效果! 為什麼我們要這麼做呢?這體現出對用戶的友好,當用戶第一次 ...
  • 學習資源: Angular官網(建議翻牆):https://angularjs.org Angular中文官網:https://angular.cn 菜鳥教程:http://www.runoob.com/angularjs2 官網Demo: 我的學習步驟是從官網教程的DEMO下手,完全跟隨教程一步一 ...
  • 本文,我們接著之前的框架繼續擴展,這次擴展了一共有5個與字元串位置相關的方法 between( left, right ) 返回兩個字元串之間的內容, 如果第二個參數沒有傳遞,返回的是找到的第一個參數 之後 到 字元串結尾的所有字元串 如果第二個參數傳遞了,但是從left這個位置查找不到,就返回空字 ...
  • html代碼 <!DOCTYPE html><html><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>實現簡單的tab框</title> <link rel="st ...
  • 面向對象的三大基本特性 封裝(把相關的信息(無論數據或方法)存儲在對象中的能力) 繼承(由另一個類(或多個類)得來類的屬性和方法的能力) 多態(一個對象在不同情況下的多種形態) 定義類或對象 第一種:基於Object對象 var person = new Object(); person.name ...
  • 一、使用zepto進行jsonp跨域請求時,請求失敗時做一些處理? 需要同時設置timeout,才能捕獲到error事件。 二、圖片載入失敗時,用預設圖片替代? 這裡有兩種情況,一種是img標簽,還有一個是background:url() 1)img標簽: 可以在error事件中進行處理。 這種方法 ...
  • Vue 實戰源碼: GitHub 地址:https://github.com/zhongmeizhi/mobile-shop-vue Demo 地址: www.jackzhongmz.96.lt ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...