全面解析vue router 基本使用(动态路由,嵌套路由)


Posted in Javascript onSeptember 02, 2018

路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。Home按钮  => home 内容, about按钮 => about 内容,也可以说是一种映射. 所以在页面上有两个部分,一个是点击部分,一个是点击之后,显示内容的部分。 

点击之后,怎么做到正确的对应,比如,我点击home 按钮,页面中怎么就正好能显示home的内容。这就要在js 文件中配置路由。

  路由中有三个基本的概念 route, routes, router。

1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮  => home内容, 这是一条route,  about按钮 => about 内容, 这是另一条路由。

2, routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]

3, router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。

4,客户端中的路由,实际上就是dom 元素的显示和隐藏。当页面中显示home 内容的时候,about 中的内容全部隐藏,反之也是一样。客户端路由有两种实现方式:基于hash 和基于html5 history api.

vue-router中的路由也是基于上面的内容来实现的

在vue中实现路由还是相对简单的。因为我们页面中所有内容都是组件化的,我们只要把路径和组件对应起来就可以了,然后在页面中把组件渲染出来。

1, 页面实现(html模版中)

在vue-router中, 我们看到它定义了两个标签<router-link> 和<router-view>来对应点击和显示部分。<router-link> 就是定义页面中点击的部分,<router-view> 定义显示部分,就是点击后,区配的内容显示在什么地方。所以 <router-link> 还有一个非常重要的属性 to,定义点击之后,要到哪里去, 如:<router-link  to="/home">Home</router-link>

2, js 中配置路由

首先要定义route,  一条路由的实现。它是一个对象,由两个部分组成: path和component.  path 指路径,component 指的是组件。如:{path:'/home', component: home}

我们这里有两条路由,组成一个routes: 

const routes = [
 { path: '/home', component: Home },
 { path: '/about', component: About }
]

最后创建router 对路由进行管理,它是由构造函数 new vueRouter() 创建,接受routes 参数。

const router = new VueRouter({
  routes // routes: routes 的简写
})

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

const app = new Vue({
 router
}).$mount('#app')

执行过程:当用户点击 router-link 标签时,会去寻找它的 to 属性, 它的 to 属性和 js 中配置的路径{ path: '/home', component: Home}  path 一一对应,从而找到了匹配的组件, 最后把组件渲染到 <router-view> 标签所在的地方。所有的这些实现才是基于hash 实现的。

 vue-cli 创建一个项目体验一下, 当然不要忘记安装vue-router

1, 在src 目录下新建两个组件,home.vue 和 about.vue

<template>
 <div>
  <h1>home</h1>
  <p>{{msg}}</p>
 </div>
</template>
<script>
 export default {
  data () {
   return {
    msg: "我是home 组件"
   }
  }
 }
</script>
<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, 把路由注入到根实例中,启动路由。这里其实还有一种方法,就像vuex  store 注入到根实例中一样,我们也可以把vueRouter 直接注入到根实例中。在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>

动态路由

上面我们定义的路由,都是严格匹配的,只有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>
嵌套路由

嵌套路由,主要是由我们的页面结构所决定的。当我们进入到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
 }
]
命名路由

命名路由,很简单,因为根据名字就可以知道,这个路由有一个名字,那就直接给这个路由加一个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前面要加一个冒号,表示绑定

编程式导航:这主要应用到按钮点击上。当点击按钮的时候,跳转另一个组件, 这只能用代码,调用rourter.push() 方法。 当们把router 注入到根实例中后,组件中通过 this.$router 可以获取到router, 所以在组件中使用

this.$router.push("home"), 就可以跳转到home界面
总结
以上所述是小编给大家介绍的vue router 基本使用,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!
Javascript 相关文章推荐
javascript里的条件判断
Feb 27 Javascript
javascript基础第一章 JavaScript与用户端
Jul 22 Javascript
JavaScript事件代理和委托详解
Apr 08 Javascript
JavaScript中的Number数字类型学习笔记
May 26 Javascript
jquery中live()方法和bind()方法区别分析
Jun 23 Javascript
项目实践一图片上传之form表单还是base64前端图片压缩(前端图片压缩)
Jul 28 Javascript
纯js实现手风琴效果代码
Apr 17 Javascript
jquery获取easyui日期控件的值实现方法
Nov 09 Javascript
JavaScript中利用Array filter() 方法压缩稀疏数组
Feb 24 Javascript
JS简单数组排序操作示例【sort方法】
May 17 Javascript
vue实现分页的三种效果
Jun 23 Javascript
vue 重塑数组之修改数组指定index的值操作
Aug 09 Javascript
解决Vue 项目打包后favicon无法正常显示的问题
Sep 01 #Javascript
修改vue+webpack run build的路径方法
Sep 01 #Javascript
解决vue项目使用font-awesome,build后路径的问题
Sep 01 #Javascript
解决vue-cli项目webpack打包后iconfont文件路径的问题
Sep 01 #Javascript
解决vue 项目引入字体图标报错、不显示等问题
Sep 01 #Javascript
解决在vue项目中webpack打包后字体不生效的问题
Sep 01 #Javascript
vuejs 制作背景淡入淡出切换动画的实例
Sep 01 #Javascript
You might like
php FPDF类库应用实现代码
2009/03/20 PHP
php传值赋值和传地址赋值用法实例分析
2015/06/20 PHP
php删除txt文件指定行及按行读取txt文档数据的方法
2017/01/30 PHP
Centos7 Yum安装PHP7.2流程教程详解
2019/07/02 PHP
JavaScript 设计模式 富有表现力的Javascript(一)
2010/05/26 Javascript
js 连接数据库如何操作数据库中的数据
2012/11/23 Javascript
jquery prop的使用介绍及与attr的区别
2013/12/19 Javascript
Javascript模块化编程详解
2014/12/01 Javascript
javascript下拉框选项单击事件的例子分享
2015/03/04 Javascript
JS实现模拟风力的雪花飘落效果
2015/05/13 Javascript
javascript判断并获取注册表中可信任站点的方法
2015/06/01 Javascript
js 判断所选时间(或者当前时间)是否在某一时间段的实现代码
2015/09/05 Javascript
封装获取dom元素的简单实例
2016/07/08 Javascript
jQuery学习之DOM节点的插入方法总结
2017/01/22 Javascript
jQuery实现 RadioButton做必选校验功能
2017/06/15 jQuery
详解关于vue-area-linkage走过的坑
2018/06/27 Javascript
解决JS表单验证只有第一个IF起作用的问题
2018/12/04 Javascript
vue中的mvvm模式讲解
2019/01/31 Javascript
创建nuxt.js项目流程图解
2020/03/13 Javascript
[02:45]DOTA2英雄敌法师基础教程
2013/11/25 DOTA
[44:26]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第二局
2016/03/03 DOTA
python3中set(集合)的语法总结分享
2017/03/24 Python
Python进阶-函数默认参数(详解)
2017/05/18 Python
Python设计模式之简单工厂模式实例详解
2019/01/22 Python
PyQt5 多窗口连接实例
2019/06/19 Python
Python字符串、列表、元组、字典、集合的补充实例详解
2019/12/20 Python
pycharm激活码2020最新分享适用pycharm2020最新版亲测可用
2020/11/22 Python
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
日本亚马逊官方网站:Amazon.co.jp
2020/04/14 全球购物
2014年公务员思想汇报范文:全心全意为人民服务
2014/03/06 职场文书
2014乡镇干部对照检查材料思想汇报
2014/09/26 职场文书
创业计划书介绍
2019/04/24 职场文书
关于感恩的作文
2019/08/26 职场文书
《语言的突破》读后感3篇
2019/12/12 职场文书
Python实现拼音转换
2021/06/07 Python
Java基础-封装和继承
2021/07/02 Java/Android