---
title: "VUE全家桶笔记 (VueX&Vue-router)"
id: "2948"
type: "post"
slug: "vue%e5%85%a8%e5%ae%b6%e6%a1%b6%e7%ac%94%e8%ae%b0-vuexvue-router"
published_at: "2020-04-25T04:34:31+00:00"
modified_at: "2020-04-27T11:06:43+00:00"
url: "https://seq.ink/all/2948.html"
markdown_url: "https://seq.ink/all/2948.html.md"
excerpt: "VUE全家桶笔记 (Vue-router) Vue-router介绍 Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成，让构建单页面应用变得易如反掌。包含的功能有： 嵌套的路由/视图表 模块化的、 ..."
taxonomy_category:
  - "ALL"
  - "Coding代码堆"
taxonomy_post_tag:
  - "Vue"
  - "Vue-router"
---

# VUE全家桶笔记 (Vue-router)

### Vue-router介绍

> Vue Router 是 [Vue.js](http://cn.vuejs.org/)
>  官方的路由管理器。它和 Vue.js 的核心深度集成，让构建单页面应用变得易如反掌。包含的功能有：
> 
>  - 嵌套的路由/视图表
> - 模块化的、基于组件的路由配置
> - 路由参数、查询、通配符
> - 基于 Vue.js 过渡系统的视图过渡效果
> - 细粒度的导航控制
> - 带有自动激活的 CSS class 的链接
> - HTML5 历史模式或 hash 模式，在 IE9 中自动降级
> - 自定义的滚动条行为 引用地址:https://router.vuejs.org/zh/ 说白了就是一个单页应用(SPA)可以通过Vue-router切换到不同的”页面”

### 起步

要想使用Vue-router就得先安装对应的插件然后将组件映射到路由。

> 安装
> 
>  1.在生成项目时选择 Manually select features -> Router
> 
>  2.在已有的项目中使用 `npm i vue-router -S` 或者 `vue add router`
> 
>  **！但是注意 命令安装会造成文件覆盖,安装前一定要提交下项目**
> 
>  在main.js中 引入并且使用 `Vue.use()`进行注册
> 
>  ```
> import VueRouter from 'vue-router'
> 
> Vue.use(VueRouter);
> ```

### 基本使用

> src -> router -> index.js
> 
>  ```
> import Vue from "vue";
> import VueRouter from "vue-router";  //引入vue-router
> import Home from "../views/Home.vue"; //引入组件
> import About from "../views/About.vue";
> Vue.use(VueRouter); //注册
> 
> const routes = [
>     {
>         path: "/",  //路由地址
>         component: Home //跳转的目标组件
>     },
>     {
>         path: "/about",
>         component: About,
>     },
> ];
> 
> const router = new VueRouter({
>   mode: "history",
>   base: process.env.BASE_URL,
>     routes
> });
> 
> export default router; //抛出router
> ```
> 
>  配置完成后可以使用`<router-link to="Home">Home</router-link>` 创建跳转的链接 to属性相当于a标签的href属性
> 
>  `<router-view />`标签作为路由出口渲染组件

### 命名路由

> 在配置路由时可以给路由一个name属性进行动态切换
> 
>  src -> router -> index.js
> 
>  ```
> const routes = [
>     {
>         path: "/",
>         name: "Home",
>         component: Home
>     },
>     {
>         path: "/about",
>         name: "About",
>         component: About,
>     },
> ];
> ```
> 
>  绑定to属性 {name:’路由中对应的home属性值’}
> 
>  `<router-link :to="{name:'Home'}">Home</router-link>`
> 
>  `<router-link :to="{name:'About'}">About</router-link>`
> 
>  这里还要注意下单引号和双引号嵌套问题

### 动态路由匹配&路由组件复用

> 在网站中 经常有动态路由的情况 例如 `https://space.bilibili.com/16052014` 这里的16052014就是一个动态路由，每一个不同的动态路由都会渲染相同组件不同的用户信息。
> 
>  src -> router -> index.js
> 
>  ```
> import Vue from "vue";
> import VueRouter from "vue-router";
> import User from "../views/User"; //新创建的用户组件
> Vue.use(VueRouter);
> 
> const routes = [
>     {
>        /*
>         /:id就是动态路由匹配 例如http://xxxxx/user/1
>         这里的1就是匹配的:id
>       */
>       path: "/user/:id",
>       name: "User",
>       component: User,
>     }
> ];
> 
> const router = new VueRouter({
>     mode: "history",
>     base: process.env.BASE_URL,
>     routes
> });
> 
> export default router; //抛出router
> ```
> 
>  使用params接收匹配路由 因为可能存在多个使用对象进行接收
> 
>  `<router-link :to="{name:'User',params:{id:1}}">用户1</router-link>`
> 
>  `<router-link :to="{name:'User',params:{id:2}}">用户2</router-link>`
> 
>  获取id中的内容与后端进行相对应的数据请求展示不同的数据
> 
>  src -> views -> User.vue
> 
>  “`javascript

我是用户页面{{ $route.params.id }}

> ````
> $route是一个对象然后取到params字段然后再取到对应的key
> 
> **！注意  当路由参数发生变化时 /user/1 切换到  /user/2时 原来的组件实例会被复用，因为两个路由渲染的是同一个组件，复用高效。**
> 
> **但是带来的问题是因为组件是被复用的而不是重新进行渲染这里如果使用生命周期钩子函数会造成一些问题**
> 
> 出现上述问题可以使用watch监听$route:(to,from) to是到哪里去 from是从哪里来 然后就可以愉快的进行一些操作了 例如ajax请求然后改变视图 （to.params.id）
> 
> 还有一种方法就是利用导航守卫 beforeRouteUpdate
> 
> ```javascript
> beforeRouteUpdate(to,from,next){
>   console.Log(to.params.id);
>     //拿到对应去哪里的id就可以在这里发ajax请求了
> 
>     next(); //注意这里一定要调用下next 否则路由会被阻塞
> }
> </code></pre>
> </blockquote>
> 
> <h3>404路由和匹配优先级</h3>
> 
> <blockquote>
>   有这样一个场景用户输入了网站未定义的路由地址 默认Vue-router会跳转到首页，显然这样是不科学的，我们可以定义一个404路由提示用户你输入的地址不存在。
> 
>   src -> router -> index.js
> 
> <pre><code class="language-javascript line-numbers">import Vue from "vue";
> import VueRouter from "vue-router";
> import Home from "../views/Home.vue";
> import About from "../views/About.vue";
> import User from "../views/User";
> Vue.use(VueRouter);
> 
> const routes = [
>       {
>         path: "/",
>         name: "Home",
>         component: Home
>       },
>       {
>         path: "/about",
>         name: "About",
>         component: About
>       },
>       {
>         path: "/user/:id",
>         name: "User",
>         component: User
>       },
>       {
>         path: "*",  // *代表通配 也就是上面的路由没有找到会匹配到这里 自然这里就引申出一个优先级的问题
>         name: "404",
>         component: () => import("../views/404") // 异步组件加载方式 效率更高
>       }
> ];
> 
> const router = new VueRouter({
>     mode: "history",
>     base: process.env.BASE_URL,
>     routes
> });
> 
> export default router;
> 
> </code></pre>
> 
>   <strong>！注意404路由一定要放到路由配置最下方，因为这里存在一个匹配优先级的问题 他会从上往下找 如果404路由放到首位或者中间某一个位置就会造成下方的路由失效</strong>
> 
>   src -> views -> User.vue
> 
> 
>   ```javascript
> 
> ````

> ### 404

 >

> ````
> *（通配符）在Vue-router中还有一些其他的作用例如在一个后台管理系统
> 
> src -> router -> index.js
> 
> ```javascript
> import Vue from "vue";
> import VueRouter from "vue-router";
> 
> import User from "../views/User";
> import UserAdmin from "../views/UserAdmin";
> Vue.use(VueRouter);
> 
> const routes = [
>       {
>         path: "/user/:id",
>         name: "User",
>         component: User
>       },
>       {
>         path: "/user-*",
>         name: "UserAdmin",
>         component: UserAdmin
>       },
> ];
> 
> const router = new VueRouter({
>     mode: "history",
>     base: process.env.BASE_URL,
>     routes
> });
> 
> export default router;
> </code></pre>
> 
>   如果说是一个这样的路由<code>http://localhost:8080/user/1</code>就是之前定义的用户动态路由如果说是一个这样的路由<code>http://localhost:8080/user-admin</code>他就会切换到一个admin路由下，可以使用<code>$route.params.pathMatch</code>获取到/user-*通配的内容
> 
>   src -> views -> UserAdmin.vue
> 
> 
>   ```javascript
> 
> ````

> #### Admin页面

 > ### {{ $route.params.pathMatch }}

 >

> ```

### 路由参数查询

> 有这样一种路由是长成这种样子`http://localhost:8080/page?id=1&title=foo` 这种形式的路由这个例子有两个参数 src -> router -> index.js ```
> import Vue from "vue";
> import VueRouter from "vue-router";
> import Page from "../views/Page";
> Vue.use(VueRouter);
> 
> const routes = [
>   {
>     path: "/page",
>     name: "Page",
>     component: Page
>   },
> ];
> 
> const router = new VueRouter({
>     mode: "history",
>     base: process.env.BASE_URL,
>     routes
> });
> 
> export default router;
> ```
> 
>  src -> App.vue
> 
>  ```html

> > Page |  
 >

>   
 >

> ```
> 
>  query为参数查询 当然这里的数据是写死的 因为我们使用的是命名路由未来可以替换成动态数据，然后可以在组件中拿到对应的参数进行一些操作。
> 
>  ```javascript

> ### Page页面

>

> ```

### 路由重定向&别名

> src -> router -> index.js
> 
>  ```
> const routes = [
> {
>  path: "/",
>  redirect:{name:'Home'} // 默认的 / 就会跳转到Home路由
> },
> {
>  path: "/home",
>  name: "Home",
>  component: Home
> },
> ];
> ```
> 
>  别名就不多说了 `alias: '/aaa'`一个属性 一个别名

### 路由组件传值

> 在之前我们是使用`$route`获取地址栏上的值进行传值，但是随着项目的复杂度增加地址栏上的参数会越来越多`$route`获取值的方式会显得复杂，也会跟路由形成高度的耦合，当前组件只能在特定的URL使用，限制了组件灵活。
> 
>  解决这个问题可以在定义路由的时候使用`porps`属性
> 
>  src -> router -> index.js
> 
>  ```
> {
>   path: "/user/:id",
>   name: "User",
>   component: User,
>   props:true //使用props传值
> },
> ```
> 
>  src -> views -> User.vue
> 
>  ```javascript

我是用户页面{{ id }}

> ````
> 在路由中定义props还有其他的用法例如定义一个函数
> 
> src -> router -> index.js
> 
> ```javascript
> {
>   path: "/user/:id",
>   name: "User",
>   component: User,
>   props: route => ({
>     id: route.params.id,
>     title: route.query.title
>   })
> },
> </code></pre>
> 
>   src -> views -> User.vue
> 
> 
>   ```javascript
> 
> ````

我是用户页面{{ id }}-{{ title }}

> ``` 之后访问`http://localhost:8080/user/1?title=lalalala`就可以拿到对应的title参数值了

### 编程式导航

> 我们可以通过`this.$route`获取路由组件实例对象里面有一些方法例如`push go back`等方法进行动态的路由跳转，我们称之为编程形导航。 类似于`<router-link :to="{name:'Home'}">Home</router-link>` 叫做声明形导航 例如我在User组件下添加了一个返回首页的按钮我们可以这样做 src -> views -> User.vue ```javascript

> 回到首页 >

> ``` 也可以使用命名的方式例如`this.$router.push("name");`也可以是个对象`this.$router.push({path:'/'});` 也可以是一个命名路由 也可以进行前进或者后退，使用`this.$route.to()`进行控制。参数1就是前进，参数0就是刷新，参数-1就是后退

### 嵌套路由

 src -> router -> index.js > ```
> {
>   path: "/user/:id",
>   name: "User",
>   component: User,
>   props: route => ({
>     id: route.params.id,
>     title: route.query.title
>   }),
>   children: [
>     {
>       path: "posts",
>       component: () => import("../views/Posts")
>     }
>   ]
> },
> ```
> 
>  然后就是在一个位置定义跳转`<router-link to="/user/1/posts">children</router-link>`最后在user中定义路由出口 `<router-view />`。

### 命名视图

> 一般情况下，我们在路由配置中，一个路由路径只能对应一个组件，若想对应多个组件，必须得作为子组件存在，然后再一个公用的视图内显示，这是一个路由对应多个组件，这些组件对应一个视图（就是上面嵌套路由的玩法）
> 
>  有时候想同时 (同级) 展示多个视图，而不是嵌套展示，例如创建一个布局，有 `sidebar` (侧导航) 和 `main` (主内容) 两个视图，这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图，而不是只有一个单独的出口。
> 
>  src -> router -> index.js
> 
>  ```
> const routes = [
>    {
>      path: "/home",
>      name: "Home",
>      component:{
>          default:Home, //默认的名字
>          Sidebar:() => import('../views/Sidebar'),
>          Main:() => import('../views/main'),
>      }
>    },
> 
> ];
> ```
> 
>  src -> views -> Home.vue
> 
>  ```
> <router-view />
> 
>   <router-view name="Sidebar"/>
>   <router-view name="Home"/>
> 
> ```

### 全局守卫

> 可以使用`router.beforEach`注册一个全局前置守卫
> 
>  ```
> beforeRouteUpdate(to, from, next) {
>   next();
> },
> ```
> 
>  有个需求，用户在浏览网站时，会访问很多组件，用户跳转到`/notes`，发现用户没有登录，此时应该让用户登陆后查看，应该让用户跳转到登录页面，登陆完成后看到我的笔记内容，这个时候全局守卫起到了关键作用。
