天天看點

Vue元件進階用法與實踐Vue元件進階用法與實踐

Vue元件進階用法與實踐

一 、基礎元件自動化全局注冊

使用場景:子產品系統内頻繁使用的基礎元件;

使用方法:使用 require.context 全局注冊;

比如說我們的内部網站,目前我們的頁面使用的是局部注冊,按需加載:

import ComponentA from './ComponentA'
import ComponentC from './ComponentC'
export default {
  components: {
    ComponentA,
    ComponentC
  },
}      

但是可能有很多類似于輸入框、按鈕等在各個元件中頻繁的使用,我們有時候會把它們稱為基礎元件;

我們内部網站的“沒有權限檢視目前頁”也可以算是一個基礎元件,每次使用的時候都需要在目前頁面引入、注冊然後再使用,但是如果使用了webpack ,那麼就可以使用 require.context 隻全局注冊這些非常通用的基礎元件:

import ComponentOne from "./ComponentOne";

components: {
  ComponentOne
}

<ComponentOne></ComponentOne>      
Vue元件進階用法與實踐Vue元件進階用法與實踐
const requireComponent = require.context(
    './components',// 其元件目錄的相對路徑
  false, // 是否查詢其子目錄
  /Base[A-Z]\w+\.(vue|js)$/ // 比對基礎元件檔案名的正規表達式
)
requireComponent.keys().forEach(fileName => {
  console.log(fileName);
  const componentConfig = requireComponent(fileName)// 擷取元件配置
  console.log(componentConfig);
  const componentName = upperFirst( // 擷取元件名
    camelCase(
      fileName
        .split('/')
        .pop()
        .replace(/\.\w+$/, '')
    )
  )
  console.log(componentName)
  Vue.component(// 全局注冊元件
    componentName,
    // 如果這個元件選項是通過 `export default` 導出的,
    // 那麼就會優先使用 `.default`,
    // 否則回退到使用子產品的根。
    componentConfig.default || componentConfig
  )
})      
Vue元件進階用法與實踐Vue元件進階用法與實踐
Vue元件進階用法與實踐Vue元件進階用法與實踐

但是自動化全局注冊在打包時會将組建代碼直接打包進項目中,增加項目大小,不能按需加載,是以推薦頻繁的使用元件才有必要進行全局自動化注冊。

Vue元件進階用法與實踐Vue元件進階用法與實踐
Vue元件進階用法與實踐Vue元件進階用法與實踐
Vue元件進階用法與實踐Vue元件進階用法與實踐

二、遞歸元件

Vue元件進階用法與實踐Vue元件進階用法與實踐

使用場景:樹狀結構;

使用方法:自己調用自己;

函數的遞歸是我們最常用的一個遞歸,通俗的說就是自己調用自己嗎,那麼遞歸需要滿足哪些條件?

1.有名字;

2.有結束條件;

元件的遞歸其實和函數 的遞歸一樣,也需要滿足上邊兩個條件,常用到的地方就是樹形結構的設計,評論回複功能等等,Let's have a try。

Vue元件進階用法與實踐Vue元件進階用法與實踐

遞歸元件Demo.docx

由于是遞歸,必須結構一緻,稍微有點局限性,這也就是為啥兩個元件必須分離,而絕不可能通過一個元件來實作遞歸。

這是一個最最簡單的元件遞歸,但是後續的所有的複雜功能,折疊,選中,拖拽都是基于這個來進行的。

三、動态元件

簡單來說,讓多個元件使用同一個挂載點,并動态切換,這就是動态元件。

通過使用保留的 <component> 元素,動态地綁定到它的 is 特性,可以實作動态元件,

使用場景:

1.router的實作原理就是動态渲染元件,适合解決複雜的頁面級别的元件的動态渲染;

2.而動态元件比較适用于元件内的切換,比如同一資料不同展示效果;

使用方法:

<template>
  <div>
    <el-button
      v-for="item in componentsList"
      :key="item.id"
      style="margin-left:10px"
      size="mini"
      @click="currentView=item.value"
    >
      <span>{{item.name}}</span>
    </el-button>
    <component :is="currentView"></component>
  </div>
</template>
<script>
export default {
  name: "DynamicComponents",
  data() {
    return {
      currentView: "DynamicComponentsOne",
      componentsList: [
        {
          id: 1,
          name: "元件一",
          value: "DynamicComponentsOne",
        },
        {
          id: 2,
          name: "元件二",
          value: "DynamicComponentsTwo",
        },
        {
          id: 3,
          name: "元件三",
          value: "DynamicComponentsThree",
        },
      ],
    };
  },
};
</script>      
Vue元件進階用法與實踐Vue元件進階用法與實踐

但是你會發現,動态元件切換也會把資料清空;

Vue元件進階用法與實踐Vue元件進階用法與實踐

提一下keep-alive元件緩存:keep-alive是Vue提供的一個抽象元件,用來對元件進行緩存,進而節省性能,由于是一個抽象元件,是以在頁面渲染完畢後不會被渲染成一個DOM元素。

但是同樣也存在一個問題就是被keep-alive包裹的元件我們請求擷取的資料不會再重新渲染頁面,解決方法就是使用include 和 exclude 屬性允許元件有條件地緩存,或者需要我們在特定的情況下強制重新整理某些元件。

當元件在keep-alive内被切換時元件的activated、deactivated這兩個生命周期鈎子函數會被執行,在這裡可以做一些需要的操作。

<keep-alive>
    <loading></loading>
</keep-laive>      

動态元件Demo.docx

四、異步元件

在使用異步之前,每次打包項目後所有的資料都會被打包到一起生成一個app.js的檔案,網站首次加載時加載這個檔案,雖然說很多資料都是目前頁面不需要的;

Vue元件進階用法與實踐Vue元件進階用法與實踐

異步元件說白了就是按需加載,隻有等到在頁面裡顯示該元件的時候才會從伺服器加載并緩存,不顯示的話就不會加載,這樣即可提高用戶端的通路速度也可以降低對伺服器的請求次數,可謂優化的一個利器。

按需加載的三種方式:

1. vue異步元件技術

{
    path: '/home',
    name: 'HomePage',
    component: resolve => require(['@/views/HomePage'], resolve)
}      

2. es提案的import();(需要webpack > 2.4)

路由懶加載:

const HomePage = () => import(/* webpackChunkName: "HomePage" */ '@/views/HomePage')
{
    path: '/home',
    name: 'HomePage',
    component: HomePage
}      

異步元件:

components: {
    HomePage: () => import('@/views/HomePage')
  },      

3. webpack提供的require.ensure()

{
    path: '/home',
    name: 'HomePage',   
    component: resolve => require.ensure([], () => resolve(require('@/views/HomePage')), 'home')
}      

配置:vue.config.js

module.exports={
    chainWebpack:config=>{
        config.plugins.delete("prefetch") //取消預加載
    }
}      

内部網站為例:

未使用路由懶加載,打包後生成一個app.js檔案,首次加載時載入;

使用路由懶加載,打包後生成多個js檔案,每個路由對應的頁面首次加載隻會加載目前頁面需要的js檔案并緩存;

五、元件插槽

是元件的一塊HTML模闆,這塊模闆顯示不顯示、以及怎樣顯示由父元件來決定;

1.單個/預設/匿名插槽-一個元件隻能有一個該類插槽

//子元件
<template>
  <div>
      <span>我是子元件</span>
      <slot>我是子元件的插槽</slot>
  </div>
</template>
//父元件
<template>
  <div>
    <span>我是父元件</span>
    <SlotChild>
      <div style="color:#999900">
        <span>我是父元件在子元件安置的</span>
      </div>
    </SlotChild>
  </div>
</template>      

2.具名插槽-可出現多次

//子元件
<template>
  <div>
      <span>我是子元件</span>
      <slot name="up">我是子元件的具名插槽up</slot>
      <slot name="down">我是子元件的具名插槽down</slot>
  </div>
</template>
//父元件
<template>
  <div>
    <span>我是父元件</span>
    <SlotChild>
      <div style="color:#999900" slot="up">
        <span>我是父元件在子元件安置的up</span>
      </div>
      <div style="color:#009900" slot="down">
        <span>我是父元件在子元件安置的down</span>
      </div>
    </SlotChild>
  </div>
</template>      

3.作用域插槽/帶資料的插槽-樣式交給父元件,資料交給子元件

//子元件中
<slot name="region" :data="clildData">我是子元件的作用域插槽</slot>

  data() {
    return {
      clildData: {
        name: "我是子元件的資料",
        type: "type",
      },
    };
  },

//父元件中
<SlotChild>
  <div style="color:#000099" slot="region" slot-scope="childData">
    <span>我來自父元件,我在子元件的作用域插槽内使用它的資料:{{childData.data}}</span>
  </div>
</SlotChild>      

使用場景

六、函數元件

對于函數式元件,可以這樣定義:

Stateless(無狀态):元件自身是沒有狀态的;

Instanceless(無執行個體):元件自身沒有執行個體,也就是沒有this;

由于函數式元件擁有的這兩個特性,我們就可以把它用作高階元件(High order components),所謂高階,就是可以生成其它元件的元件。

建立一個函數元件非常容易,你需要做的就是在單檔案元件 (SFC)中添加一個 functional: true 屬性,或者在模闆中添加 functional。由于它像函數一樣輕巧,沒有執行個體引用,是以渲染性能提高了不少。

函數元件依賴于上下文,并随着其中給定的資料而突變。

//基本寫法
 {
  functional: true,
  // Props 是可選的
  props: {
    // ...
  },
  // 為了彌補缺少的執行個體
  // 提供第二個參數作為上下文元件需要的data、prop、slots、children、parent都是通過這個上下文來傳遞。比如this.level要改寫為context.props.level,this.$slots.default改變為context.children。
  render: function (createElement, context) {
    // ...
  }
}
      

函數化元件不常用,它應該應用于以下場景:

一個簡單的展示元件,也就是dumb元件,比如buttom、tags、cards.....。

children、props 或者 data 在傳遞給子元件之前,處理它們。

簡單的展示。

同樣函數式元件可能不适用于許多情況。畢竟,使用 JavaScript 架構的目的是建構響應式的應用程式。在 Vue 中,如果沒有響應式,就無法做到這一點。

七、自定義元件雙向綁定

自定義元件實作 v-model 雙向綁定,首先要先明白 v-model,這個指令到底實作了什麼?

v-model實際做的事情就是:傳入一個value屬性值,雙向綁定會預設監聽input事件并傳回一個值

在子元件 emit 一個 input 事件,并傳回一個值,父元件調用 v-model 的時候會預設執行這個時間;

# 正常寫法
<input type="text" v-model="userName" />
# 等價于這種寫法
<input type="text" :value="userName" @input="userName = $event.target.value" />      

八、強制更新

如果你發現你自己需要在 Vue 中做一次強制更新,99.9% 的情況,是你在某個地方做錯了事。

你可能還沒有留意到數組或對象的變更檢測注意事項,或者你可能依賴了一個未被 Vue 的響應式系統追蹤的狀态。

然而,如果你已經做到了上述的事項仍然發現在極少數的情況下需要手動強制更新,那麼你可以通過 $forceUpdate 來做這件事。

繼續閱讀