1. 程式人生 > 其它 >vue中的動態元件

vue中的動態元件

技術標籤:vuevuekeep-alive動態元件

文章目錄


一、概念

Vue.js 提供了一個特殊的元素 <component> 用來動態地掛載不同的元件 使用 is 屬性來選擇要掛載的元件。

<!-- 元件會在 `currentTabComponent` 改變時改變 -->
<component v-bind:is="currentTabComponent"></component>

在上述示例中,currentTabComponent 可以包括

  • 已註冊元件的名字,或
  • 一個元件的選項物件

二、程式碼演示

1、is 屬性繫結已註冊元件的名字

<div id="app">
  <button @click="changeView('A')">切換到元件A</button>
  <button @click="changeView('B')">切換到元件B</button>
  <button @click="changeView('C')"
>
切換到元件C</button> <component :is="currentView"></component> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> let vm = new Vue({ el: "#app", data: { currentView: 'comA' }, components:
{ comA: { template: '<div>元件A</div>' }, comB: { template: '<div>元件B</div>' }, comC: { template: '<div>元件C</div>' } }, methods: { changeView(component) { this.currentView = 'com' + component; } } });
</script>

效果如圖所示:
在這裡插入圖片描述

2、is 屬性繫結元件物件

<div id="app">
  <component :is="currentView"></component>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  let Home = {
    template:'<div>我是元件</div>'
  }

  let vm = new Vue({
    el: "#app",
    data: {
      currentView: Home
    }
  });
</script>

3、在動態元件上使用 keep-alive

我們之前曾經在一個多標籤的介面中使用 is 屬性來切換不同的元件

<component v-bind:is="currentTabComponent"></component>

當在這些元件之間切換的時候,我們有時會想保持這些元件的狀態,以避免反覆重渲染導致的效能問題。

我們來看一個案例:

在這裡插入圖片描述
在這個案例中,如果我們選擇了一篇文章,點選 “我的” 標籤,然後再切換回 文章元件,是不會繼續展示之前選擇的文章的。這是因為你每次切換新標籤的時候,Vue 都建立了一個新的元件例項。

重新建立動態元件的行為通常是非常有用的,但是在這個案例中,我們更希望那些標籤的元件例項能夠被在它們第一次被建立的時候快取下來。為了解決這個問題,我們可以用一個 <keep-alive> 元素將其動態元件包裹起來。

<!-- 失活的元件將會被快取!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

修改後的效果如下:

在這裡插入圖片描述
現在這個 文章元件 標籤保持了它的狀態 (被選中的文章) 甚至當它未被渲染時也是如此。

keep-alive 是vue的一個內建元件,主要用於保留元件狀態或避免重新渲染<keep-alive> 包裹動態元件時,會快取不活動的元件例項,而不是銷燬它們。

注意這個 <keep-alive> 要求被切換到的元件都有自己的名字,不論是通過元件的 name 選項還是區域性/全域性註冊。

本案例的完整程式碼如下,大家可以直接複製貼上到自己本地的一個html檔案來執行測試:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>test</title>
  <style>
    .article {
      display: flex;
    }

    .left {
      width: 100px;
      border: 1px solid red;
    }

    .right {
      width: 200px;
      border: 1px solid blue;
    }

    li {
      cursor: pointer;
    }

    .selected {
      color: red;
    }
  </style>
</head>
<body>

<div id="app">
  <button @click="changeView('comA')">文章</button>
  <button @click="changeView('comB')">我的</button>
  <keep-alive>
    <componet :is="currentView"></componet>
  </keep-alive>
</div>  

<template id="cpn1">
  <div class="article">
    <div class="left">
      <ul>
        <li v-for="(item,index) in articles" @click="articleClick(index)"
            :class="{selected:currentIndex === index}">{{item.name}}
        </li>
      </ul>
    </div>
    <div class="right">
      {{content}}
    </div>
  </div>
</template>

<template id="cpn2">
  <div>
    <h2>我的介面</h2>
  </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

  let comA = {
    template: '#cpn1',
    data() {
      return {
        articles: [
          {name: '文章1', content: '內容1'},
          {name: '文章2', content: '內容2'},
          {name: '文章3', content: '內容3'}
        ],
        currentIndex: '',
        content: '請選擇一篇文章'
      }
    },
    created() {
      console.log('文章元件被建立');
    },
    destroyed() {
      console.log('文章元件被銷燬');
    },
    methods: {
      articleClick(index) {
        this.content = this.articles[index].content;
        this.currentIndex = index;
      }
    }
  }

  let comB = {
    template: '#cpn2'
  }

  let vm = new Vue({
    el: "#app",
    data: {
      currentView: 'comA'
    },
    components: {
      comA,
      comB
    },
    methods: {
      changeView(component) {
        this.currentView = component;
      }
    }
  });
</script>
</body>
</html>

三、資料

動態元件 | vue官網

keep-alive | vue官網