Vuejs:基于路由有条件地渲染组件

时间:2020-07-16 14:11:40

标签: javascript vue.js

某些路线的某些组件需要隐藏。通过使用从这个SO问题-Vuejs: Event on route change中发现的路由更改,我能够实现这一点。我不想在customPage中显示标题和侧边栏(route-/ customize)。但是,当我从该特定页面进行硬重新加载时,会出现问题。那没有执行手表,因此它失败了。我发现的解决方案是也将它放在mount()中,以便它也可以在重新加载时执行。

但是在安装时具有相同的功能,并且watcher看起来很奇怪。有更好的方法吗?

<template>
    <div>
        <TrialBanner v-if="$store.state.website.is_trial"/>
        <div class="page-body-wrapper" :class="{ 'p-0' : isCustomizePage}">
            <Sidebar :key="$store.state.user.is_admin" v-if="!isCustomizePage"/>
            <div class="main-panel" :class="{ 'm-0 w-100' : isCustomizePage}">
                <Header v-if="!isCustomizePage"/>
                <div class="content-wrapper" :class="{ 'p-0' : isCustomizePage}">
                    <router-view :key="$store.state.websiteId"></router-view>
                </div>
            </div>
        </div>
    </div>
</template>


mounted() {
  if(this.$route.path == '/customize') {
     this.isCustomizePage = true;
  } else {
     this.isCustomizePage = false;
  }
},
watch: {
  $route (to, from){
     if(this.$route.path == '/customize') {
       this.isCustomizePage = true;
     } else {
       this.isCustomizePage = false;
     }
  }
}

1 个答案:

答案 0 :(得分:1)

轻松修复: 使用即时观察者

watch: {
  $route: {
     immediate: true,
     handler(to, from) {
         if(this.$route.path == '/customize') {
           this.isCustomizePage = true;
         } else {
            this.isCustomizePage = false;
         }
     }
  }
}

更复杂但可扩展的修补程序: 使用“布局”组件。

Demo

通常的想法是创建“布局”组件,在路线上使用meta标签来定义每个路线的布局,然后在App.vue中使用动态组件来告诉应用使用哪种布局。

App.vue

<template>
  <div id="app">    
    <component :is="layout">
      <router-view></router-view>
    </component>
  </div>
</template>

<script>

export default {
  name: "App",
  computed: {
    layout() {
      return this.$route.meta.layout || 'default-layout';
    }
  }
};
</script>

默认布局组件

<template>
    <div>
        <TrialBanner v-if="$store.state.website.is_trial"/>
        <div class="page-body-wrapper" >
            <Sidebar :key="$store.state.user.is_admin" />
            <div class="main-panel">
                <Header />
                <div class="content-wrapper">
                    <slot></slot>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
  name: 'DefaultLayout',
};
</script>

示例自定义页面布局

<template>
    <div>
        <TrialBanner v-if="$store.state.website.is_trial"/>
        <div class="page-body-wrapper" class="p-0">
            <div class="main-panel" class="m-0 w-100">
                <div class="content-wrapper" class="p-0">
                    <slot></slot>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
  name: 'CustomizeLayout',
};
</script>

Main.js:将布局组件注册为全局组件

import DefaultLayout from '@/layouts/DefaultLayout.vue';
import CustomizeLayout from '@/layouts/CustomizeLayout.vue';

Vue.component('default-layout', DefaultLayout);
Vue.component('customize-layout', CustomizeLayout);

Router.js:路由定义了每个路由的布局

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,    
  },
  {
    path: '/customize',
    name: 'customize',
    component: CustomizeView,
    meta: {
      layout: 'customize-layout'
    }
  }
];

视图将渲染每个布局组件中的<slot></slot>。如果要在每个布局的区域中渲染不同的components,则还可以具有多个named slotsnamed views