vue-router详尽:编程式导航、路由重定向、动态路由匹配、路由别名、嵌套路由、命名视图
vue-router编程式导航 在vue项目中经常用到this.$router.push() 和 this.$router.replace() 方法进行路由跳转就是编程式导航。。。通俗理解编程式导航:通过操作$router实例的JavaScript代码实现路由跳转。点击 <router-link :to="..."> 等同于调用 router.pus
vue-router编程式导航
在vue项目中经常用到this.$router.push() 和 this.$router.replace() 方法进行路由跳转就是编程式导航。。。
通俗理解编程式导航:通过操作$router实例的JavaScript代码实现路由跳转。点击 <router-link :to="...">
等同于调用 router.push(...)
。$router实例的方法有push()、replace()、go()方法,也可以进行路由传参。
先上代码简单入手看效果:
demo基于vue-cli创建的,项目结构如图:
第一步:定义路由文件 router >index.js如下
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import home from '@/components/Home' //引入组件
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/home', //可以定义路由路径、命名、组件、参数、别名、重定向
name: 'home',
component: home
},
]
})
第二步:helloWorld页面使用声明式和编程式导航到home组件的按钮,helloWorld组件如下
<template>
<div class="hello">
<h1>{{ msg }} 页面</h1>
<router-link to="/home">声明式使用router-link路由导航到home页面</router-link><br>
<button @click="pushToHome()">js编程式push方法导航到home页面</button>
<button @click="replaceToHome()">js编程式replace方法导航到home页面</button><br>
<button @click="goNext()">js编程式go方法导航到history记录的下一个页面</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to HelloWorld'
}
},
methods:{
pushToHome:function(){
this.$router.push("/home",function(){ //push()方法的使用,包括导航成功或失败的回调函数
console.log("导航成功的回调函数");
},function(){
console.log("导航中止的回调函数");
});
},
replaceToHome:function(){ //replace()方法的使用
this.$router.replace("/home");
},
goNext:function(){ //go()方法的使用
this.$router.go(1);
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
button {
margin:10px;
}
</style>
第三步骤页面:home组件中可以使用router.go(-1) 返回到上一个历史记录中的页面;无记录时点击无效。home组件如下
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<button @click="goBack()">js编程式go方法返回history页面</button>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'Welcome to Home 主页!!!!'
}
},
methods:{
goBack:function(){
this.$router.go(-1);
}
}
}
</script>
<style scoped>
h1, h2 {
color:red;
}
</style>
router.push(location, onComplete, onAbort)方法
1、router.push() 方法,参数分别指的是导航到 新的url、导肮完成的回调函数、导航中止的回调函数 ;
2、router.push() 方法 会向history栈添加一个新的记录 ,所以当用户点击浏览器后退按钮时,则回到之前的 URL。
3、router.push(location)方法使用
//使用路由的path值
this.$router.push("/router1");
//使用包含路由path键值的对象
this.$router.push({path:'/router1'});
//使用包含路由name键值的对象
this.$router.push({name:'routerNum1'});
//使用包含name键值和params参数对象的对象,
//注意:该方式params传参浏览器页面不在url中显示参数,但是会页面刷新的时候丢失参数
this.$router.push({name:'routerNum1',params:{userId:123}});
//path键值结合params的形式传参无效
this.$router.push({path:'/router1',params:{userId:123}});
//可以使用path键值结合query的形式传参
this.$router.push({path:'/router1',query:{userId:123}});
//使用path值拼接参数来传参,注意这里使用的不是单引号!!!
const userId=123;
this.$router.push({path:`/router1/${userId}`});
4、 push()编程式导航注意点:
const userId = 123
1、router.push({ path: `/router1/${userId}` }) // 注意使用反引号
2、router.push({ path: '/router1', params: { userId }}) // 注意path键值结合params传参无效
3、router.push({ name: '/routerNum1', params: { userId }}) // 注意该方式在浏览器url不显示参数,但是页面刷新会导致参数丢失
4、小demo使用验证如下:
第一步:定义路由文件 router >index.js如下
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import home from '@/components/Home'
import router1 from '@/components/Router1'
import router2 from '@/components/Router2'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/home',
name: 'home',
component: home
},
{
path: '/router1',
name: 'routerNum1',
component: router1
},
{
path: '/router2',
name: 'routerNum2',
component: router2
},
]
})
第二步:home.vue组件文件代码如下。
<template>
<div class="hello">
<h3>{{ msg }}</h3>
<button @click="goBack()">js编程式go方法返回history页面</button>
<hr>
<h3>js编程式导航中push方法的使用:</h3>
<button @click="pathTo()">push方法的url参数使用path值导航</button>
<button @click="pathObjectTo()">push方法的url参数使用path对象导航</button><br>
<button @click="nameObjectTo()">push方法,包含路由命名name键值的对象导航</button><br>
<button @click="nameParamTo()">push方法,包含路由命名name键值的对象结合params传参</button><br>
<button @click="pathParamTo()">push方法,path键值对象导航结合params传参,参数传递失败</button>
<button @click="pathQueryTo()">push方法,path键值对象导航结合query传参</button><br>
<button @click="pathandTo()">push方法,path值拼接参数来传参</button>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'Welcome to Home 主页!!!!'
}
},
methods:{
goBack:function(){
this.$router.go(-1);
},
pathTo:function(){ //使用路由的path值
this.$router.push("/router1");
},
pathObjectTo:function(){ //使用包含路由path键值的对象
this.$router.push({path:'/router1'});
},
nameObjectTo:function(){ //使用包含路由name键值的对象
this.$router.push({name:'routerNum1'});
},
nameParamTo:function(){ //使用包含name键值和params参数对象的对象
this.$router.push({name:'routerNum1',params:{userId:123}});
},
pathParamTo:function(){ //path键值结合params的形式传参无效
this.$router.push({path:'/router1',params:{userId:123}});
},
pathQueryTo:function(){ //可以使用path键值结合query的形式传参
this.$router.push({path:'/router1',query:{userId:123}});
},
pathandTo:function(){
const userId=123;
this.$router.push({path:`/router1/${userId}`});
}
}
}
</script>
<style scoped>
h1, h2 {
color:red;
}
</style>
第三步:router1.vue组件代码如下,使用this.$route.params.paramName或query.queryName接收路由传的参数。
<template>
<div class="hello">
<h3>{{ msg }}</h3>
<button @click="goBack()">js编程式go方法上一个路由页面</button>
<p>{{fromRouterParams}}</p>
<p>{{fromRouterQuery}}</p>
</div>
</template>
<script>
export default {
name: 'Router1',
data () {
return {
msg: 'Welcome to Router1' ,
fromRouterParams:this.$route.params.userId,
fromRouterQuery:this.$route.query.userId,
}
},
methods:{
goBack:function(){
this.$router.go(-1);
},
}
}
</script>
<style scoped>
h1, h2 {
color:red;
}
</style>
router.replace(location, onComplete, onAbort)方法
跟 router.push
很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录;
router.go(n)方法
1、参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
。 Browser History APIs点击了解更多
2、使用:
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
Vue Router 的导航方法 (push
、 replace
、 go
) 在各类路由模式 (history
、 hash
和 abstract
) 下表现一致。
路由重定向:
路由配置{ path: '/a', redirect: '/b' },路由重定向是指当用户访问 /a
时,路由跳转到b路由,URL 将会被替换成 /b
1、在路由配置文件 router >index.js上使用:
const router = new VueRouter({
routes: [
{ path: '/router1', redirect: '/router2' }, //是从 /route1 重定向到 /router2
{ path: '/b', redirect: {name:'foo'} }, //重定向的目标也可以是一个命名的路由
{ path: '/c', redirect:(to)=>{
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
//注意:导航守卫应用在导航跳转目标to上
}},
]
})
2、注意在给路由设置有路由重定向时,再使用的路由导航会应用在跳转to指向的路由上,如下路由router1上的导航守卫无效
{
path: '/router1',
redirect: '/router2',
name: 'routerNum1',
component: router1,
beforeEnter:(from,to,next)=>{ //导航守卫无效
console.log("在路由1上进行重定向");
next();
}
},
{
path: '/router2',
name: 'routerNum2',
component: router2,
beforeEnter:(from,to,next)=>{
console.log("进入到了路由2");
next();
}
},
3、重定向指向自身会报错:[Vue warn]: Error in beforeCreate hook: "RangeError: Maximum call stack size exceeded,使用动态路径参数传参除外
路由别名
路由别名可以理解为路由的 '小名',可以使用路由别名进行路由导航
路由 /router2 的别名 alias 为 /secondRouter ,那么使用别名访问 /secondRouter 时,url是/secondRouter,导航跳转到路由 /router2 ,如下
{path: '/router2', name: 'routerNum2', alias:'/secondRouter',component: router2 },
动态路由匹配:
使用情况:
1、如果导航目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users/1
-> /users/2
),需要组件复用,组件复用意味着组件的生命周期钩子函数不会被调用!
2、或者所有路由映射到同一个组件模式渲染,只是参数不同时。那么,我们可以在 vue-router
的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果:
动态路径参数的使用
第一步:动态路径参数的使用需要在路由配置文件上使用冒号开头的形式
{
//动态路径参数的使用 冒号开头
//那么像/router1/1 和/router1/2都将跳转到该路由页面
path: '/router1/:userNum',
name: 'routerNum1',
component: router1,
},
第二步:使用this.$router.push({path: `/router1/${userNum1}` }); 形式进行动态路径传参,注意反引号,url中的参数不会刷新丢失
<template>
<div class="hello">
<h3>{{ msg }}</h3>
<button @click="goBack()">js编程式go方法返回history页面</button>
<hr>
<h3>js动态路由匹配的使用:</h3>
<button @click="pathParam1To()">动态路径参数1导航</button>
<button @click="pathParam2To()">动态路径参数2导航</button>
<hr>
<button @click="diffParamsTo()">导航到当前组件(组件复用),但传递的参数不同</button>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'Welcome to Home 主页!!!!'
}
},
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
console.log('路由发生变化');
console.log(this.$route.params.userNum);
}
},
methods:{
goBack:function(){
this.$router.go(-1);
},
pathParam1To:function(){
let userNum1=111111;
this.$router.push({path:`/router1/${userNum1}`});
},
pathParam2To:function(){
let userNum2=222222;
this.$router.push({path:`/router1/${userNum2}`});
},
diffParamsTo:function(){
let userNum2=666;
this.$router.push({path:`/router1/${userNum2}`});
},
}
}
</script>
<style scoped>
h1, h2 {
color:red;
}
</style>
第三步:可以在路由组件中使用this.$route.params获取动态路径参数,如下
<p>{{this.$route.params.userNum}}</p>
组件复用
复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route
对象:
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
console.log('路由发生变化');
console.log(this.$route.params.userNum);
}
},
也可以使用2.2中引入的 beforeRouteUpdate导航守卫来响应这个变化 (比如抓取用户信息)。组件内导航守卫可以点击了解
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
嵌套路由
嵌套路由指的是在渲染的路由组件页面中包含了下级路由渲染出口(<router-view>),浏览器的URL 中各段动态路径也按某种结构对应嵌套的各层组件,
在项目的app.vue 文件中<router-view>是最顶层的出口,渲染最高级路由匹配到的组件。
<div id="app">
<router-view></router-view>
</div>
第一步:定义路由配置文件router >index.js,在路由上使用children属性定义下级路由
import Vue from 'vue'
import Router from 'vue-router'
import helloWorld from '@/components/HelloWorld'
import home from '@/components/Home'
import book from '@/components/Book'
import water from '@/components/Water'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component:helloWorld
},
{
path: '/home',
component: home,
children:[
{
path:'', //当访问的子路由路径无匹配时会指向到该空的子路由
component:water,
},
{
path:'book',
component:book,
},
{
path:'water',
component:water,
},
]
},
]
})
第二步:路由组件home.vue的内容,子路由导航包括了声明式和编程式导航
<template>
<div class="hello">
<h3>{{msg}}</h3>
<button @click="showBookRouter()">点击按钮显示子路由页面book</button>
<button @click="showWaterRouter()">点击按钮显示子路由页面water</button><br>
<router-link to="/home/book">book</router-link>
<router-link to="/home/water">water</router-link>
<router-link to="/home/">foo</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'Welcome to Home !!!'
}
},
methods:{
showBookRouter:function(){
this.$router.push('/home/book'); //编程式路由导航
},
showWaterRouter:function(){
this.$router.push('/home/water');
},
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
color:red;
}
</style>
第三步:子组件book.vue 和water.book这里就不写了
命名视图
同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view
没有设置名字,那么默认为 default
。
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components
配置 (带上 s):
{
path: '/',
components: {
default: water,
a: book,
b: water
}
}
参考网址:官网API https://router.vuejs.org/zh/guide/essentials/navigation.html
更多推荐
所有评论(0)