Vue3 builds view admin background management system (3) - realizes navigation bar based on Vue Router

Series Article Directory

Vue3 builds view admin background management system (1) - technology selection
vue3 builds view admin background management system (2) - Vue Router uses detailed
vue3 to build view admin background management system (3) - implements navigation bar based on Vue Router



foreword

In the previous article, we explained the basic use of the Vue Router routing management tool. However, if students have no project experience and can understand the official documents immediately, it is difficult to really apply what they have learned to the project, resulting in easy understanding at a glance, and instant use. An embarrassing situation.

How to actually apply Vue Router to the project is our top priority.

In fact, before writing this article, I was very hesitant, because many things, the principle is very simple, the application is a little troublesome, and the writing is even more troublesome. The most important thing is that I don’t know if it will be helpful after I finish writing. I am throwing bricks here to attract jade, if there is something inappropriate, welcome to correct me.


insert image description here

1. Nested routing

This article has an unavoidable basic concept - nested routing of Vue Router.

Please go to the official website to read the detailed concepts carefully. Here is just an overview to help students who have read the official website recall their memories.

We have defined routing data in the routing definition file router.js:

const routes = [{
    
     path: '/user/:id', component: User }]

We defined the routing entry in the page entry file APP.vue:

<router-view></router-view>

When we introduce the router plug-in in main.js, it will automatically get the routing information defined in routes, and then render the corresponding components into router-view according to the events we defined.

The meaning here is to render the User component to the position of router-view.

If there is still a router-view tag in the User component, which is route nesting, the corresponding children content defined in routes will be rendered at the router-view position in User. like:

const routes = [
  {
    
    
    path: '/user/:id',
    component: User,
    children: [
      {
    
    
        // 当 /user/:id/profile 匹配成功
        // UserProfile 将被渲染到 User 的 <router-view> 内部
        path: 'profile',
        component: UserProfile,
      },
      {
    
    
        // 当 /user/:id/posts 匹配成功
        // UserPosts 将被渲染到 User 的 <router-view> 内部
        path: 'posts',
        component: UserPosts,
      },
    ],
  },
]

If the content of the User component is as follows:

const User = {
    
    
  template: `
    <div class="user">
      <h2>User {
    
    {
    
     $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
}

Then the UserProfile and UserPosts will be rendered in the router-view in the User component.

The above is the general content of routing nesting. User can be regarded as a parent component, and UserProfile and UserPosts are child components.

2. Use steps

1. Sort out the file relationship

If you have doubts about the use of the router plug-in, please read my previous article. It is assumed that you are already familiar with the basic use of router.

Let's sort out the main components involved in routing:

  1. APP.vue (basically every vue project has it)
  2. layout.vue (my custom layout component, also called main.vue, home.vue, etc. in some frameworks)
  3. SideMenu.vue (my custom navigation component, included in layout.vue)
  4. Components of each business

The previous section mentioned that there is a routing entry in App.vue

<router-view></router-view>

The data in router.js will be rendered here. After the router.js code is simplified, only a few pieces of data are left:

import Login from 'module-base/views/Login/Login.vue'
import Layout from 'module-base/views/Layout/Layout.vue'
export const routes = [
    {
    
    
        path: '/login',
        name: 'login',
        component: Login, //默认直接加载
        meta: {
    
    
            hideInMenu: true
        }
    },
    {
    
    
        path: '/home',
        name: 'home',
        component: Layout,
        children: [
            {
    
    
                path: '/home_page',
                name: 'home_page',
                meta: {
    
    
                    title: '首页',
                    icon: 'ios-list-box'

                },
                component: () => import('module-base/views/Home.vue')
            }
        ]
    },
    {
    
    
        path: '/mailSend',
        name: 'mailSend',
        component: Layout,
        meta: {
    
    
            showAlways: true,
            title: '表单',
            icon: 'ios-list-box',
            // hideInMenu: true

        },
        children: [
            {
    
    
                path: '/mailSend_page',
                name: 'mailSend_page',
                meta: {
    
    
                    title: '表单示例',
                    icon: 'ios-list-box'

                },
                component: () => import('@/views/MailSend/MailSend.vue')
            }
        ]
    }
]

There are two components in router.js, Login and Layout, which are loaded first and then defined in the component attribute, while other components are loaded through the following code:

() => import('@/views/MailSend/MailSend.vue')

This is a way to dynamically load components, which can be loaded on demand and optimize speed.

We can find that, except for the "path: '/login'" part, login is loaded directly, and a property is defined in the latter part:

component: Layout

This shows that each of our business pages is actually nested in the Layout component. Layout is the parent component of all our pages, and other business pages are child components, such as Home.vue and MailSend.vue defined in children.

2. Understand the layout component Layout.vue

We extract the main html code in Layout.vue:

 <div class="layout">
    <Layout style="height: 100%">
      <Sider ref="side1" style="min-width: 100px" hide-trigger collapsible :collapsed-width="78" v-model="isCollapsed">
        <SideMenu ref="sideMenu" :menu-list="menuList" @on-select="turnToPage_sideMenu"></SideMenu>
        <svg class="icon icon-menu" @click="collapsedSider" aria-hidden="true">
          <use xlink:href="#icon-pendant-full"></use>
        </svg>
      </Sider>

      <Layout>
        <Content :style="{overflowY:'auto',overflowX:'auto', background: '#fff', minHeight: '260px'}">
          <!--router-view嵌套,这里渲染Layout路由的children路由          -->
          <router-view v-slot="{Component}">
            <KeepAlive :max="10">
              <component :is="Component"></component>
            </KeepAlive>
          </router-view>
        </Content>
      </Layout>
    </Layout>
  </div>

This code is very simple, mainly divided into two parts, one is Sider, which is the navigation bar on the left, and the other is Layout (the layout label provided by the iview framework), which is the area for rendering component content on the right side. In the Layout label, there is router- The view tag, here and the router-view in App.vue form a routing nest. So the subcomponents Home.vue, MailSend.vue, etc. will be rendered here.

There is nothing to say about the Layout tag part, which is the basic application of the router plug-in.

The svg in the Sider tag is the Ali iconfont of the application, if you don’t understand it, you can ignore it. The core of this part is actually the SideMenu component .

3. Understand the navigation component SideMenu

The SideMenu component is relatively more complicated than Layout.vue, because the judgment of some custom information in router.js is here, the code is as follows:

 <Menu theme="dark" width="auto" :class="menuitemClasses">
    <template v-for="item in menuList">
      <template v-if="item.children && item.children.length === 1">
        <!--          只有一个children元素的情况-->
        <SideMenuItem v-if="showChildren(item)" :key="`menu-${item.name}`" :parent-item="item"></SideMenuItem>
        <MenuItem v-else :name="getNameOrHref(item,true)" :key="`menu-${item.children[0].name}`">
          <svg v-if="item.children[0].meta.iconfont" class="icon" aria-hidden="true">
            <use xlink:href="#icon-weixin"></use>
          </svg>
          <Icon v-else :type="item.children[0].meta.icon"></Icon>
          <span v-if="!isCollapsed" :class="{active:!isCollapsed}">{
    
    {
    
     showTitle(item.children[0]) }}</span>
        </MenuItem>
      </template>
      <template v-else>
        <!--          没有children或者有多个children的情况-->
        <SideMenuItem v-if="showChildren(item)" :key="`menu-${item.name}`" :parent-item="item"></SideMenuItem>
        <MenuItem v-else :name="getNameOrHref(item)" :key="`menu-${item.name}`">
          <svg v-if="item.meta.iconfont" class="icon" aria-hidden="true">
            <use xlink:href="#icon-weixin"></use>
          </svg>
          <Icon v-else :type="item.meta.icon"></Icon>
          <span v-if="!isCollapsed" :class="{active:!isCollapsed}">{
    
    {
    
     showTitle(item) }}</span>
        </MenuItem>
      </template>
    </template>
  </Menu>

Navigation mainly uses the Menu component of the iview framework. When we render navigation, we must render according to an array of data. Where does this data come from? Yes, it is obtained from router.js.

My router data transmission process is roughly as follows:

  1. Define the getters method for obtaining router.js data in pinia, pinia is a global management tool similar to vuex.
  2. Call pinia in Layout.vue to get the data in router.js defined as: menuList
  3. Pass parameters through the parent-child component, and pass the menuList to the sideMenu component.
  4. After sideMenu gets the component, it starts to render it in a loop, which is the above: v-for="item in menuList"

During the rendering process, you can control the rendering effect through some custom configurations of the item. For example, in my navigation bar, there are the following processing:

  1. According to whether there is a children object in the node item, it is judged whether to render the secondary navigation bar.
  2. I have customized a meta attribute, which contains some custom parameters. For example, I will judge the icon in the sideMenu to determine the rendered icon, and judge the rendered title according to the title.

4. Realize the jump

The Layout and SideMenu components have been explained, so how to click the navigation bar to jump?

The answer is that when I wrote SideMenu in the Layout component, I defined a method @on-select="turnToPage_sideMenu". When clicking to select the navigation bar, the calling method is as follows:

function turnToPage_sideMenu(name) {
    
    
  console.log(name)
  turnToPage(router, name)
}

//在另一个工具函数中定义了方法turnToPage
export const turnToPage= ($router,route)=> {
    
    
    let {
    
     name, params, query } = {
    
    }
    if (typeof route === 'string') name = route
    else {
    
    
        name = route.name
        params = route.params
        query = route.query
    }
    if (name.indexOf('isTurnByHref_') > -1) {
    
    
        window.open(name.split('_')[1])
        return
    }
    $router.push({
    
    
        name,
        params,
        query
    })
}

Summarize

This part of the code is a bit too much, and there is no way to paste it all. If you are interested in learning more about it, you can private chat or comment on me to get the source code.

The idea of ​​rendering the navigation bar according to the routing information is actually very simple:

  1. Define the router-view tag in App.vue as the routing entry
  2. In addition to special components such as login, the parent component of each business component defines a Layout layout component, so that every time you jump to a different component, there is a parent component Layout
  3. The Layout layout component does two things: one is the SideMenu navigation component, and the other is to define router-view as a nested sub-route, which is used to render the components defined in children in router.js.
  4. Obtain router information in the global management tool. If you do not consider the follow-up, you can even obtain it directly in the required components without using the global management tool. Render the menulist to the SideMenu navigation component
  5. Define the jump method turnToPage_sideMenu, and jump to the corresponding component when the navigation bar is clicked.

Guess you like

Origin blog.csdn.net/zjsj_lize/article/details/128550496