【问题标题】:Vuejs : Rendering components conditionally based on routeVuejs:根据路由有条件地渲染组件
【发布时间】:2020-11-06 05:43:55
【问题描述】:

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

但是在mounted 和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;
     }
  }
}

【问题讨论】:

  • 你应该考虑使用 vue-router 钩子而不是观察者:router.vuejs.org/guide/advanced/…。此外,如果您没有找到任何其他解决方案,将重复的代码分解为一个方法会更简洁:)

标签: javascript vue.js


【解决方案1】:

简单修复: 使用即时观察者

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

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

Demo

总体思路是创建“Layout”组件,在路由上使用meta标签定义每条路由的布局,然后在App.vue中使用动态组件告诉app使用哪个布局。

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'
    }
  }
];

每个布局组件中的&lt;slot&gt;&lt;/slot&gt; 是视图将呈现的位置。如果您想在每个布局的区域中呈现不同的components,也可以有多个named slotsnamed views

【讨论】:

    猜你喜欢
    • 2020-05-21
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    相关资源
    最近更新 更多