vue-router 的基本使用


路由:指向的意思,也可以說是一種映射(一對一)。

例如:點擊+頁面上的home按鈕,頁面中展示home的內容。點擊detail按鈕,頁面中展示detail內容。

如何正確的對應顯示,這就要在js文件中配置路由,路由中有三個基本概念route,routes,router.

1.route,是一條路由 ,一個局部對象。

2.routes,是一組路由,多個局部對象。

3.router,是一個機制,相當於管理者--->管理路由,全局的對象。因為routes定義了一組路由,當有交互事件發生時,router就會到routes中去查找對應的路由。

4.客戶端的路由,實際上就是dom元素的顯示和隱藏,當頁面中顯示home內容的時候,detail中的內容就全部隱藏,反之也是一樣。

客戶端路由有兩種實現方式:基於hash和基於html5 history api

在vue中使用vue-router

在vue中頁面中所有內容都是組件化的,我們只要把路徑和組件對應起來,然后在頁面中把組件渲染出來

html模板中

在vue-router中,定義了兩個標簽<router-link>和<router-view>來對應點擊和顯示部分。<router-link>定義頁面中的點擊部分,<router-view>定義顯示部分,就是點擊后匹配的內容顯示在什么地方。

<router-link>有一個非常重要的屬性to,定義點擊之后要到哪里去。<router-link to='/home'>Home</router-link>

js中配置路由

1.一條路由,是一個對象,由兩部分組成:path和component,path指路徑,component指的是組件 。例如:{path:'/home',component: home}

2.多條路由組成一個routes

const routes = {
  {path:'/home',component: home}
  {path:'/detail',component: detail}
}

3.通過構造函數new vueRouter()創建router對路由進行管理,接受routes參數

const router = new VueRouter({
    routes       ( routes: routes 的簡寫)
})

配置完成之后,把route實例注入到vue根實例中,就可以使用路由了

 執行過程:當用戶點擊 router-link 標簽時,會去尋找它的 to 屬性, 它的 to 屬性和 js 中配置的路徑{ path: '/home', component: Home}  path 一 一對應,從而找到了匹配的組件, 最后把組件渲染到 <router-view> 標簽所在的地方。所有的這些實現才是基於hash 實現的。

vue-cli 創建一個項目體驗一下, 當然不要忘記安裝vue-router

1.在src 目錄下新建兩個組件,home.vue 和 about.vue

//home.vue
<template> <div> <h1>home</h1> <p>{{msg}}</p> </div> </template> <script> export default { data () { return { msg: "我是home 組件" } } } </script>

 

   // about.vue

<template>
    <div>
        <h1>about</h1>
        <p>{{aboutMsg}}</p>
    </div>
</template>
<script>
    export default {
        data () {
            return {
                aboutMsg: '我是about組件'
            }
        }
    }
</script>

2. 在 App.vue中 定義<router-link > 和 </router-view>  

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <header>
    <!-- router-link 定義點擊后導航到哪個路徑下 -->
      <router-link to="/home">Home</router-link>
      <router-link to="/about">About</router-link>
    </header>
    <!-- 對應的組件內容渲染到router-view中 -->
    <router-view></router-view>   
  </div>
</template>

<script>
export default {
  
}
</script>

3.在 src目錄下再新建一個router.js 定義router, 就是定義 路徑到 組件的 映射。

import Vue from "vue";
import VueRouter from "vue-router";

// 引入組件
import home from "./home.vue";
import about from "./about.vue";

// 要告訴 vue 使用 vueRouter
Vue.use(VueRouter);

const routes = [
    {
        path:"/home",
        component: home
    },
    {
        path: "/about",
        component: about
    }
]

var router =  new VueRouter({
    routes
})
export default router;

 

4.把路由注入到根實例中,啟動路由。在main.js中引入路由,注入到根實例中。

import Vue from 'vue'
import App from './App.vue'

// 引入路由
import router from "./router.js"    // import router 的router 一定要小寫, 不要寫成Router, 否則報 can't match的報錯
new Vue({
  el: '#app',
  router,  // 注入到根實例中
  render: h => h(App)
})

5. 這時點擊頁面上的home 和about 可以看到組件來回切換。但是有一個問題,當首次進入頁面的時候,頁面中並沒有顯示任何內容。

這是因為首次進入頁面時,它的路徑是 '/',我們並沒有給這個路徑做相應的配置。一般,頁面一加載進來都會顯示home頁面,我們也要把這個路徑指向home組件。

但是如果我們寫{ path: '/', component: Home },vue 會報錯,因為兩條路徑卻指向同一個方向。這怎么辦?

這需要重定向,所謂重定向,就是重新給它指定一個方向,它本來是訪問 / 路徑,我們重新指向‘/home’, 它就相當於訪問 '/home', 相應地, home組件就會顯示到頁面上。vueRouter中用 redirect 來定義重定向。

const routes = [
    {
        path:"/home",
        component: home
    },
    {
        path: "/about",
        component: about
    },
    // 重定向
    {
        path: '/', 
        redirect: '/home' 
    }
]

現在頁面正常了,首次進入顯示home, 並且點擊也可以看到內容的切換。

6.最后,我們看一下路由是怎么實現的

打開瀏覽器控制台,首先看到 router-link 標簽渲染成了 a 標簽,to 屬性變成了a 標簽的 href 屬性,這時就明白了點擊跳轉的意思。

router-view 標簽渲染成了我們定義的組件,其實它就是一個占位符,它在什么地方,匹配路徑的組件就在什么地方,所以 router-link 和router-view 標簽一 一對應,成對出現。

這里還看到,當點擊Home和About 來回切換時,a 標簽有一個樣式類 .router-link-active 也在來回切換, 原來這是當router-link 處於選中狀態時,vueRouter 會自動添加這個類,因此我們也可以利用這個類來改變選中時的狀態,如選中時,讓它變成紅色。

但當設置 .router-link-active {color: red;},它並沒有生效,這時還要在類前面加一個a, a.router-link-active {color: red;}, 這樣就沒有問題了。

未處於選中狀態的router-link, 我們也想給它更改樣式,怎么辦? 直接給它添加一個 class 就可以了, <router-link class="red">Home</router-link>

7.動態路由

上面我們定義的路由,都是嚴格匹配的,只有router-link 中的to屬性和 js 中一條路由route中 path 一模一樣,才能顯示相應的組件component. 但有時現實卻不是這樣的,當我們去訪問網站並登錄成功后,它會顯示 歡迎你,+ 你的名字。不同的用戶登錄,

只是顯示“你的名字” 部分不同,其它部分是一樣的。這就表示,它是一個組件,假設是user組件。不同的用戶(就是用戶的id不同),它都會導航到同一個user  組件中。

這樣我們在配置路由的時候,就不能寫死, 就是路由中的path屬性,不能寫死,那要怎么設置? 導航到 user 組件,路徑中肯定有user, id 不同,那就給路徑一個動態部分來匹配不同的id.  在vue-router中,動態部分 以 : 開頭,那么路徑就變成了 /user/:id, 這條路由就可以這么寫:  { path:"/user/:id", component: user }.

我們定義一個user組件(自己隨便寫一個就好了),頁面中再添加兩個router-link 用於導航, 最后router.js中添加路由配置,來體驗一下

app.vue 中添加兩個router-link:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <header>
      <router-link to="/home">Home</router-link>
      <router-link to="/about">About</router-link>
     <!--  增加兩個到user組件的導航,可以看到這里使用了不同的to屬性 -->
      <router-link to="/user/123">User123</router-link>
      <router-link to="/user/456">User456</router-link>
    </header>
    <router-view></router-view>   
  </div>
</template>

router.js 配置user動態路由:

const routes = [
    {
        path:"/home",
        component: home
    },
    {
        path: "/about",
        component: about
    },
    /*新增user路徑,配置了動態的id*/
    {
        path: "/user/:id",
        component: user
    },
    {
        path: '/', 
        redirect: '/home' 
    }
]

user組件

<template>
    <div>
        <h1>User</h1>
        <div>我是user組件</div>
    </div>
</template>
<script>
    export default {

    }
</script>

 

這時在頁面中點擊user123 和user456, 可以看到它們都導航到user組件,配置正確。   

在動態路由中,怎么獲取到動態部分? 因為在組件中是可以顯示不同部分的,就是上面提到的“你的名字”。其實,當整個vue-router 注入到根實例后,在組件的內部,可以通過this.$route 來獲取到 router 實例

它有一個params 屬性,就是來獲得這個動態部分的。它是一個對象,屬性名,就是路徑中定義的動態部分 id, 屬性值就是router-link中to 屬性中的動態部分,如123。

使用vuex時,組件中想要獲取到state 中的狀態,是用computed 屬性,在這里也是一樣,在組件中,定義一個computed 屬性dynamicSegment, user 組件修改如下:

<template>
    <div>
        <h1>User</h1>
        <div>我是user組件, 動態部分是{{dynamicSegment}}</div>
    </div>
</template>
<script>
    export default {
        computed: {
            dynamicSegment () {
                return this.$route.params.id
            }
        }
    }
</script>

這里還有最后一個問題,就是動態路由在來回切換時,由於它們都是指向同一組件,vue不會銷毀再創建這個組件,而是復用這個組件,就是當第一次點擊(如:user123)的時候,vue 把對應的組件渲染出來,但在user123, user456點擊來回切換的時候,這個組件就不會發生變化了,組件的生命周期不管用了。

這時如果想要在組件來回切換的時候做點事情,那么只能在組件內部(user.vue中)利用watch 來監聽$route 的變化。把上面的代碼用監聽$route 實現

<script>
    export default {
        data () {
            return {
                dynamicSegment: ''
            }
        },
        watch: {
            $route (to,from){
                // to表示的是你要去的那個組件,from 表示的是你從哪個組件過來的,它們是兩個對象,你可以把它打印出來,它們也有一個param 屬性
                console.log(to);
                console.log(from);
                this.dynamicSegment = to.params.id
            }
        }
    }
</script>

8.嵌套路由

嵌套路由,主要是由我們的頁面結構所決定的。當我們進入到home頁面的時候,它下面還有分類,如手機系列,平板系列,電腦系列。當我們點擊各個分類的時候,它還是需要路由到各個部分,如點擊手機,它肯定到對應到手機的部分。

在路由的設計上,首先進入到 home ,然后才能進入到phone, tablet, computer.  Phone, tablet, compute 就相當於進入到了home的子元素。所以vue  提供了childrens 屬性,它也是一組路由,相當於我們所寫的routes。

首先,在home頁面上定義三個router-link 標簽用於導航,然后再定義一個router-view標簽,用於渲染對應的組件。router-link 和router-view 標簽要一一對應。

home.vue 組件修改如下:

<template>
    <div>
        <h1>home</h1>
<!-- router-link 的to屬性要注意,路由是先進入到home,然后才進入相應的子路由如 phone,所以書寫時要把 home 帶上 -->
        <p>
            <router-link to="/home/phone">手機</router-link>
            <router-link to="/home/tablet">平板</router-link>
            <router-link to="/home/computer">電腦</router-link>
        </p>
        <router-view></router-view>
    </div>
</template>

router.js 配置路由,修改如下:

const routes = [
    {
        path:"/home",
     // 下面這個屬性也不少,因為,我們是先進入home頁面,才能進入子路由
        component: home,
     // 子路由
        children: [
            {
                path: "phone",
                component: phone
            },
            {
                path: "tablet",
                component: tablet
            },
            {
                path: "computer",
                component: computer
            }
        ]
    },
    {
        path: "/about",
        component: about
    },
    {
        path: "/user/:id",
        component: user
    },
    {
        path: '/', 
        redirect: '/home' 
    }
]

這時當我們點擊home 時,它下面出現手機等字樣,但沒有任何對應的組件進行顯示,這通常不是我們想要的。要想點擊home時,要想渲染相對應的子組件,那還需要配置一條路由。當進入到home 時,它在children中對應的路由path 是空 ‘’,完整的childrens 如下:

children: [
    {
        path: "phone",
        component: phone
    },
    {
        path: "tablet",
        component: tablet
    },
    {
        path: "computer",
        component: computer
    },
    // 當進入到home時,下面的組件顯示
    {
        path: "",
        component: phone
    }
]

9.命名路由

命名路由,很簡單,因為根據名字就可以知道,這個路由有一個名字,那就直接給這個路由加一個name 屬性,就可以了。 給user 路由加一個name 屬性:

{
    path: "/user/:id",
    name: "user",
    component: user
}

命名路由的使用, 在router-link 中to 屬性就可以使用對象了, 

 <router-link to="/user/123">User123</router-link> // 和下面等價 
 <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>   // 當使用對象作為路由的時候,to前面要加一個冒號,表示綁定

10.編程式導航

這主要應用到按鈕點擊上。當點擊按鈕的時候,跳轉另一個組件, 這只能用代碼,調用rourter.push() 方法。 當們把router 注入到根實例中后,組件中通過 this.$router 可以獲取到router, 所以在組件中使用

this.$router.push("home"), 就可以跳轉到home界面

 看一下項目中的實際應用:

項目中的菜單結構如下:有一級菜單,二級菜單,三級菜單,看下這個三級菜單的實現

import Vue from 'vue';
import Router from 'vue-router';
/* Layout */
import Layout from '@/layout/index.vue';

Vue.use(Router);

export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true,
  },
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true,
  },
  {
    path: '/',
    redirect: '/dataOperations/productInformation/productTree',
  },
  {
    path: '/dataOperations',
    component: Layout,
    alwaysShow: true,
    redirect: '/dataOperations/productInformation/productTree',
    name: 'DataOperations',
    meta: { title: '數據運維', icon: 'table' },
    children: [
      {
        path: 'productInformation',
        component: () => import('@/views/productInformation/index'),
        meta: { title: '產品信息', icon: 'tree' },
        alwaysShow: true,
        name: 'ProductInformation',
        redirect: '/dataOperations/productInformation/productTree',
        children: [
          {
            path: 'productTree',
            name: 'ProductTree',
            component: () => import('@/views/productInformation/productTree'),
            meta: { title: '產品樹查詢' },
          },
          {
            path: 'spu',
            name: 'Spu',
            component: () => import('@/views/productInformation/spu'),
            meta: { title: 'SPU' },
          },
          {
            path: 'statisticsSku',
            name: 'StatisticsSku',
            component: () => import('@/views/productInformation/statisticsSku'),
            meta: { title: 'statisticsSku' },
          },
          {
            path: 'salesSku',
            name: 'SalesSku',
            component: () => import('@/views/productInformation/salesSku'),
            meta: { title: 'salesSku' },
          },
          {
            path: 'sku',
            name: 'Sku',
            component: () => import('@/views/productInformation/sku'),
            meta: { title: 'SKU' },
          },
          {
            path: 'bom',
            name: 'Bom',
            component: () => import('@/views/productInformation/bom'),
            meta: { title: 'BOM' },
          },
        ],
      },
      {
        path: 'exception',
        component: () => import('@/views/productInformation/exception/template'),
        meta: { title: '異常數據', icon: 'tree' },
        alwaysShow: true,
        name: 'Exception',
        hidden: localStorage.role === '1',
        redirect: '/dataOperations/productInformation/exception/index',
        children: [
          {
            path: 'index',
            name: 'ExceptionList',
            component: () => import('@/views/productInformation/exception/index'),
            meta: { title: 'salesSku異常處理' },
          },
          {
            path: 'detail',
            name: 'exceptionDetail',
            component: () => import('@/views/productInformation/exception/detail'),
            meta: { title: 'salesSku異常處理詳情' },
            hidden: true,
          },
        ],
      },
      {
        path: 'backup',
        component: () => import('@/views/productInformation/backup/index'),
        meta: { title: '數據備份' },
        name: 'ProductInformation',
        hidden: localStorage.role === '1',
      },
      {
        path: 'backup/detail',
        component: () => import('@/views/productInformation/backup/detail'),
        meta: { title: '數據備份明細' },
        name: 'ProductInformation',
        hidden: true,
      },
    ],
  },
  {
    path: '/permiss',
    component: Layout,
    meta: {
      title: '權限管理',
      icon: 'example',
    },
    name: 'Permiss',
    redirect: '/permiss/appId',
    hidden: localStorage.role === '1',
    children: [
      {
        path: 'appId',
        name: 'AppId',
        component: () => import('@/views/appId/index'),
        meta: { title: 'appId管理' },
      },
      {
        path: 'interface',
        name: 'Interface',
        component: () => import('@/views/interface/index'),
        meta: { title: '接口管理' },
      },
      {
        path: 'user',
        name: 'User',
        component: () => import('@/views/user/index'),
        meta: { title: '用戶管理' },
      },
    ],
  },
  // 404 page must be placed at the end !!!
  { path: '*', redirect: '/404', hidden: true },
];

const createRouter = () =>
  new Router({
    // mode: 'history', // require service support
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRoutes,
  });

const router = createRouter();

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  setTimeout(() => {
    const newRouter = createRouter();
    router.matcher = newRouter.matcher; // reset router
  }, 200);
}

export default router;

 

 

轉自https://www.cnblogs.com/SamWeb/p/6610733.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM