iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

0
自我挑戰組

跟 VueJS 認識的30天系列 第 15

[DAY15]跟 Vue.js 認識的30天 - Vue 動態模組(Dynamic Components)

這次寫的內容是之前都沒使用過的,所以就盡量讓自己有概念,希望之後能使用到。

使用 v-bind:is 來切換模組

切換模組的基本語法

<component :is="currentComponent"></component>

currentComponent 是用來決定目前使用的模組是哪一個。

透過全域註冊來設定模組

<button v-for="tab of tabs" :key="tab" @click="currentTabComponent = tab">{{ tab }}</button>
<component :is="currentTabComponent"></component>
<script>
Vue.component('home',{
  template:`<div>I am home!</div>`
})
Vue.component('shop',{
  template:`<div>I am shop!</div>`
})
Vue.component('rate',{
  template:`<div>I am rate!</div>`
})
const vm = new Vue({
  el:'#vm',
  data:{
    tabs:['home','shop','rate'],
    // 指定當前欲顯示的模組'名'
    currentTabComponent:'home'
  }
})
</script>

data 中設定的 currentTabComponent 為當前欲顯示的模組, currentTabComponent 值為模組名,並透過 <component :is="currentTabComponent"></component> 中的 Attribute is 綁定 currentTabComponent ,指定顯示的模組內容。

透過在 data 設定物件

<button v-for="tab of tabs" :key="tab.name" @click="currentTabComponent = tab">{{ tab.name }}</button>
<component :is="currentTabComponent"></component>
<script>
const tabs = [{
  name: 'home',
  template: `<div>I am home!</div>`
},
{
  name: 'shop',
  template: `<div>I am shop!</div>`
},
{
  name: 'rate',
  template: `<div>I am rate!</div>`
}]

const vm = new Vue({
  el:'#vm',
  data:{
    tabs: tabs,
    // 指定當前欲顯示的模組 '物件'
    currentTabComponent: tabs[0]
  }
})
</script>

透過物件處理模組的資料(如模組名及模板),並且 currentTabComponent 的值為模組資料,而非模組名。

使用 <keep-alive> 建立動態模組緩存

在一般情況下,Vue 是透過建立新的模組,來執行模組的切換(動態模組),但這樣一來,當我們在 A 模組點選或寫下東西後,切換到 B 模組,在執行別的事情後,再返回 A 模組,會發現原本在 A 模組點選或寫下的東西都會消失(回復成初始的模組狀態)。

這樣的情況可以透過 <keep-alive> 來解決, <keep-alive> 主要是用來將沒使用到的模組緩存起來(就是將模組最後一次出現的狀態儲存起來),也因此在切換的過程中,模組的狀態不會因為切換而消失。

<button v-for="tab of tabsC" :key="tab" @click="keepAliveComponent=tab">{{tab}}</button>
<!--<keep-alive>用來包裹欲被緩存的模組-->
<keep-alive>
<component :is="keepAliveComponent"></component>
</keep-alive>
<script>
Vue.component("A", {
  template: `<div>I am A!</div>`
});
Vue.component("B", {
  template: `<div>I am B!</div>`
});
Vue.component("C", {
  template: `<div>I am C!</div>`
});

Vue.component("posts", {
  template: `<div>
  <button v-for="title of titles" :key="title" @click="currentPostComponent=title">{{title}}</button>
  <component :is="currentPostComponent"></component>
  </div>`,
  data() {
    return {
      titles: ["A", "B", "C"],
      currentPostComponent:'A'
    };
  }
});

Vue.component("archives", {
  template: `<div>
  <input type="text">
  </div>`
});

const vm = new Vue({
  el: "#vm",
  data: {    
    tabs: ["posts", "archives"],
    keepAliveComponent: "posts"
  }
});
</script>

<keep-alive> 屬性 includeexclude

  • v-bind:include="/reg/" :值為正規表達式,只有符合該值的模組才能被緩存。

  • include="string" :值為字符串,只有符合該值的模組才能被緩存。

  • v-bind:exclude="/reg/" :值為字符串或正規表達式,只有符合該值的模組才能被緩存。

  • exclude="string" :值為字符串或正規表達式,只有符合該值的模組才能被緩存。

提醒:如果值為字符串的話,就不需使用 v-bind 來綁定了!

<button v-for="tab of tabsC" :key="tab" @click="keepAliveComponent=tab">{{tab}}</button>
<!--只有 posts 模組才能被緩存-->
<!--所以 archives 模組寫下文字,切換模組之後,該文字不會被緩存起來-->
<keep-alive :include="posts">
<component :is="keepAliveComponent"></component>
</keep-alive>
<script>
Vue.component("A", {
  template: `<div>I am A!</div>`
});
Vue.component("B", {
  template: `<div>I am B!</div>`
});
Vue.component("C", {
  template: `<div>I am C!</div>`
});

Vue.component("posts", {
  template: `<div>
  <button v-for="title of titles" :key="title" @click="currentPostComponent=title">{{title}}</button>
  <component :is="currentPostComponent"></component>
  </div>`,
  data() {
    return {
      titles: ["A", "B", "C"],
      currentPostComponent:'A'
    };
  }
});

Vue.component("archives", {
  template: `<div>
  <input type="text">
  </div>`
});

const vm = new Vue({
  el: "#vm",
  data: {    
    tabs: ["posts", "archives"],
    keepAliveComponent: "posts"
  }
});
</script>

因為對於異步模組的部分研究的還不夠,看起來還可以加上 webpack 的使用,但對於 webpack 的研究也還不夠,所以這一塊就先不寫出來了!

Demo:DAY15 | 跟 Vue.js 認識的30天 - Vue 動態模組(Dynamic Components)

參考資料:

Vue.js - 动态组件 & 异步组件

Vue.js -keep-alive


上一篇
[DAY14]跟 Vue.js 認識的30天 - Vue 模組插槽(`slot`)
下一篇
[DAY16]跟 Vue.js 認識的30天 - Vue 過渡(轉場)及動畫效果上篇(`<transition>`)
系列文
跟 VueJS 認識的30天21

尚未有邦友留言

立即登入留言