全面解析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获取GridView中用户点击控件的行号,列号
Apr 14 Javascript
JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型
Oct 11 Javascript
可插入图片的TEXT文本框
Dec 27 Javascript
浅析JS运动
Dec 28 Javascript
原生JS仿QQ阅读点击展开、收起效果
Mar 08 Javascript
jQuery实现选中行变色效果(实例讲解)
Jul 06 jQuery
在 React、Vue项目中使用SVG的方法
Feb 09 Javascript
JavaScript设计模式之职责链模式应用示例
Aug 07 Javascript
解决vue的变量在settimeout内部效果失效的问题
Aug 30 Javascript
小程序实现分类页
Jul 12 Javascript
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
Sep 05 Javascript
vue项目使用$router.go(-1)返回时刷新原来的界面操作
Jul 26 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 cli 方式 在crotab中运行解决
2010/02/08 PHP
php入门之连接mysql数据库的一个类
2012/04/21 PHP
php使用mb_check_encoding检查字符串在指定的编码里是否有效
2013/11/07 PHP
destoon首页调用求购供应信息的地区名称的方法
2014/08/21 PHP
PHP设计模式之模板方法模式定义与用法详解
2018/04/02 PHP
THINKPHP5分页数据对象处理过程解析
2020/10/28 PHP
Javascript实例教程(19) 使用HoTMetal(3)
2006/12/23 Javascript
javascript各种复制代码收集
2008/09/20 Javascript
JQuery UI皮肤定制
2009/07/27 Javascript
使用JS CSS去除IE链接虚线框的三种方法
2013/11/14 Javascript
js通过元素class名字获取元素集合的具体实现
2014/01/06 Javascript
对于Form表单reset方法的新认识
2014/03/05 Javascript
jquery datepicker参数介绍和示例
2014/04/15 Javascript
jQuery通过扩展实现抖动效果的方法
2015/03/11 Javascript
原生js实现移动开发轮播图、相册滑动特效
2015/04/17 Javascript
JS利用cookies设置每隔24小时弹出框
2017/04/20 Javascript
angularJS自定义directive之带参方法传递详解
2018/10/09 Javascript
layui form.render('select', 'test2') 更新渲染的方法
2019/09/27 Javascript
Python中的下划线详解
2015/06/24 Python
ansible作为python模块库使用的方法实例
2017/01/17 Python
Python装饰器实现几类验证功能做法实例
2017/05/18 Python
python爬虫框架scrapy实现模拟登录操作示例
2018/08/02 Python
Python实现的线性回归算法示例【附csv文件下载】
2018/12/29 Python
Python操作qml对象过程详解
2019/09/26 Python
Python对象的属性访问过程详解
2020/03/05 Python
python爬虫开发之使用python爬虫库requests,urllib与今日头条搜索功能爬取搜索内容实例
2020/03/10 Python
关于Python字符编码与二进制不得不说的一些事
2020/10/04 Python
浅谈盘点5种基于Python生成的个性化语音方法
2021/02/05 Python
新学期班主任寄语
2014/01/18 职场文书
公证委托书大全
2014/04/04 职场文书
基层党员对照检查材料
2014/09/24 职场文书
工作失误检讨书(3篇)
2014/10/11 职场文书
党的群众路线教育实践活动个人对照检查材料(校长)
2014/11/05 职场文书
公司更名通知函
2015/04/24 职场文书
敬业奉献模范事迹材料(2016精选版)
2016/02/26 职场文书
MySql按时,天,周,月进行数据统计
2022/08/14 MySQL