動態Vue.js佈局組件

動態Vue.js佈局組件

前言

  • vue.js是漸進增強的視圖庫,可以作爲.html頁面部分使用,也可以結合vue-router、vuex、axios用來構建單頁面或多頁面應用。以開發單頁面爲例,開發過程中爲遇到,不同的頁面需要使用不同的頁面佈局情況,下面我們將探索Vue.js中處理佈局的多種方式。
  • 構建Vue Router驅動的Vue應用程序.(基本結構如下),它能很好的工作。(但假設有一個結帳流程,您不想顯示導航。或者您可能有帶側邊欄的產品頁面和沒有側邊欄的其他頁面等等)面對這種多樣性要求,我們要怎麼做來滿足業務需求的同時,保持代碼的可維護、易擴展呢?下面一起來探討。
<template>
  <div class="App">
    <nav class="App__nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <router-view/>
    <footer>
      &copy; Awesome Company
    </footer>
  </div>
</template>

實現方式

  1. 條件渲染:最基本和最直接的方法是有條件地渲染布局的某些部分。因此,您可以將v-if指令添加到佈局的某些部分,並根據需要切換可見性。
<template>
   <div class="App">
    <nav v-if="showNav" class="App__nav">
       <router-link to="/">Home</router-link> |
       <router-link to="/about">About</router-link>
     </nav>
     <router-view/>
     <footer v-if="showFooter">
       &copy; Awesome Company
     </footer>
   </div>
 </template>

-說明:這種方法的一個問題是,您必須控制應用程序中某些元素的可見性,通過在Vue.js中處理全局狀態。雖然如果您不需要非常複雜的佈局並且只是想在某些上下文中隱藏某些元素,這可能是正確的方法,但隨着應用程序的增長,這種方法可能會成爲維護的噩夢。

  1. 靜態佈局包裝器組件:使用普通組件(包含佈局不同部分的一個或多個插槽)作爲視圖的包裝器,它提供了很大的靈活性,並且感覺不像條件渲染方法那麼髒。
// app.vue
<template>
  <div class="App">
    <router-view/>
  </div>
</template>

// LayoutDefault.vue
<template>
  <div class="LayoutDefault">
    <nav class="LayoutDefault__nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <main class="LayoutDefault__main">
      <slot/>
    </main>
    <footer class="LayoutDefault__footer">
      &copy; Awesome Company
    </footer>
  </div>
</template

// home.vue
<template>
  <layout-default>
    <div class="Home">
      <h1>Home</h1>
      <p>
        Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
        eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
        voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
        clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
        amet.
      </p>

      <h2>Amet sit</h2>
      <p>
        Eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
        voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
        clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
        amet.
      </p>
    </div>
  </layout-default>
</template>

<script>
import LayoutDefault from '../layouts/LayoutDefault.vue';

export default {
  name: 'Home',
  components: {
    LayoutDefault,
  },
};
</script>
  • 說明:
  • Home.vue組件實現LayoutDefault包裝器組件以包裝其內容。
  • 雖然在靈活性方面,這種方法具有我們所需的一切,但是在靜態佈局組件中包裝我們的視圖有一個巨大的缺點:每次路由更改時,組件都會被銷燬並重新創建。
  • 這不僅會對性能產生負面影響,因爲客戶端必須在每次路由更改時一次又一次地重新創建佈局組件(以及嵌套在其中的所有其他組件),但這也意味着您必須獲取某些數據,您在佈局的某個組件中使用的每個路徑更改。
  • 靜態佈局包裝器組件非常強大且靈活,但它們也帶來了成本。讓我們一起探討一下,如果我們能夠提出一種方法,它具有靜態包裝器組件的所有積極特性,但沒有一個是負面的,那麼它就是最佳解決方案
  1. 動態佈局包裝器組件
  • 在我們開始之前,先介紹一下Vue.js中的組件系統的一個非常強大的功能動態組件
<component :is="SomeComponent"/>
  • 在上面的示例中,SomeComponent是一個變量,可以動態分配給任何組件,每次分配不同的組件時,模板都會在您定義標記的位置呈現新組件。
  • 我們可以使用動態組件來構建一個非常靈活且高性能的動態佈局系統。代碼如下:
// app.vue
<template>
  <component :is="layout">
    <router-view :layout.sync="layout"/>
  </component>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      layout: 'div',
    };
  },
};
</script>

// home.vue
<template>
  <div class="Home">
    <h1>Home</h1>
    <!-- ... -->
  </div>
</template>

<script>
import LayoutDefault from '../layouts/LayoutDefault.vue';

export default {
  name: 'Home',
  created() {
    this.$emit('update:layout', LayoutDefault);
  },
};
</script>
  • 上面你可以看到我們不再將Layout視圖的模板包裝在LayoutDefault組件中,但我們加載組件並將其作爲我們在App基礎組件中定義的layout屬性的新值發出。這意味着,一旦創建Home組件,包裝呈現Home組件的的動態組件將被重新呈現,以呈現我們在created()鉤子中發出的組件。
  • 爲什麼說這比靜態包裝器組件更好? 主要區別在於,佈局組件不是路由器視圖組件的一部分,而是包裹它。這意味着,如果視圖組件使用與先前視圖組件不同的佈局,則僅==重新呈現佈局組件==。
  1. 繼續重構代碼使得使用動態佈局更加直觀
// 修改home.vue
<template>
   <layout name="LayoutDefault">
     <div class="Home">
       <h1>Home</h1>
       <!-- ... -->
     </div>
   </layout>
</template>
 
<script>
  import Layout from '../layouts/Layout';
 
  export default {
    name: 'Home',
    components: {
      Layout,
    },
  };
</script>


// src/layouts/Layout.js
import Vue from 'vue';

export default {
  name: 'Layout',
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  created() {
    // Check if the layout component
    // has already been registered.
    if (!Vue.options.components[this.name]) {
      Vue.component(
        this.name,
        () => import(`../layouts/${this.name}.vue`),
      );
    }

    this.$parent.$emit('update:layout', this.name);
  },
  render() {
    return this.$slots.default[0];
  },
};
<templat

參考鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章