vue高級進(jìn)階( 三 ) 組件高級用法及最佳實(shí)踐

世界上有太多孤獨(dú)的人害怕先踏出第一步庶橱。 ---綠皮書

書接上回娃闲,上篇介紹了vue組件通信比較有代表性的幾種方法厘擂,本篇主要講述一下組件的高級用法和最佳實(shí)踐程腹,爭取用最少的篇幅占領(lǐng)高地C惩啊(多說一句焕数,后續(xù)這個系列會有vue最佳實(shí)踐和源碼解讀,我總有辦法能讓大家看懂刨啸,所以點(diǎn)贊關(guān)注堡赔,不迷路啊,小老弟

本篇主要內(nèi)容

  • 遞歸組件
  • 動態(tài)組件
  • 異步組件
  • 內(nèi)聯(lián)模板 inline-template的使用
  • 全局組件批量自動注冊
  • Vue 的構(gòu)造器——extend
  • vue 修飾符sync深入解析

正文開始

遞歸組件

函數(shù)的遞歸是自己調(diào)用自己设联,這個過程有兩個必要條件:

  • 這個函數(shù)必須有函數(shù)名稱
  • 這個遞歸函數(shù)必須有結(jié)束條件,不然就會報Maximum call stack size exceeded,內(nèi)存溢出

本質(zhì)上講善已,組件也是一個函數(shù),遞歸組件自然也是自己調(diào)用自己离例,所以也要滿足兩個條件:

  • 這個組件必須有確定的name,也就是要給組件設(shè)置name
  • 必須要有一個結(jié)束條件换团,告訴組件什么時候遞歸結(jié)束

上代碼

非常簡單的功能,讓你看懂遞歸宫蛆,A.vue中引入B.vue,B組件是遞歸的核心所在

<template>
  // 要將treeData通過prop進(jìn)行傳遞
  <B :propTreeData="treeData"/>
</template>
<script>
import B from './B'
export default {
  name: "Tree",
  data() {
    return {
      treeData: [
        {
          id: "1",
          menuName: "笑傲江湖",
          menuCode: "1",
          children: [
            {
              menuName: "令狐沖",
              menuCode: "10"
            },
            {
              menuName: "東方不敗",
              menuCode: "11"
            }
          ]
        },
        {
          id: "2",
          menuName: "射雕英雄",
          menuCode: "2",
          children: [
            {
              menuName: "蓉兒",
              menuCode: "20"
            },
            {
              menuName: "郭靖",
              menuCode: "21"
            }
          ]
        }
      ]
    };
  },
  components:{B}
};
</script>
  

B組件艘包,遞歸的核心,由于是遞歸耀盗,必須結(jié)構(gòu)一致想虎,因此就必須將A中的treeData通過Props傳給B才能實(shí)現(xiàn)遞歸,這就是為啥A和B必須分離叛拷,而絕不可能通過一個組件來實(shí)現(xiàn)遞歸舌厨,不知道你懂了沒?體會一下

<template>
  <ul>
    <li v-for="item in propTreeData" :key="item.menuCode">
      {{item.menuName}}
      // 要有一個結(jié)束條件
      <tree v-if="item.children&&item.children.length" :propTreeData="item.children"></tree>
    </li>
  </ul>
</template>
<script>
export default {
  name: "Tree",
  props:{
    propTreeData:Array,
    default:()=>([])
  },
};
</script>
  

看下實(shí)現(xiàn)效果忿薇,這是一個最最簡單的遞歸裙椭,但是后續(xù)的所有的復(fù)雜功能,折疊署浩,選中揉燃,拖拽哪一個又不是基于這個來進(jìn)行的呢?復(fù)雜功能大家可以繼續(xù)擴(kuò)展筋栋,都不難

<figcaption style="box-sizing: border-box; outline: 0px; display: block; text-align: center; margin: 8px; color: rgb(153, 153, 153); font-size: 14px; overflow-wrap: break-word;"></figcaption>

動態(tài)組件

讓多個組件使用同一個掛載點(diǎn)炊汤,并動態(tài)切換,這就是動態(tài)組件。

通過使用保留的 <component> 元素婿崭,動態(tài)地綁定到它的 is 特性拨拓,可以實(shí)現(xiàn)動態(tài)組件

<template>
  <div id="example">
    <button @click="change">切換頁面</button>
  <component :is="currentView"></component>
  </div>
</template>
 
<script>
var LZL = { template: "<div>林志玲</div>" };
var GYY = { template: "<div>高圓圓</div>" };
var JJW = { template: "<div>賈靜雯</div>" };
 
export default {
  name: "App",
  components: {
    LZL,
    GYY,
    JJW
  },
  data() {
    return {
       index:0,
    arr:['LZL','GYY','JJW'],
    };
  },
  computed:{
    currentView(){
        return this.arr[this.index];
    }
  },
  methods:{
    change(){
      this.index = (++this.index)%3;
    }
  }
};
</script>
 

動態(tài)組件的緩存,會將不活動的組件實(shí)例緩存起來氓栈,而不是銷毀它們渣磷,比如切換tab后,還能保持切換之前的狀態(tài)授瘦,如果有多個條件性的子元素醋界,<keep-alive> 要求同時只有一個子元素被渲染

 <keep-alive>
    <component :is="currentView"></component>  
</keep-alive>
-----------------------------------------------
      
<keep-alive>` 要求同時只有一個子元素被渲染
 
<keep-alive>
    <LZL v-if="index===0"></LZL>
    <GYY v-else-if="index===1"></GYY>
    <JJW v-else></JJW>  
</keep-alive>
 

使用的時候,比如keep-alive下有A,B,C三個組件提完,但是我只想緩存A和B,這時候該怎么辦形纺,就要用到include和exclude】來進(jìn)行篩選過濾,根據(jù)你的過濾 條件確定緩存哪個組件

include會匹配首先檢查組件自身的 name 選項(xiàng)徒欣,如果 name 選項(xiàng)不可用逐样,則匹配它的局部注冊名稱(父組件 components 選項(xiàng)的鍵值)。匿名組件不能被匹配

<!-- 逗號分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>
<!-- 正則表達(dá)式 (使用 v-bind) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>
<!-- Array (use v-bind) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
 

異步組件

異步組件說白了就是按需加載打肝,使用時才裝入需要的組件脂新,可以有效的提高首次裝入頁面的速度。比如在路由切換時粗梭。

 {
            path: '/promisedemo',
            name: 'PromiseDemo',
            component: resolve => require(['../components/PromiseDemo'], resolve)
  }
 

利用此特性争便,我們便能做很多針對前端的優(yōu)化。 比如:將頁面核心功能(音断医、視頻播放滞乙、文章、商品等等)打包成一個核心模塊鉴嗤,通過框架優(yōu)先加載斩启。 其他的一些周邊功能打包后,通過服務(wù)器異步加載躬窜,從而解決業(yè)務(wù)需求越來越多導(dǎo)致的系統(tǒng)難維護(hù)浇垦、訪問慢問題。

既然是異步加載荣挨,就會存在加載過程(正在加載中)、以及加載失敗等異常情況,看下圖一目了然朴摊。默垄。。

<figcaption style="box-sizing: border-box; outline: 0px; display: block; text-align: center; margin: 8px; color: rgb(153, 153, 153); font-size: 14px; overflow-wrap: break-word;"></figcaption>

內(nèi)聯(lián)模板 inline-template的使用

Vue提供了一種內(nèi)聯(lián)模板的功能甚纲,在使用組件時口锭,給標(biāo)簽加上inline-complate特性,組件就會把它的內(nèi)容當(dāng)作模板,而不是當(dāng)內(nèi)容分發(fā)鹃操。其實(shí)也就是說韭寸,不在創(chuàng)建一個組件時定義它的模板,而是在聲明的外部創(chuàng)建荆隘。

父組件
<child-component inline-template>
     <div>
        <h2>在父組件中定義子組件的模板</h2>
        <p>{{msg}}</p>
     </div>
</child-component>
 
子組件
export default{
    name:'ChildComponent',
    data(){
        return{
            msg:'張不慫'
        }
    }
}
 
最終顯示
<div data-v-763db97b="">
    <h2 data-v-763db97b="">在父組件中定義子組件的模板</h2>
    <p data-v-763db97b="">張不慫</p>
</div>
 

inline-template使得各個組件的結(jié)構(gòu)混亂恩伺,建議不要輕易使用內(nèi)聯(lián)模板

全局組件批量自動注冊

我們vue組件中引入組件的一般方式是這樣的

<template>
    <A  v-model="searchText"  @keydown.enter="search"/>
    <B @click="search">
        <C name="search"/>
    </B>
</template>
<script>
    import B from './B'
    import C from './C'
    import A from './A'
    export default {
      components: { B, C, A }
    }
</script>
 

有沒有辦法可以自動全局進(jìn)行注冊呢?答案是肯定的,在你要引入的包含所有組件的文件夾components的同級目錄下建register.js,寫入下邊的代碼

const requireComponent = require.context(
  './components',   // 其組件目錄的相對路徑
  false,   // 是否查詢其子目錄
  /base_[A-Z]\w+\.(vue|js)$/   // 匹配基礎(chǔ)組件文件名的正則表達(dá)式
)
 
requireComponent.keys().forEach(fileName => {
  // 獲取組件配置
  const componentConfig = requireComponent(fileName)
 
  // 獲取組件的 PascalCase 命名
  const componentName = upperFirst(
    camelCase(
      // 剝?nèi)ノ募_頭的 `./` 和結(jié)尾的擴(kuò)展名
      fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
    )
  )
 
  // 全局注冊組件
  Vue.component(
    componentName,
    componentConfig.default || componentConfig
  )
})
 

然后在你的vue項(xiàng)目的main.js中進(jìn)行引入,就直接可以使用

import @/register.js;
 

Vue 的構(gòu)造器——extend

Vue.extend(options)

用法:使用Vue構(gòu)造器椰拒,創(chuàng)建一個“子類”晶渠,參數(shù)是一個包含組件選項(xiàng)的對象,其中,data選項(xiàng)中必須是函數(shù)

描述:Vue.extend返回的是一個“擴(kuò)展實(shí)例構(gòu)造器”燃观,也就是預(yù)設(shè)了部分選項(xiàng)的Vue的實(shí)例構(gòu)造器

自定義一個無參數(shù)標(biāo)簽

var foo = Vue.extend({
 template: "<p><a :href='url'>{{foo}}</a></p>",
 data : function() {
  return {
   foo : 'vamous',
   url : 'https://juejin.im/editor/drafts/5cd2da7a5188253e8c23baf6'
  }
 }
});
 
對應(yīng)的html
<foo></foo>
 
此時的頁面必然是沒有任何效果的褒脯,因?yàn)閿U(kuò)展實(shí)例構(gòu)造器還需要掛載,如下:
new foo().$mount('#app');
 

可以利用propsData傳遞參數(shù)

var author = Vue.extend({
 template: "<p><a :href='url'>{{bar}} & {{name}}</a></p>",
 data : function() {
  return {
   bar : 'vamous',
   url : 'https://juejin.im/editor/drafts/5cd2da7a5188253e8c23baf6'
  }
 },
 props : ['name']
});
 
new author({propsData: {name : 'foo'}}).$mount('#author');
 

vue 修飾符sync深入解析

實(shí)現(xiàn)子組件與父組件雙向綁定的【sync】修飾符:其實(shí)sync這個修飾符是vue1.0就有的缆毁,它可以實(shí)現(xiàn)父子組件的雙向綁定番川,但是Vue2.0被移除了,直到2.3.0版本發(fā)布后脊框,又重新開始啟用颁督,【.sync】可以很輕松的實(shí)現(xiàn)子組件同步修改父組件的值

如果子組件想修改父組件的值,推薦以update:my-prop-name 的模式觸發(fā)事件取而代之缚陷,也就是這樣:

父組件
<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>
---------------------------------------------------------------
子組件
this.$emit("update:title".newTitle)
 

而上邊的 v-on:update:title="doc.title = $event"适篙,本質(zhì)上就可以用sync這個語法糖來表示,.sync后面緊接的就是父組件中需要被改變的值箫爷,看下邊的例子體會一下

父組件
<template>
    <div>
        <child-com :value.sync="text" ></child-com>
    </div>
</template>
<script>
    export default{
        data(){
            return {
                text:"父組件的值",
            }
        },
    }
</script>
==================================================================================
//子組件中修改父組件的值
<template>
    <div @click="post"></div>
</template>
 
<script>
    export default{
        methods:{
            post(){
                this.$emit('update:value',"子組件的值")
            }
        }
    }
</script>
 

本篇基本就是這些嚷节,這三篇概述了vue的一些知識點(diǎn),更多的vue實(shí)踐還需要在工作中自己總結(jié)和挖掘虎锚,道阻且長,行則將至~

覺得對你有幫助硫痰,不妨點(diǎn)個

,后續(xù)持續(xù)輸出這種簡短有效的文章窜护,幫助你用最短的時間內(nèi)掌握最多的內(nèi)容效斑,畢竟誰不喜歡一勞永逸不是? ?(^_-) thank you ~

后續(xù)目錄

vue高級進(jìn)階( 一 ) 組件精髓概述

vue高級進(jìn)階( 二 ) 8種組件通信詳解

vue高級進(jìn)階( 三 ) 組件高級用法及最佳實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柱徙,一起剝皮案震驚了整個濱河市缓屠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌护侮,老刑警劉巖敌完,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異羊初,居然都是意外死亡滨溉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晦攒,“玉大人闽撤,你說我怎么就攤上這事「眨” “怎么了哟旗?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長伐脖。 經(jīng)常有香客問我热幔,道長,這世上最難降的妖魔是什么讼庇? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任绎巨,我火速辦了婚禮,結(jié)果婚禮上蠕啄,老公的妹妹穿的比我還像新娘场勤。我一直安慰自己,他們只是感情好歼跟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布和媳。 她就那樣靜靜地躺著,像睡著了一般哈街。 火紅的嫁衣襯著肌膚如雪留瞳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天骚秦,我揣著相機(jī)與錄音她倘,去河邊找鬼。 笑死作箍,一個胖子當(dāng)著我的面吹牛硬梁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胞得,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼荧止,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阶剑?” 一聲冷哼從身側(cè)響起跃巡,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牧愁,沒想到半個月后瓷炮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡递宅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片办龄。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡烘绽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出俐填,到底是詐尸還是另有隱情安接,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布英融,位于F島的核電站盏檐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏驶悟。R本人自食惡果不足惜胡野,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痕鳍。 院中可真熱鬧硫豆,春花似錦、人聲如沸笼呆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诗赌。三九已至汗茄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铭若,已是汗流浹背洪碳。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奥喻,地道東北人偶宫。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像环鲤,于是被迫代替她去往敵國和親纯趋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 組件(Component)是 Vue.js 最核心的功能冷离,也是整個框架設(shè)計最精彩的地方吵冒,當(dāng)然也是最難掌握的。本章將...
    遼A丶孫悟空閱讀 553評論 1 13
  • 在文章《Vue組件開發(fā)三板斧:prop西剥、event痹栖、slot》中聊了常用的組件開發(fā)常用API和一些采坑心得,這里瞭空,...
    娜姐聊前端閱讀 1,027評論 0 2
  • 什么是組件揪阿? 組件 (Component) 是 Vue.js 最強(qiáng)大的功能之一疗我。組件可以擴(kuò)展 HTML 元素,封裝...
    youins閱讀 9,466評論 0 13
  • 遞歸組件 組件在它的模板中可以遞歸地調(diào)用自己南捂,但是需要給組件設(shè)置 name 的選項(xiàng)吴裤。同時要注意限制遞歸的數(shù)量,否則...
    林鍵燃閱讀 169評論 0 0
  • 組件局部注冊 is 屬性掛載組件 常見:ul溺健、select麦牺、table(字符串模板除外:.vue文件) 例:在ta...
    彤_姑娘閱讀 446評論 0 0