vue.js结构应用程序布局

时间:2016-10-12 23:19:52

标签: vue.js

我希望使用Holy Grail layout构建我的Web应用程序,只有一个侧边栏,没有页脚。 侧边栏将用作导航栏,以及用于保存将在布局中心显示的内容的交互式选项,具体取决于当前选择的链接。 这意味着,当在导航栏中选择要导航到的链接时,它将影响侧边栏中显示的内容以用于自定义交互选项,以及中心内的主要内容。

为实现这一目标,我提出了几种方法:

  1. 方法1:
    • 拥有一个Vue实例
    • Layout组件创建我们的布局,其中HeaderNavbar用于子组件。
    • 我们的Vue实例将使用路由器,其中包含导航侧栏中每个链接的路径
    • 我们的Vue实例将呈现一个 router-view组件以显示当前路径组件
    • 每条路线都会显示其模板正在使用我们之前创建的Layout组件的组件,并使用插槽注入相应的自定义导航选项和主要内容。
  2. Layout组件:

    <template>
    <div class="app-layout">
        <header-component></header-component>
        <div class="main">
          <navbar-component>
            <slot name="navigation-menu"></slot>
          </navbar-component>
          <main>
            <slot name="main-content"></slot>
          </main>
        </div>
      </div>
    </template>
    
    <script>
      import Header from './Header.vue';
      import Navbar from './Navbar.vue';
      export default {
        name: 'Layout',
        components: {
          'header-component': Header,
          'navbar-component': Navbar
        }
      };
    </script>
    
    <style lang="sass" rel="stylesheet/scss" scoped>
      some styling to achieve our layout for the present tags in the template
    </style>
    

    Header组件:

    <template>
      <header v-once class="header">
        <router-link to="/">
          Brand
        </router-link>
      </header>
    </template>
    
    <script>
      export default {
        name: 'Header'
      };
    </script>
    
    <style lang="sass" rel="stylesheet/scss" scoped>
      some styling to achieve our layout for the present tags in the template
    </style>
    

    Navbar组件:

    <template>
      <nav class="navigation">
        <div class="links">
          // iterate on some property of this component, and create a list of links
        </div>
        <div class="menu">
          <slot name="navigation-menu"></slot>
        </div>
      </nav>
    </template>
    
    <script>
      export default {
        name: 'Navbar'
      };
    </script>
    
    <style lang="sass" rel="stylesheet/scss" scoped>
      some styling to achieve our layout for the present tags in the template
    </style>
    

    带路由的Vue实例:

    import link1Component from './components/Link1ComponentUsingLayout.vue';
    import link2Component from './components/Link2ComponentUsingLayout.vue';
    import link3Component from './components/Link3ComponentUsingLayout.vue';
    
    const router = new VueRouter({
      mode: 'history',
      routes: [
        {
          path: '/',
          redirect: '/link1'
        },
        {
          path: '/link1',
          name: 'link1',
          component: Link1ComponentUsingLayout
        },
        {
          path: '/link2',
          name: 'link2',
          component: Link2ComponentUsingLayout
        },
        {
          path: '/link3',
          name: 'link3',
          component: Link3ComponentUsingLayout
        }
      ]
    });
    
    export default new Vue({
      el: '#app',
      router,
      render: h => h('router-view')
    });
    
    1. 方法2:
      • 有两个Vue实例
      • 将布局作为index.html中的静态html而不是组件
      • 每个Vue实例将使用一个路由器(每个一个),导航栏中存在每个链接的路径
      • 其中一个实例将安装在我们的静态html导航侧栏内的html上,以及一个位于中心内容区域内的
      • 每个Vue实例将呈现一个 router-view组件以显示当前路径组件
    2. 方法3:
      • 拥有一个Vue实例
      • 我们的Vue实例将使用路由器,其中包含导航侧栏中每个链接的路径
      • 或者Vue实例将模板代表我们的布局和导航侧边栏内部,中心内容区域我们将有2个router-view组件
      • 我们的Vue实例将呈现导航侧边栏,中心内容是当前路径的组件
    3. 方法4:
      • 与方法3相同,只要点击导航内的链接,就不要使用路由器并使用动态组件在导航侧边栏和中心内容区域组件之间切换。
    4. 现在,我想知道哪种方法最好,为什么? 另外,如果你有任何新的方法,我想听听它们,并解释为什么它们会更好。

4 个答案:

答案 0 :(得分:1)

我没有更好的解释,但是我想补充一下我以前使用的另一种方法。

假定您的项目需要多种布局,例如管理员的布局,最终用户的单独布局等等。尽管这似乎不太适合您的用例,但您可以考虑将其作为补充。

Layout.vue

您的版式将包含可保留在其下任何页面上的组件。

<template>
  <div>
    <header-component />

    <div class="main">
      <navbar-component />

      <main>
        <!-- your child routes here -->
        <router-view />
      </main>
    </div>
  </div>
</template>

router.js

在路线中,您将组件或视图嵌套在Layout.vue下,如下所示:

routes: [
  {
    path: '',
    component: Layout,
    // child routes now have the style of Layout
    children: [
      {
        path: '/page1',
        name: 'Page1Name',
        component: Page1
      },
      // ...
    ]
  }
]

Layout.vue的子组件显示在其<router-view />中。

NavComponent.vue

<template>
  <nav class="navigation">
    <!-- links and other stuff -->

    <!-- your custom interactive options below -->

    <div v-if="isInRoutes('Page1Name')">
      <!-- div or some component for Page1 -->
    </div>
  </nav>
</template>

其中isInRoutes方法检查this.$route.name,否则可能会更复杂。

您的App.vue(将用h(App)渲染的那个)也将包含自己的<router-view />,以便显示布局。

App.vue

<template>
  <div>
    <router-view />
  </div>
</template>

通过这种方法,您可以创建多个布局,并使用路线将组件嵌套在特定的布局下。

答案 1 :(得分:0)

尽可能不要围绕布局构建代码。这是我希望你的外卖。

我倾向于使用基本上2但是一个深度(如3)。我有一个应用程序组件来加载components文件夹中的vue内容。我在main中有一个router-view来显示路径,标题和导航栏的标题组件,以及main底部的模态组件。

答案 2 :(得分:0)

第一种方法可能是最好的方法,除非您在任何地方都没有router-view。您也不需要使用广告位,除非您的导航会更改。而且,如果您的导航方式发生变化,您可能仍会在Navbar组件内执行此逻辑。

您可以将Layout组件简化为:

<template>
  <div class="app-layout">
    <header-component />
    <div class="main">
      <navbar-component />
      <main>
        <router-view />
      </main>
    </div>
  </div>
</template>

<script>
  import Header from './Header.vue';
  import Navbar from './Navbar.vue';
  export default {
    name: 'Layout',
    components: {
      'header-component': Header,
      'navbar-component': Navbar
    }
  };
</script>

您调用h => h('router-view')的方式将使整个应用程序呈现为router-view,这不是您想要的。您只希望main div根据您所在的路线更改内容。请将其更改为:

export default new Vue({
  el: '#app',
  router,
  render: h => h(require('./Layout')) //change this path to where Layout.vue is
});

这将使您的Layout组件成为应用程序的根组件。

答案 3 :(得分:0)

我认为您可以参考更成熟的代码。

我认为该项目中的方法与您的想法非常相似。

my write up