沒有廢話的vue高級進階( 三 ) 組件高級用法及最佳實踐

世界上有太多孤獨的人懼怕先踏出第一步。      ---綠皮書

書接上回,上篇介紹了vue組件通訊比較有表明性的幾種方法,本篇主要講述一下組件的高級用法和最佳實踐,爭取用最少的篇幅佔領高地!(多說一句,後續這個系列會有vue最佳實踐和源碼解讀,我總有辦法能讓你們看懂,因此點贊關注,不迷路啊,小老弟javascript

本篇主要內容
  • 遞歸組件
  • 動態組件
  • 異步組件
  • 內聯模板 inline-template的使用
  • 全局組件批量自動註冊
  • Vue 的構造器——extend
  • vue 修飾符sync深刻解析
正文開始

遞歸組件

函數的遞歸是本身調用本身,這個過程有兩個必要條件:html

  • 這個函數必須有函數名稱
  • 這個遞歸函數必須有結束條件,否則就會報Maximum call stack size exceeded,內存溢出

本質上講,組件也是一個函數,遞歸組件天然也是本身調用本身,因此也要知足兩個條件:前端

  • 這個組件必須有肯定的name,也就是要給組件設置name
  • 必需要有一個結束條件,告訴組件何時遞歸結束
上代碼

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

<template>
  // 要將treeData經過prop進行傳遞
  <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組件,遞歸的核心,因爲是遞歸,必須結構一致,所以就必須將A中的treeData經過Props傳給B才能實現遞歸,這就是爲啥A和B必須分離,而毫不可能經過一個組件來實現遞歸,不知道你懂了沒?體會一下java

<template>
  <ul>
    <li v-for="item in propTreeData" :key="item.menuCode">
      {{item.menuName}}
      // 要有一個結束條件
      <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>

複製代碼

看下實現效果,這是一個最最簡單的遞歸,可是後續的全部的複雜功能,摺疊,選中,拖拽哪個又不是基於這個來進行的呢?複雜功能你們能夠繼續擴展,都不難web

動態組件

讓多個組件使用同一個掛載點,並動態切換,這就是動態組件。正則表達式

經過使用保留的 <component> 元素,動態地綁定到它的 is 特性,能夠實現動態組件promise

<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>
複製代碼

動態組件的緩存,會將不活動的組件實例緩存起來,而不是銷燬它們,好比切換tab後,還能保持切換以前的狀態,若是有多個條件性的子元素,<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】來進行篩選過濾,根據你的過濾 條件肯定緩存哪一個組件**bash

include會匹配首先檢查組件自身的 name 選項,若是 name 選項不可用,則匹配它的局部註冊名稱(父組件 components 選項的鍵值)。匿名組件不能被匹配

<!-- 逗號分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>
<!-- 正則表達式 (使用 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)
  }
複製代碼

利用此特性,咱們便能作不少針對前端的優化。 好比:將頁面核心功能(音、視頻播放、文章、商品等等)打包成一個核心模塊,經過框架優先加載。 其餘的一些周邊功能打包後,經過服務器異步加載,從而解決業務需求愈來愈多致使的系統難維護、訪問慢問題。

既然是異步加載,就會存在加載過程(正在加載中)、以及加載失敗等異常狀況,看下圖一目瞭然。。。

內聯模板 inline-template的使用

Vue提供了一種內聯模板的功能,在使用組件時,給標籤加上inline-complate特性,組件就會把它的內容看成模板,而不是當內容分發。其實也就是說,不在建立一個組件時定義它的模板,而是在聲明的外部建立。

父組件
<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使得各個組件的結構混亂,建議不要輕易使用內聯模板

全局組件批量自動註冊

咱們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> 複製代碼

有沒有辦法能夠自動全局進行註冊呢?答案是確定的,在你要引入的包含全部組件的文件夾components的同級目錄下建register.js,寫入下邊的代碼

const requireComponent = require.context(
  './components',   // 其組件目錄的相對路徑
  false,   // 是否查詢其子目錄
  /base_[A-Z]\w+\.(vue|js)$/   // 匹配基礎組件文件名的正則表達式
)

requireComponent.keys().forEach(fileName => {
  // 獲取組件配置
  const componentConfig = requireComponent(fileName)

  // 獲取組件的 PascalCase 命名
  const componentName = upperFirst(
    camelCase(
      // 剝去文件名開頭的 `./` 和結尾的擴展名
      fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
    )
  )

  // 全局註冊組件
  Vue.component(
    componentName,
    componentConfig.default || componentConfig
  )
})

複製代碼

而後在你的vue項目的main.js中進行引入,就直接可使用

import @/register.js;
複製代碼

Vue 的構造器——extend

Vue.extend(options)

用法:使用Vue構造器,建立一個「子類」,參數是一個包含組件選項的對象,其中,data選項中必須是函數

描述:Vue.extend返回的是一個「擴展實例構造器」,也就是預設了部分選項的Vue的實例構造器

自定義一個無參數標籤

var foo = Vue.extend({
 template: "<p><a :href='url'>{{foo}}</a></p>",
 data : function() {
  return {
   foo : 'vamous',
   url : 'https://juejin.im/editor/drafts/5cd2da7a5188253e8c23baf6'
  }
 }
});

對應的html
<foo></foo>

此時的頁面必然是沒有任何效果的,由於擴展實例構造器還須要掛載,以下:
new foo().$mount('#app');
複製代碼

能夠利用propsData傳遞參數

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深刻解析

實現子組件與父組件雙向綁定的【sync】修飾符:其實sync這個修飾符是vue1.0就有的,它能夠實現父子組件的雙向綁定,可是Vue2.0被移除了,直到2.3.0版本發佈後,又從新開始啓用,【.sync】能夠很輕鬆的實現子組件同步修改父組件的值

若是子組件想修改父組件的值,推薦以update:my-prop-name 的模式觸發事件取而代之,也就是這樣:

父組件
<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",本質上就能夠用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的一些知識點,更多的vue實踐還須要在工做中本身總結和挖掘,道阻且長,行則將至~

以爲對你有幫助,不妨點個

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

後續目錄

沒有廢話的vue高級進階( 一 ) 組件精髓概述

沒有廢話的vue高級進階( 二 ) 8種組件通訊詳解

沒有廢話的vue高級進階( 三 ) 組件高級用法及最佳實踐

相關文章
相關標籤/搜索