Router:路由(注意:这里的路由完全不同于路由器!他们只是名字相似,其余毫无关系),这里的路由主要负责多个页面中的切换,一个站点的多个页面之间主要就是靠着路由进行着页面之间的联系。说的专业点就还是定义url规则
与具体的视图(View)
映射的关系。从A页面到B页面你也许会想到标签,相比于
标签Vue-Router的会强大的多,甚至你只用
Vue.js
+ Vue Router
就能创建单页应用(单页应用特点为一个拥有多个页面的网站,你在开发文件夹中只能看见一个.html文件)。
你可以通过npm
(npm可以看成是一个js常用的包管理器是随同NodeJS一起安装的,如果你了解Python的话,这里的nodejs和npm的关系类似与Python和pip,或者你可以就单纯的将npm理解成一个类似与Linux中yum或者apt之类的东西。)安装使用 npm install vue-router
。
也可以直接使用在线版本的 。
下方我所有的实例都会使用在线版本的,方便大家复制粘贴查看效果。
如果你使用的是VSCode可以将按照我的模板设置一套Vue使用的模板
使用Vue-Router导航,在从A路径导航进入B路径,如果A路径和B路径有相同的组件,将会直接复用。因为比起销毁在创建,复用会更加高效。不过这也意味着被复用组件的生命周期钩子不会被调用。
在路由规则中,*
可以匹配任意字符,我们可以利用此特性做一个404页面,并且*
的优先级很低,只有在找不到指定的路由才会使用*
,所以我们不用担心页面会提前被*
所匹配到。
有时候,通过一个名称来标识一个路由显得更方便一些,比如在路由路径较长有子路由时。在创建路由时候,我们只需要添加上name属性即可将视图命名,不过需要注意的是,在使用视图命名绑定视图时需要用到v-bind:
绑定
中的to
属性并使用字典将name写入,比如:
(默认情况下
相当于
)
上面我们提到过视图出口
,其实这个视图出口标签中隐藏了一个name
属性,其完整状态应该是
,如果我们在routes
(路由)中使用component
(组件)调用自定义组件,会默认传到name为default的视图中,但是如果一个比较复杂的页面中,我们想让不同的组件出现在不同的视图出口
,就可以给视图出口指定一个名称。但是在使用组件的时候,我们也应该使用其复数形式components
。
重定向是从一个网址重定向到另一个网址上使用,假如你的网站更换了域名或者ip地址更换,都可以使用重定向(比如你可以尝试访问 http://jingdong.com/
会被重定向到 https://www.jd.com/
),此时URL
会被替换
别名是一个页面可以拥有多个名称,我们虽然访问的URL
不同,但获得的模板却是相同的
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>vueRoutertitle>
head>
<body>
<router-link to="/">导航页1router-link>
<router-link :to="{path:'/'}">导航页2router-link>
<router-link :to="{name: '首页'}">首页router-link>
<router-view>router-view>
<router-view name='a'>我是视图a口,当前的页面路径为{{$route.path}}router-view>
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js">script>
<script>
// 创建首页模板
var index = Vue.extend({template:"测试索引页面"})
var home = {template:"测试页面首页
"}
var html404 = Vue.extend({template:"找不到该页面
"})
// 为插槽,用于接收上述视图组件中传入的值
var view_a = {template:"我是视图a,并且我在 输出
"}
// 创建Vue路由,并赋值,方便在Vue实例中调用
var router = new VueRouter({
routes:[
// path设置路由路径,用于router-link标签中to调用, component是指定调用的模板, alias用于起别名
{path: "/", component:index, alias: '/header'},
// name用于命名路由
{
path: "/home",
// 如果是渲染多个视图出口,需要使用components如下(component默认传给default没有命名的视图)
components:{
// default会给没有名称的视图中传入组件(或者视图名称为default的视图)
default: home,
// a用于给上述视图名称为a的视图出口处传自定义组件
a: view_a
},
// 可以使用name给路由起名
name:'首页',
// 使用alias传入数组可以给路由同时取多个别名
alias: ['/home1', '/home2', '/home3', '/home4', '/home5']
},
// 访问/index会被重定向到/
{path: "/index", redirect:'/'},
// 访问/head会被重定向到/home
{path: "/head", redirect:{name: "首页"}},
// *可以匹配任意字符,所以我们可以做一个*用来匹配不存在的页面
{path: "*", component:html404},
]
})
// 创建Vue实例
new Vue({
el: '#app',
// 调用路由
router,
data: {
vdata : 0
},
mounted(){
this.vdata += 1
console.log('我被调用了'+this.vdata+'次')
}
});
script>
html>
动态路由(通过URL向后台传参)
动态路由也是一个用途非常广泛的功能,很多新闻页面,个人登录页面都有动态路由,csdn的个人页面中就使用了动态路由。其中qq_39611230是我csdn的id,而动态路由则使用的此id。此id不仅有标识作用,还可以作为一种想路由中传参的手段,这里我的id是qq_39611230,我访问此路由就相当将我的id作为参数传给了页面。
在Vue-Router
中使用动态路由非常简单,只需要在路由路径中写入/:参数
即可(参数前可以不添加反斜杠,但如果不添加反斜杠直接写:参数
容易和前方的路径混淆),其中我们输入的动态路由参数会传如变量中。如下:
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>VueRouter动态路由title>
head>
<body>
<router-link to="/">导航页router-link>
<router-link :to='{name:"动态路由", params:{userid: uid}, query:{传参: items}}'>用户页面router-link>
<router-view>router-view>
<input type="text" v-model="uid" placeholder="你的id">
<input type="text" v-model="items" placeholder="参数">
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js">script>
<script>
// 创建首页模板
var index = Vue.extend({template:"首页"})
var nameuser = Vue.extend({
template:"{{$route.params.userid}}的个人中心",
// 生命周期函数(页面渲染完成时会调用)
mounted(){
console.log(this.$route)
}
})
// 创建Vue路由,并赋值,方便在Vue实例中调用
var router = new VueRouter({
routes:[
{path: "/", component:index},
{
// :userid 可以接收使用params方式传入的参数(上述传入时候键名必须和下方定义的相同),这样就可以实现动态路由
path: "/uid/:userid",
component:nameuser,
name:'动态路由'
}
]
})
// 创建Vue实例
new Vue({
el: '#app',
// 调用路由
router,
data:{
uid: '',
items: '',
}
});
script>
html>
注:$route
用于获取路由的一些信息,其中包含路由的参数,我们可以使用params
或者query
两种方式传参
嵌套路由(子路由)
csdn多个文章之间使用的路由就可以看成一种嵌套路由,从下图我们可以看成,第二部分和最后一部分是不一样的,其中第二部分是博主的id,而最后则应该是文章的id。
想要实现这个功能,我们就可以使用Vue-Router的嵌套路由,我们需要在routes
路由中除了path
和component
外在添加一个children
,这个children
就是嵌套路由,其中写入的东西和routes
一样。
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>VueRouter嵌套路由title>
head>
<body>
<router-link to="/">主页router-link>
<router-link to="/uid/测试">个人中心router-link>
<router-view>router-view>
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js">script>
<script>
// 创建首页模板
var index = Vue.extend({template:"主页"})
var home = Vue.extend({template:`
我的文章
我的下载资源
`})
var article = Vue.extend({template:"我的文章"})
var download = Vue.extend({template:"我的下载"})
// 创建Vue路由,并赋值,方便在Vue实例中调用
var router = new VueRouter({
routes:[
{path: "/", component:index},
{
path: "/uid/:userid",
component: home,
children: [
// 设置一个默认方法的页面
{path: "", component: article},
// 注意这里的路径(path)不需要带反斜杠
{path: "articles", component: article},
{path: "downloads", component: download},
]
},
]
})
// 创建Vue实例
new Vue({
el: '#app',
// 调用路由
router
});
script>
html>
不过需要注意的是children
中我们的路径(path
)是不需要加反斜杠的
编程式导航
之前我们想要跳转需要使用
作为一个连接,等待用户点击出发这种叫声明式,如果我们想要在js中出发页面跳转,这就要用的编程式导航router
中的router.push()
、router.replace()
和router.go()
三个进行,下面我们就来介绍一下他们怎么使用。
$router.push()
: 如果想要导航到不同的URL
.则需要使用此方法,调用此方法时加载的页面的时候,会将其每次跳转都记录到历史(history)栈中,所以如果用户点击后退按钮时,则回到之前的URL
中。
等同于router.push(...)
$router.replace()
: 此方法和$router.push()
类似,唯一不同的就是他不会向历史(history)栈中添加新的记录,而是替换掉当前的history记录。
router.go(n)
: 这里的n指的是一个整数,意思是在历史(history)栈中向前或者向后多少步,类似与浏览器的前进和后退按钮。
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>编程式导航title>
head>
<body>
<router-link to="/index">使用声明式导航进入索引router-link>
<router-view>router-view>
<button @click="page(0)">使用字符串的编程式导航button>
<button @click="page(1)">使用对象的编程式导航button>
<button @click="page(2)">使用编程式导航进入索引页并传参button>
<button @click="rep">使用替换历史记录的的编程式导航button>
<button @click="historys(-1)">后退button>
<button @click="historys(1)">前进button>
<br>
<button @click="page(3)">编程式错误的动态路由使用方式button>
<button @click="page(4)">编程式正确的的动态路由使用方式1button>
<button @click="page(5)">编程式正确的的动态路由使用方式2button>
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js">script>
<script>
// 创建首页模板
var index = Vue.extend({template:`
索引页面
使用声明式导航进入首页1
使用声明式导航进入首页2
使用声明式导航进入首页3
使用声明式导航进入首页4
使用声明式导航进入首页5
`})
var home1 = Vue.extend({template:"首页1
"})
var home2 = Vue.extend({template:"首页2
"})
var home3 = Vue.extend({template:"首页3
"})
var home4 = Vue.extend({template:"首页4
"})
var home5 = Vue.extend({template:"首页5
"})
var username = {template:"当前为{{$route.params.userid}}的个人中心
"}
// 创建Vue路由,并赋值,方便在Vue实例中调用
var router = new VueRouter({
routes:[
{path: "/", redirect: {name: '索引页面'}},
{
path: "/index",
component: index,
name: '索引页面',
children: [
{path: "home1", component: home1},
{path: "home2", component: home2},
{path: "home3", component: home3},
{path: "home4", component: home4},
{path: "home5", component: home5},
]
},
{
path: "/uid/:userid",
component:username,
name:'动态路由'
}
]
})
// 创建Vue实例
new Vue({
el: '#app',
// 调用路由
router,
methods: {
nums(){
// 做一个1-5的随机数
var num = Math.ceil(Math.random()*10)
if (num>5) {
num -= 5
}
else if(num==0) {
num = 1
}
return num
},
page(num){
// this.$route.path用于获取当前页面的路径,三元表达式用于,如果是/则随机切换到一个/home路径,反之亦然
var page = this.$route.path=='/index'?'/index/home'+this.nums():'/'
if (num==0) {
// push可以直接传入一个字符串参数,页面会导航到此参数所指的页面中
router.push(page)
} else if(num==1) {
// push还可以用对象的形式传入一个参数
router.push({path: page})
} else if(num==2) {
// 也可以通过命名路由指定路由和想路由中传参
router.push({name: '索引页面', query:{测试: '参数'}})
} else if(num==3) {
// 但是需要注意的是使用编程式导航想动态路由传参如果是使用的path则不能使用params传参,如下,参数无效
router.push({path: '/uid', params:{userid: '123'}})
} else if(num==4) {
// 我们可以直接写入完整路径即可
router.push({path: '/uid/123'})
}
else if(num==5) {
// 我们可以直接写入完整路径即可
router.push({name: '动态路由', params:{userid: '123'}})
}
},
rep(){
// 判断一下随机生成的对象是否和当前页面路径相同,如果相同则导航到首页
var p = '/index/home'+this.nums()
if (p == this.$route.path) {
p = '/index'
}
router.replace(p)
},
historys(num){
router.go(num)
}
}
});
script>
html>
路由传参
上面我们已经有方法进行了传参,分别是,路由中的组件如何向外传递参数,或者多个组件之间如何互相传递参数,上述我们用过$route.params
获取参数,不过我们还可以利用路由传参的方式,接收传入的参数,只需我们在new VueRouter()
的routers
中添加props: true
,然后在Vue.extend({})
添加props
属性,接收传入的参数即可。需要注意的是:Vue.extend({})
中添加的props
属性中用于接收参数的变量必须和params
中指定的键名相同。
如果我们指定了命名视图,这需要对每个命名视图都分别添加props
选项。
对象模式
上述我所说的使用props: true
为布尔模式,如果是true则会将外部的值直接传到模板中,但如果我们并不是想接收外部的值,而是在路由的时候手动传值,则可以使用对象的模式比如props: { userid: '这是我指定的值' },
这里的值,我们可以设置为一个变量。
函数模式
除布尔和对象外,props还可以接收函数props:function(){}
作为值,我们可以利用此特性接收使用?
传入的参数,比如function(route){return {userid: route.query.传参}}
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>VueRouter动态路由title>
head>
<body>
<router-link to="/">导航页1router-link>
<router-link :to='{name:"动态路由", params:{userid: uid}}'>用户页面router-link>
<router-link :to='{name:"传参的动态路由", params:{userid: uid}}'>传参的动态路由的用户页面router-link>
<router-link :to='{name:"多视图调用动态路由", params:{userid: uid}}'>多视图调用动态路由的用户页面router-link>
<router-link :to='{name:"对象模式", params:{userid: uid}}'>对象模式router-link>
<router-link :to='{name:"函数模式", params:{userid: uid}, query:{传参: "测试"}}'>函数模式router-link>
<router-view>router-view>
<router-view name='带传参的动态路由'>router-view>
<input type="text" v-model="uid" placeholder="你的id">
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js">script>
<script>
// 创建首页模板
var index = Vue.extend({template:"首页"})
var r_nameuser = Vue.extend({
template:"{{$route.params.userid}}的个人中心",
})
// 使用props接收参数的模板
var p_nameuser = Vue.extend({
props: ['userid'],
template:"{{userid}}的个人中心",
mounted(){
console.log(this.$route.query.传参)
}
})
// 创建Vue路由,并赋值,方便在Vue实例中调用
var router = new VueRouter({
routes:[
{path: "/", component:index},
{
path: "/ruid/:userid",
component:r_nameuser,
name:'动态路由',
},
{
path: "/puid/:userid",
component:p_nameuser,
name:'传参的动态路由',
// 直接输入true即可将外部值直接传入模板中
props: true,
},
// 对于包含命名视图的路由,必须分别为每个命名视图添加 `props` 选项:
{
path: "/vuid/:userid",
components:{ default: p_nameuser, 带传参的动态路由: p_nameuser },
name:'多视图调用动态路由',
// 如果是false则不会传参
props: { default: true, 带传参的动态路由: false },
},
{
path: "/ouid/:userid",
component:p_nameuser,
name:'对象模式',
// 对象模式可以指定值,这里的值也可以是个变量,不想像我这样写死
props: { userid: '这是我指定的值' },
},
{
path: "/fuid/:userid",
component:p_nameuser,
name:'函数模式',
// 使用函数模式可以接收使用问号传入的参数
// (route) => ({userid: route.query.传参}) 是 function(route){return {userid: route.query.传参}} 的简写
props: (route) => ({userid : route.query.传参})
}
]
})
// 创建Vue实例
new Vue({
el: '#app',
// 调用路由
router,
data: {
uid: ''
}
});
script>
html>