官方文档
https://router.vuejs.org/zh-cn/
用 Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。
hash 和 history模式
默认hash模式:
以#/开始匹配,这种叫作哈希模式(hash)
HTML5 History 模式:
/开始,就是我们常见的方式没有 # 符号
<a href=
"/"
>首页</a>
<a href=
"/work"
>工作</a>
|
我们此时使用a标签来切换比较麻烦,每次更改路由模式的时候,需要单独改a标签里面herf的链接
在vue里面提供了一个更好的方式,来解决这个问题
<router-link to=
"/"
>home主页</router-link>
<router-link to=
"/work"
>我的工作</router-link>
|
<router-view/>
每次切换路由的时候,里面的内容都依靠 来显示在页面上
只有页面有导航的地方,打算让组件显示在页面上,必须写这个标签
<template>
<div id=
"app"
>
<router-link to=
"/"
>home主页</router-link>
<router-link to=
"/work"
>我的工作</router-link>
<router-view> 这个标签用来显示页面内容
</router-view></div>
</template>
|
router-link 默认解析成a标签
<a href=
"#/"
class=
"router-link-active"
>home主页</a>
<a href=
"#/work"
class=
"router-link-exact-active router-link-active"
>我的工作</a>
|
给导航添加激活样式
通过css里面设置
.router-link-active{
background-color
:
red
}
|
当我们单独设置激活样式的时候,根路由 / 永远都会匹配到样式
我们可以在标签中添加 exact 方式来解决永远都会匹配到跟路径样式问题
直接加在标签属性上
<router-link exact=
""
to=
"/"
>home主页</router-link>
|
我们自己来给导航添加自定义class名字
通过 设置 active-class属性值 改变默认的激活样式类
<router-link to=
"/work"
active-class=
"starkwang"
>我的工作</router-link>
|
统一更改激活样式
在 router/index.js里面设置 linkExactActiveClass属性
export
default
new
Router({
// mode: 'history',
mode:
'hash'
,
linkExactActiveClass:
'shudong'
,
//通过设置这个属性值,给所有的激活样式,添加统一的类
当我们统一设置后,每次激活的路由标签,都带着自己设置的这个shudong类
<a href=
"#/work"
class=
"shudong starkwang"
>我的工作</a>
|
使用属性 tag 统一更改路由编译后的标签名字 -> <li> </li>
默认编译的标签名字是 a
<router-link to=
"/stark"
tag=
"li"
>我的Stark</router-link>
更改完后的dom
<li class=
"shudong router-link-active"
>我的Stark</li>
|
路由嵌套 chidren
使用方式
{
path:
'/about'
,
// 这是一级路由
component: About,
children: [{
// 里面是嵌套路由
path:
'blog'
,
//如果在这个嵌套
name:
'blog'
,
component: Blog
},
{
path:
'/info'
,
name:
'info'
,
component: Info
}
]
}
|
如果在这个嵌套里面的path:” 留空,默认会显示这个组件
http:
//localhost:8080/#/about
此时会把 这个默认留空的嵌套路由组件显示出来,也就是上面的blog 组件显示出来
|
如果嵌套路由里面的path:’blog’ 写具体的路由,则访问的时候必须匹配
必须是这个路由精准匹配
http:
//localhost:8080/#/about/blog
这样才会把这个blog嵌套路由组件显示出来
|
以 / 开头的嵌套路径会被当作根路径。
这让你充分的使用嵌套组件而无须设置嵌套的路径。
{
path:
'/about'
,
// 这是一级路由
component: About,
children: [{
// 里面是嵌套路由
path:
'blog'
,
//如果在这个嵌套
name:
'blog'
,
component: Blog
},
{
path:
'/info'
,
// 以 / 开头的嵌套路径会被当作跟路径
name:
'info'
,
component: Info
}
]
}
访问方式:
http:
//localhost:8080/#/info
|
如果去掉/ 此时去掉了 ‘/info’ -> ‘info’
{
path:
'/about'
,
// 这是一级路由
component: About,
children: [{
// 里面是嵌套路由
path:
'blog'
,
//如果在这个嵌套
name:
'blog'
,
component: Blog
},
{
path:
'info'
,
// 此时去掉了 '/info' -> 'info'
name:
'info'
,
component: Info
}
]
}
访问方式:
http:
//localhost:8080/#/about/info
|
你会发现,children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
此时,基于上面的配置,当你访问 /about/info 时,about 的出口是不会渲染任何东西,这是因为没有匹配到合适的子路由。
重定向
使用方式 path:’*’
这个 * 是匹配上面没有找到的路径,会到这里
可以直接写:component: NotFound,
redirect 这是一个函数,里面有参数 to
to 打印出来是一个对象
{name: undefined, meta: {…}, path: “/aaa”, hash: “”, query: {…}, …}
通过 to.path 可以获取当前用户访问的路径,来写一些逻辑跳转下面是使用详细方式
{
path:
'*'
,
// component: NotFound,
redirect: (to) => {
console.log(to);
if
(to.path ===
'/aaa'
) {
return
'/work'
}
else
if
(to.path ===
'/bbb'
) {
return
'/info'
}
else
{
return
'/'
}
}
}
|
最后附上所有路由文件代码
import Vue from
'vue'
import Router from
'vue-router'
import HelloWorld from
'@/components/HelloWorld'
import Work from
'@/components/Work'
import Stark from
'@/components/Stark'
Vue.use(Router)
const UserProfile = { template: `<div> 我是profile 组件 </div>` };
const UserPosts = { template: `<div> 我是UserPosts 组件 </div>` };
const Blog = { template: `<div> 我是Blog 组件 </div>` };
const Info = { template: `<div> 我是Info 组件 </div>` };
const NotFound = { template: `<div>404 您访问的页面不存在 </div>` };
const About = { template: `<div> 我是About组件 <router-view> </router-view> </div>` };
const User = {
// template: '<div>User {{ $route.params.id }}</div>'
template:
' <div class="user"> \
<h2><a name="13"></a> User {{ $route.params.id } } </h2> \
<router-view> </router-view> \
</div>'
}
export
default
new
Router({
// mode: 'history',
mode:
'hash'
,
linkExactActiveClass:
'shudong'
,
routes: [{
path:
'/'
,
name:
'Hello'
,
component: HelloWorld
},
{
path:
'/work'
,
name:
'Work'
,
component: Work
},
{
path:
'/stark'
,
name:
'stark'
,
component: Stark
},
// { path: '/user/:id', component: User }
{
path:
'/user/:id'
,
component: User,
children: [{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path:
'profile'
,
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path:
'posts'
,
component: UserPosts
}
]
},
{
path:
'/about'
,
component: About,
children: [{
path:
'blog'
,
name:
'blog'
,
component: Blog
},
{
path:
'/info'
,
name:
'info'
,
component: Info
}
]
},
{
path:
'*'
,
// component: NotFound,
redirect: (to) => {
console.log(to);
if
(to.path ===
'/aaa'
) {
return
'/work'
}
else
if
(to.path ===
'/bbb'
) {
return
'/info'
}
else
{
return
'/'
}
}
}
]
})
|
路由传参
传一个参数
在路由里面的path:
'/user/:stark'
这个冒号后面跟的字符串相当于 key
在组件里面使用
this
.$route.params.stark 来获取这个value的值
访问方式:
http:
//localhost:8080/#/user/wang
wang 就是console.log(
this
.$route.params.stark) 值
在后面跟 ?号
可以 写wang 或不写 后面的参数
如果不跟?号 ,必须写这个参数
|
如果想传多个参数
在路由里面添加多个key
path: '/user/:stark?/:name?
访问方式
http:
//localhost:8080/#/user/wang/stark
打印结果 console.log(
this
.$route.params)
{stark:
"wang"
, name:
"shudong"
}
|
{
path:
'/user/:stark?/:name?'
,
name:
'user'
,
component: User
},
|
案例:
user 组件
<template>
<div>
<router-link :to=
"'/user/' + item.id"
v-
for
=
"item in userList"
>{{item.username}} </router-link>
<div>
<p> 姓名:{{userInfo.username}}</p>
<p> 爱好:{{userInfo.hobby}}</p>
<p> 性别:{{userInfo.sex}}</p>
</div>
</div>
</template>
<script>
let data = [
{
id:1,
tip:
'vip'
,
username:
'luchang'
,
sex:
'男'
,
hobby:
'coding'
},
{
id:2,
tip:
'vip'
,
username:
'guomian'
,
sex:
'男'
,
hobby:
'女'
},
{
id:3,
tip:
'common'
,
username:
'zhangming'
,
sex:
'男'
,
hobby:
'bug'
},
]
export
default
{
data(){
return
{
userList:data,
userInfo:
''
}
},
watch:{
$route(){
this
.getData();
}
},
created(){
this
.getData();
},
methods:{
getData(){
// let id = this.$route;
console.log(
this
.$route);
let id =
this
.$route.params.userId;
if
(id){
this
.userInfo =
this
.userList.filter((item)=>{
return
item.id == id;
})[0]
}
console.log(
this
.userInfo);
// console.log(this.$route.params.stark);
}
}
}
</script>
|
路由
import Vue from
'vue'
import Router from
'vue-router'
import HelloWorld from
'@/components/HelloWorld'
import Work from
'@/components/Work'
import Stark from
'@/components/Stark'
import User from
'@/components/User'
Vue.use(Router)
const UserProfile = { template: `<div> 我是profile 组件 </div>` };
const UserPosts = { template: `<div> 我是UserPosts 组件 </div>` };
const Blog = { template: `<div> 我是Blog 组件 </div>` };
const Info = { template: `<div> 我是Info 组件 </div>` };
const NotFound = { template: `<div>404 您访问的页面不存在 </div>` };
const About = { template: `<div> 我是About组件 <router-view> </router-view> </div>` };
const Users = {
// template: '<div>User {{ $route.params.id }}</div>'
template:
' <div class="user"> \
<h2><a name="15"></a> User {{ $route.params.id } } </h2> \
<router-view> </router-view> \
</div>'
}
export
default
new
Router({
// mode: 'history',
mode:
'hash'
,
linkExactActiveClass:
'shudong'
,
routes: [{
path:
'/'
,
name:
'Hello'
,
component: HelloWorld
},
{
path:
'/work'
,
name:
'Work'
,
component: Work
},
{
path:
'/user/:userId?/:name?'
,
name:
'user'
,
component: User
},
{
path:
'/stark'
,
name:
'stark'
,
component: Stark
},
// { path: '/user/:id', component: User }
{
path:
'/users/:id'
,
component: Users,
children: [{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path:
'profile'
,
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path:
'posts'
,
component: UserPosts
}
]
},
{
path:
'/about'
,
component: About,
children: [{
path:
'blog'
,
name:
'blog'
,
component: Blog
},
{
path:
'/info'
,
name:
'info'
,
component: Info
}
]
},
{
path:
'*'
,
// component: NotFound,
redirect: (to) => {
// console.log(to);
if
(to.path ===
'/aaa'
) {
return
'/work'
}
else
if
(to.path ===
'/bbb'
) {
return
'/info'
}
else
{
return
'/'
}
}
}
]
})
|