动态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

参考链接

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