介绍
1,什么是vue-router?
(官方)vue-router是专门给vue提供的路由管理器。
vue-router是个模块,是一个js的模块。基于vue的语法封装的专门处理路由切换的模块
vue-router是前端路由,用来切换页面(切换组件)
2,为什么使用?
在大型的项目中,组件数量很多,组件之间的关系复杂,需要一个功能完善的模块统一管理组件
3,
route:一条路由信息,映射关系 /admin/list --- 网站的管理主页、/detail --文章详情页
routes:多条路由信息。[/admin/list --- 网站的管理主页,/detail --文章详情页],根据多条映射关系,汇总的一个路由表
router:路由对象。routes只是一张表,摆在那不应用一点作用都没有,router路由对象才是真正将映射关系实现的管理者
发起请求,router会发现请求,找routes找对应关系,将关系实现
使用
<body>
<div id='app'>
<ul>
<!-- router-link触发路由切换的组件,to属性配置路由的 -->
<router-link to="/home">
<li>首页</li>
</router-link>
<router-link to="/news">
<li>新闻</li>
</router-link>
<router-link to="/product">
<li>产品</li>
</router-link>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
//1,定义路由对象,指定路由规则
//2,给Vue注入路由对象
//3,调用 router-link 组件,触发路由切换(原理:a标签)
//4,在相应的位置,调用 router-view组件 用来显示路由组件的
const router = new VueRouter({
routes:[
{
path:"/home",
component:{
template:`<h1>我是home组件</h1>`
}
},
{
path:"/news",
component:{
template:`<h1>我是news组件</h1>`
}
},
{
path:"/product",
component:{
template:`<h1>我是product组件</h1>`
}
}
]
})
new Vue({
el:'#app',
// router:router,
router, //注入路由对象
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
动态路由的路由参数
<body>
<div id='app'>
<ul>
<!-- router-link触发路由切换的组件,to属性配置路由的 -->
<router-link to="/home/我是路由参数/第二个参数">
<li>首页</li>
</router-link>
<router-link to="/news">
<li>新闻</li>
</router-link>
<router-link to="/product">
<li>产品</li>
</router-link>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
//1,定义路由对象,指定路由规则
//2,给Vue注入路由对象
//3,调用 router-link 组件,触发路由切换(原理:a标签)
//4,在相应的位置,调用 router-view组件 用来显示路由组件的
const router = new VueRouter({ //路由对象
routes:[
{
//设置路由参数 :abc路由参数,以冒号为标识,abc是个变量名
path:"/home/:abc/:def",
component:{
template:`<h1>我是home组件
abc:{{$route.params.abc}}
def:{{$route.params.def}}
</h1>`,
//当前路由信息和目标路由一致(不管路由参数变化与否),不会触发重新加载,不会再次触发created
created(){
console.log(this.$route) //路由信息对象
console.log(this.$route.params.abc) //路由信息对象
},
}
},
{
path:"/news",
component:{
template:`<h1>我是news组件</h1>`
}
},
{
path:"/product",
component:{
template:`<h1>我是product组件</h1>`
}
}
]
})
new Vue({
el:'#app',
// router:router,
router, //注入路由对象
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
动态路由的查询参数
<body>
<div id='app'>
<ul>
<!-- router-link触发路由切换的组件,to属性配置路由的 -->
<router-link to="/home">
<li>首页</li>
</router-link>
<router-link to="/news?abc=我是查询参数&def=谢谢">
<li>新闻</li>
</router-link>
<router-link to="/product">
<li>产品</li>
</router-link>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
//1,定义路由对象,指定路由规则
//2,给Vue注入路由对象
//3,调用 router-link 组件,触发路由切换(原理:a标签)
//4,在相应的位置,调用 router-view组件 用来显示路由组件的
const router = new VueRouter({
routes:[
{
path:"/home",
component:{
template:`<h1>我是home组件</h1>`,
}
},
{
//查询参数
path:"/news",
component:{
template:`<h1>我是news组件
abc:{{$route.query.abc}}
def:{{$route.query.def}}
</h1>`,
created(){
// console.log(this.$route)
console.log(this.$route.query.abc)
},
}
},
{
path:"/product",
component:{
template:`<h1>我是product组件</h1>`
}
}
]
})
new Vue({
el:'#app',
// router:router,
router, //注入路由对象
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
监听路由信息变化
<body>
<div id='app'>
<ul>
<!-- router-link触发路由切换的组件,to属性配置路由的 -->
<router-link to="/home/我是路由参数/第二个参数">
<li>首页</li>
</router-link>
<router-link to="/news?abc=我是查询参数&def=谢谢">
<li>新闻</li>
</router-link>
<router-link to="/product">
<li>产品</li>
</router-link>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
//1,定义路由对象,指定路由规则
//2,给Vue注入路由对象
//3,调用 router-link 组件,触发路由切换(原理:a标签)
//4,在相应的位置,调用 router-view组件 用来显示路由组件的
const router = new VueRouter({ //路由对象
routes:[
{
//设置路由参数 :abc路由参数,以冒号为标识,abc是个变量名
path:"/home/:abc/:def",
component:{
template:`<h1>我是home组件
abc:{{$route.params.abc}}
def:{{$route.params.def}}
</h1>`,
//当前路由信息和目标路由一致(不管路由参数变化与否),不会触发重新加载,不会再次触发created
created(){
console.log("组件重新创建完成!!!")
// console.log(this.$route) //路由信息对象
// console.log(this.$route.params.abc) //路由信息对象
},
watch:{ //可以监听到参数的变化!
$route(to,from){
console.log("路由信息对象变化了!!")
console.log(to,from) //to指的是当前路由 from上一条路由
}
}
}
},
{
path:"/news",
component:{
template:`<h1>我是news组件
abc:{{$route.query.abc}}
def:{{$route.query.def}}
</h1>`
}
},
{
path:"/product",
component:{
template:`<h1>我是product组件</h1>`
}
}
]
})
new Vue({
el:'#app',
// router:router,
router, //注入路由对象
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
路由嵌套
<body>
<div id='app'>
<ul>
<!-- router-link触发路由切换的组件,to属性配置路由的 -->
<router-link to="/home">
<li>首页</li>
</router-link>
<router-link to="/news">
<li>新闻</li>
</router-link>
<router-link to="/product">
<li>产品</li>
</router-link>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
let pro = {
template:`<div>产品组件
<ul>
<router-link to="/product/p1/201101">
<li>产品1</li>
</router-link>
<router-link to="/product/p2?idx=201102">
<li>产品2</li>
</router-link>
</ul>
<router-view></router-view>
</div>`
}
let router = new VueRouter({
routes:[
{
path:"/home",
component:{
template:`<h1>我是home组件</h1>`
}
},
{
path:"/news",
component:{
template:`<h1>我是news组件</h1>`
}
},{
path:"/product", //设置路由名称:以/开头表示从根路由开始,没有/开头,跟在当前接口后面做子路由
component:pro,
children:[
{
path:"p1/:idx",
component:{
template:`<i>我是 产品1 组件{{$route.params.idx}}</i>`
}
},
{
path:"p2",
component:{
template:`<i>我是 产品2 组件{{$route.query.idx}}</i>`
}
}
]
}
]
})
new Vue({
el:'#app',
router,
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
编程式路由
<body>
<div id='app'>
<ul>
<li @click="jump('home')">首页</li>
<li @click="jump('news')">新闻</li>
<li @click="jump('product')">产品</li>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
const router = new VueRouter({ //路由对象
routes:[
{
//设置路由参数 :abc路由参数,以冒号为标识,abc是个变量名
path:"/home",
component:{
template:`<h1>我是home组件
</h1>`,
//当前路由信息和目标路由一致(不管路由参数变化与否),不会触发重新加载,不会再次触发created
created(){
console.log("组件重新创建完成!!!")
console.log(this.$route) //路由信息对象
// console.log(this.$route.params.abc) //路由信息对象
},
watch:{ //可以监听到参数的变化!
$route(to,from){
console.log("路由信息对象变化了!!")
// console.log(to,from) //to指的是当前路由 from上一条路由
}
}
}
},
{
path:"/news",
component:{
template:`<h1>我是news组件
abc:{{$route.query.abc}}
def:{{$route.query.def}}
</h1>`
},
created(){
console.log("组件重新创建完成!!!")
console.log(this.$route) //路由信息对象
// console.log(this.$route.params.abc) //路由信息对象
},
},
{
path:"/product",
component:{
template:`<h1>我是product组件</h1>`
},
created(){
console.log("组件重新创建完成!!!")
console.log(this.$route) //路由信息对象
// console.log(this.$route.params.abc) //路由信息对象
},
}
]
})
new Vue({
el:'#app',
router,
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
jump(url){
//编程式路由:使用js代码,触发路由跳转,不允许重复访问当前路径(会报错,可以忽略)
//方法1:
// this.$router.push(url) //push方法,向history历史记录中添加一个新的记录,允许前进后退
// 方法2:
// this.$router.push({
// path:url,
// query:{ //查询参数
// idx:url
// },
// params:{ //路由参数,在使用编程式路由时,不能使用path+params传递参数,path会忽略掉params
// str:"params-"+url //解决,使用命名路由
// }
// })
//方法3: replace --替换,不会向history对象添加新的访问记录
this.$router.replace({
path:url
})
}
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
命名路由
<body>
<!--编程式路由下,param参数(路由参数)和query参数(查询参数)区别:
1,path+params传递路由参数,不可以的,path会忽略params。
path+query,可以传递查询参数,会拼接在地址栏。(query类似get)
2,name+params可以传递路由参数,不会拼接在地址栏上(params类似post)
3,params参数会被f5强制刷新刷新掉。
-->
<div id='app'>
<ul>
<li @click="jump('home')">首页</li>
<li @click="jump('news')">新闻</li>
<li @click="jump('product')">产品</li>
</ul>
<!-- router-view用来显示组件的 -->
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
const router = new VueRouter({ //路由对象
routes:[
{
path:"/home",
name:"home", //命名路由
component:{
template:`<h1>我是home组件
</h1>`,
created(){
console.log("组件重新创建完成!!!")
console.log(this.$route) //路由信息对象
},
watch:{ //可以监听到参数的变化!
$route(to,from){
console.log("路由信息对象变化了!!")
}
}
}
},
{
path:"/news",
name:"news",
component:{
template:`<h1>我是news组件
abc:{{$route.query.abc}}
def:{{$route.query.def}}
</h1>`,
created(){
console.log("组件重新创建完成!!!")
console.log(this.$route) //路由信息对象
},
},
},
{
path:"/product",
name:"product",
component:{
template:`<h1>我是product组件</h1>`,
created(){
console.log("组件重新创建完成!!!")
console.log(this.$route) //路由信息对象
}
},
}
]
})
new Vue({
el:'#app',
router,
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
jump(url){
this.$router.push({
name:url,
query:{ //查询参数
idx:url
},
params:{ //路由参数,在使用编程式路由时,不能使用path+params传递参数,path会忽略掉params
str:"params-"+url //解决,使用命名路由
}
})
}
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
重定向与路由别名
<body>
<div id='app'>
<button type="button" @click="jump()">点击 first</button>
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
const router = new VueRouter({
routes:[
{
path:"/first",
component:{
template:`<h1>first</h1>`
},
//重定向,当用户访问/a接口,会被引导至/b,并且地址栏显示/b接口。
// redirect:function(to){
// return "/second"
// },
redirect:to=>"/second"
},
{
path:"/second",
component:{
template:`<h1>second</h1>`
},
//路由别名,当用户访问/a接口,会被引导至/b,并且地址栏显示/a接口。
alias:"/third"
},
{
path:"/third",
component:{
template:`<h1>third</h1>`
}
}
]
})
new Vue({
el:'#app',
router,
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
jump(){
this.$router.push({
path:"first"
})
}
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
history模式和hash模式
<body>
<div id='app'>
<router-link to="/home">
<button>home</button>
</router-link>
<router-link to="/news">
<button>news</button>
</router-link>
<router-view></router-view>
</div>
</body>
<script type='text/javascript'>
window.onhashchange = function(){
// console.log(location.hash)
var h = location.hash.split("#/#").pop()
console.log(h)
document.body.style.background = h
}
let router = new VueRouter({
//默认的模式 hash模式:以#为特征,路由地址不够简洁,history模式,会保留简洁路径地址
mode:"history",
routes:[
{
path:"/home",
component:{
template:`<h1>我是home组件</h1>`
}
},
{
path:"/news",
component:{
template:`<h1>我是news组件</h1>`
}
}
]
})
new Vue({
el:'#app',
router,
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //监听,配置项,handler deep immediate
},
created(){
},
})
</script>
命名视图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html,body,#vue,.fl,.fr {
height: 100%;
}
div.fl {
float: left;
width: 20%;
background-color: #fc9;
}
li.fl {
float: left;
cursor: pointer;
margin: auto 10px;
}
div.fr {
float: right;
width: 80%;
}
aside,header,footer,section {
color: #fff;
text-align: center;
}
header,footer {
height: 10%;
background-color: lightseagreen;
}
section {
height: 80%;
background-color: lightsalmon;
}
</style>
<link rel="stylesheet" href="css/reset.css">
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
</head>
<body>
<div id="vue">
<div class="fl">
<!-- <aside>侧边栏</aside>-->
<router-view name="aside"></router-view>
</div>
<div class="fr">
<!-- <header>顶部</header>-->
<router-view name="top"></router-view>
<!-- <section>内容区</section>-->
<router-view></router-view>
<!-- <footer>底部</footer>-->
<router-view name="footer"></router-view>
</div>
</div>
</body>
<script>
let topView = {
template:`<header>
<ul>
<li class="fl" @click="jump('/')">首页</li>
<li class="fl" @click="jump('/news')">新闻</li>
<li class="fl" @click="jump('/sports')">体育</li>
</ul>
</header>`,
methods: {
jump(url){
this.$router.push(url)
}
}
}
let asideView = {template: `<aside>侧边栏</aside>`}
let homeView = {template: `<section>【首页】内容区</section>`}
let newsView = {template: `<section>【新闻】内容区</section>`}
let sportsView = {template: `<section>【体育】内容区</section>`}
let homeFooterView = {template: `<footer>【首页】内容区</footer>`}
let newsFooterView = {template: `<footer>【新闻】内容区</footer>`}
let sportsFooterView = {template: `<footer>【体育】内容区</footer>`}
const router = new VueRouter({
routes:[
{
path:"/",
components:{
top:topView,
aside:asideView,
default:homeView,
footer:homeFooterView
}
},
{
path:"/news",
components:{
top:topView,
aside:asideView,
default:newsView,
footer:newsFooterView
}
},
{
path:"/sports",
components:{
top:topView,
aside:asideView,
default:sportsView,
footer:sportsFooterView
}
}
]
})
new Vue({
el:"#vue",
router,
data:{ //响应式数据
},
methods:{ //统一管理自定义函数
},
computed:{ //计算属性
},
watch:{ //单独监听某一个数据变化
},
created(){
},
updated(){ //监听所有的data中的数据
}
})
</script>
</html>
路由的props配置
//作用:让路由组件更方便的收到参数
{
name:'',
path:'',
component:'',
//第一种写法:props值为对象,对象中所有的key-value的组合最终都会通过props传给组件
//props:{a:100}
//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给组件
//props:true
//第三种写法:props值为函数,函数返回的对象中每一组key-value都会通过props传给组件
props(route){
return{
id:route.query.id
}
}
}
新的生命周期钩子
路由组件独有
activated() {
console.log('组件被激活')
}
deactivated() {
console.log('组件失活')
}
路由守卫
//1.全局路由守卫
const router = new Router({
routes: [{
path: '',
redirect: '/home' //缺省时候重定向到/home
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/',
name: 'Home',
component: Home,
children: [{
path: 'home', //子嵌套路由 无须加/
name: 'Index',
component: () => import('@/components/Index') //懒加载组件
}
]
},
]
})
//全局前置路由守卫
router.beforeEach((to,from,next)=>{
if(判断条件){next()}
})
//全局后置路由守卫
router.afterEach((to,from)=>{
})
export default router
//2.独享路由守卫
const router = new Router({
routes: [{
path: '',
redirect: '/home' //缺省时候重定向到/home
},
{
path: '/login',
name: 'Login',
component: Login,
//独享路由守卫
beforeEnter((to,from,next)=>{
next()
})
},
{
path: '/',
name: 'Home',
component: Home,
children: [{
path: 'home', //子嵌套路由 无须加/
name: 'Index',
component: () => import('@/components/Index') //懒加载组件
}
]
},
]
})
export default router
//3.组件内路由守卫
// 通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next) {
}
// 通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next) {
}