全面解析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 相关文章推荐
js获取div高度的代码
Aug 09 Javascript
Jquery读取URL参数小例子
Aug 30 Javascript
无闪烁更新网页内容JS实现
Dec 19 Javascript
jquery.cookie.js使用指南
Jan 05 Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
Apr 13 Javascript
微信小程序 石头剪刀布实例代码
Jan 04 Javascript
浅谈gulp创建完整的项目流程
Dec 20 Javascript
angularJS的radio实现单项二选一的使用方法
Feb 28 Javascript
如何在vue中使用ts的示例代码
Feb 28 Javascript
关于微信小程序bug记录与解决方法
Aug 15 Javascript
vue实现条件判断动态绑定样式的方法
Sep 29 Javascript
Three.js实现简单3D房间布局
Dec 30 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正则获取页面所有图片地址
2016/03/23 PHP
Linux(CentOS)下PHP扩展PDO编译安装的方法
2016/04/07 PHP
php用户密码加密算法分析【Discuz加密算法】
2016/10/12 PHP
在 Laravel 6 中缓存数据库查询结果的方法
2019/12/11 PHP
js去空格技巧分别去字符串前后、左右空格
2013/10/21 Javascript
javascript右下角弹层及自动隐藏(自己编写)
2013/11/20 Javascript
js获取select默认选中的Option并不是当前选中值
2014/05/07 Javascript
在JavaScript应用中实现延迟加载的方法
2015/06/25 Javascript
解决jquery插件:TypeError:$.browser is undefined报错的方法
2015/11/21 Javascript
JavaScript中的ParseInt(&quot;08&quot;)和“09”返回0的原因分析及解决办法
2016/05/19 Javascript
轻松掌握JavaScript状态模式
2016/09/07 Javascript
js实现hashtable的赋值、取值、遍历操作实例详解
2016/12/25 Javascript
js实现5秒倒计时重新发送短信功能
2017/02/05 Javascript
ES6新特性一: let和const命令详解
2017/04/20 Javascript
jQuery实现checkbox即点即改批量删除及中间遇到的坑
2017/11/11 jQuery
vue使用Element组件时v-for循环里的表单项验证方法
2018/06/28 Javascript
微信小程序使用map组件实现检索(定位位置)周边的POI功能示例
2019/01/23 Javascript
vue实现动态按钮功能
2019/05/13 Javascript
[01:37]全新的一集《真视界》——TI7总决赛
2017/09/21 DOTA
用Python的urllib库提交WEB表单
2009/02/24 Python
Python实现把回车符\r\n转换成\n
2015/04/23 Python
python之virtualenv的简单使用方法(必看篇)
2017/11/25 Python
详解Django之auth模块(用户认证)
2018/04/17 Python
Python 判断文件或目录是否存在的实例代码
2018/07/19 Python
基于python的socket实现单机五子棋到双人对战
2020/03/24 Python
python 中的9个实用技巧,助你提高开发效率
2020/08/30 Python
Numpy实现卷积神经网络(CNN)的示例
2020/10/09 Python
python mongo 向数据中的数组类型新增数据操作
2020/12/05 Python
Python3爬虫ChromeDriver的安装实例
2021/02/06 Python
Lentiamo比利时:便宜的隐形眼镜
2020/02/14 全球购物
智能室内花园:Click & Grow
2021/01/29 全球购物
俄罗斯连接商品和买家的在线平台:goods.ru
2020/11/30 全球购物
用Python匹配HTML tag的时候,<.*>和<.*?>有什么区别
2012/11/04 面试题
实习自我鉴定范文
2013/10/30 职场文书
市场部经理岗位职责
2015/02/02 职场文书
2015年医院药剂科工作总结
2015/05/04 职场文书