iT邦幫忙

2021 iThome 鐵人賽

DAY 25
0
自我挑戰組

Vue.js 從零開始系列 第 25

Vue.js 從零開:v-bind:is 動態元件

  • 分享至 

  • xImage
  •  

如果要控制元件出現或是消失,依照之前討論的章節,會使用到v-ifv-show的指令來完成,但當你的元件較多時,寫的code會看起來很多,這時可以使用:is來優化,下面用tab功能來當範例。


分頁功能 v-if

<div id="app">
  <button v-for="item in tab" :key="item" @click="click(item)">
    {{ item }}
  </button>
  <tab-one v-if="title === 'One'">{{ item }}</tab-one>
  <tab-two v-if="title === 'Two'"></tab-two>
</div>
const app = Vue.createApp({
  data() {
    return {
      title: 'One',
      tab: ['One', 'Two']
    }
  },
  methods: {
    click(e){
      this.title = e;
    }
  },
});
app.component('tab-one',{
  template: `<div>one-component</div>`
});
app.component('tab-two',{
  template: `<div>two-component</div>`
});

app.mount('#app');
  1. 註冊兩個內層元件tab-onetab-two
  2. 外層元件html模組,增加內層元件v-if判斷。
  3. 透過@click="click(item)"改變外層元件的data,做到切換分頁功能。

目前子元件只有兩個用v-if來寫還看不差異,數量較多就可以改為:is方式來處理。


分頁功能 v-bind:is

<div id="app">
    <button v-for="item in tabs" :key="item" @click="titleTab = item">
        {{ item }}
    </button>
    <!-- titleTab的值有變化,元件跟著切換 -->
    <component :is="tabComponent">
</div>
const app = Vue.createApp({
  data() {
    return {
      titleTab: 'One',
      tabs: ['One','Two','Three','Four','Five','six'],
    };
  },
  computed: {
    tabComponent() {
      // 轉成小寫並回傳 ,符合相對應的component名稱,就會顯示。
      return `tab-${ this.titleTab.toLowerCase() }`
    }
  }
});
app.component("tab-one", {
  template: `<div class="tab">One component</div>`
});
app.component("tab-two", {
  template: `<div class="tab">Two component</div>`
});
app.component("tab-three", {
  template: `<div class="tab">three component</div>`
});
app.component("tab-four", {
  template: `<div class="four">four component</div>`
});
app.component("tab-five", {
  template: `<div class="tab">five component</div>`
});
app.component("tab-six", {
  template: `<div class="tab">six component</div>`
});
app.mount("#app");

新增了六個子元件,在外層元件模板使用v-if就要寫六次。

  1. 這邊改寫為<component :is="tabComponent">
  2. 增加computed屬性,如果titleTab的值有變化,元件跟著切換,並改變computedName

目前分頁功能可以正常運作,如果在每個子元件都放一個input輸入框,觀察裡面值的變化。


改寫上一個範例的Js

const app = Vue.createApp({
  data() {
    return {
      titleTab: 'One',
      tabs: ['One','Two','Three'],
    };
  },
  computed: {
    tabComponent() {
      // 轉成小寫並回傳 ,符合相對應的component名稱,就會顯示。
      return `tab-${ this.titleTab.toLowerCase() }`
    }
  }
});
app.component("tab-one", {
  template: `<div class="tab">One component</div>
  <input type="text" v-model="text">`,
  data() {
    return {
      text: "第一個子元件"
    }
  }
});
app.component("tab-two", {
  template: `<div class="tab">Tow component</div>
  <input type="text" v-model="text">`,
  data() {
    return {
      text: "第二個子元件"
    }
  }
});
app.component("tab-three", {
  template: `<div class="tab">Tow component</div>
  <input type="text" v-model="text">`,
  data() {
    return {
      text: "第三個子元件"
    }
  }
});
app.mount("#app");

修改輸入框的文字,再切換其他分頁,會發現修改後的值,不會被留存,為了解決這个問題Vue.js提供了<keep-alive>元素,來改善這個問題。


<keep-alive>

將要保留的元件,放在<keep-alive>元素即可:

<keep-alive>
    <component :is="tabComponent">
</keep-alive>

參考資料

重新認識 Vue.js
:is
keep-alive


上一篇
Vue.js 從零開始 mitt
下一篇
Vue.js 從零開始:provide / inject
系列文
Vue.js 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言