vue-router
在研究vue的路由前,先说说什么是路由
路由是指 当地址栏的改变时页面做出改变
路由分为前端路由 和 后端路由
- 后端路由就是指访问和相应了,地址栏是百度,当前的路由就是百度,如果跳转到淘宝,路由就是淘宝,后端路由会带来页面刷新
- 前端路由是自己通过API改变地址栏的内容,再判断地址栏的值修改页面的内容,最重要的是前端路由是可以被浏览器的
history
记录,history记录的意思就是点击返回是返回上一个路由,到了最后一个路由关闭页面,完美的模拟后端路由的效果
为什么要用前端路由,前端路由带来了什么
- 漂亮的路由地址,去看看网易云音乐的网页版地址和哔哩哔哩的网站地址
- 减少页面请求,只需要ajax修改数据,只需要第一次进入请求一次页面数据就行,称为单页面应用,简称
SPA
起步
如果没有安装vue-router
自己去看开发文档
- 先npm下载
- 然后在创建配置文件和基础配置文件的模板
- 最后在main.js引入
vue的路由是用什么API history
和hash
window.history
// 方法有
history.pushState
history.replaceState
window.hash
// 方法有
window.hashchange = function(){ ... }
这两个路由对应的就是vue-router的配置的参数mode
,默认是hash
new Router({
mode: 'history', // history 和 hash
routes: [{
path: '/',
component: () => import('page/home'),
children: [{
path: 'list',
component: () => import('page/list'),
}]
},{
path: '/404',
component: () => import('page/error')
}]
})
mode的参数有什么区别
history模式,这是个新API,所以兼容性不好,地址栏没有【#】,哔哩哔哩就是没带【#】号的,更好看,而且在微信的分享等地方是禁止用【#】的
hash模式,地址栏带有【#】,网易云音乐就是带【#】号的,我不喜欢这个模式
routes参数是一个数组,这个数组需要学的有子路由的配置和参数路由的配置
在配置之前了解一下vue怎么把路由进行显示出来的,看路由的component
参数,这个是指当有人访问这个路由,我就给他看哪个页面的传参,参数是一个页面的地址,首先找到这个路径下的地址,是 .vue后缀文件,打开后是这样的
<template>
<div>
<div>HOME</div>
<div>{{ msg }}</div>
</div>
</template>
<script>
export default {
// 这个name是无意义的,只是为了好看,是代码规范,但不是代码规定
name: 'HOME',
data(){
return {
msg:"helloword"
}
}
}
</script>
<style scoped>
// 这是写样式的
// scoped属性的意思是这里的样式只服务这个vue文件
</style>
那这个文件被显示到哪里了呢
vue格式文件显示在<router-view />
标签里,这也是子路由的配置理解,比如上面的路由配置,当路由是【/】时,页面显示的是home.vue这个文件,如果路由是【/404】就显示的是error.vue文件,home和error是展示在同一个<router-view />
里的,因为他们属于同一级,把这个<router-view />
理解成div的innerHTML也行,所以当我们要给路由【/】添加子路由时,就需要在home.vue文件里放置一个<router-view />
标签,如下
<div>我是HOME.vue</div>
<router-view />
当路由是【/】时,我们会看到我是HOME.vue,看不到<router-view />
,当我们访问【/list】时,<router-view />
会绘制上list.vue文件的代码,就能看到页面显示,我是HOME.vue,我是List.vue,应该很好理解吧
那么问题来了,一级配置,也就是上面的【/】和【/404】是显示在哪个<router-view />
里的,在文件列表有个APP.vue
文件,这个才是一级路由显示的地方,这个文件又显示在哪呢,显示在public文件夹的index.html,打开index.html,会看见一个id为app的div,跟srcipt引入插件的方式一样,vue脚手架最后也只是把vue给new一下,显示到#app里而已,查看main.js
import App from './App'
import store from './store'
import router from './router'
new Vue({
// 这个就是路由
router,
// 这个是vuex
store,
// render渲染,$mount是代表index.html的id
// 即我把App.vue渲染到id为app的div里
render: h => h(App)
}).$mount('#app')
现在应该知道怎么配子路由了吧,接下来参数路由【/:】
new Router({
mode: 'history', // history 和 hash
routes: [{
path: '/:type/:id',
component: () => import('page/type'),
},{
path: '/home/test',
component: () => import('page/ceshi'),
}]
})
上面的路由是要干什么呢,是想实现根据类型和id去返回页面的功能,比如【/book/0001】,是指找一个编号是0001的书,【/movie/123】是找一部编号123的电影,所以我才说前段路由是那么的好看,如果是后端路由应该是【xxx.com/index.html?type=movie&id=123】
在上面有个【/home/test】的配置,如果有人访问这个,会跳转到上面去吗,这是不会的,参数路由是最后被判断的,这个插件是非常智能的,先把固定的判断完,没合适的再去找参数路由
问题来了,我怎么去知道当前的type是什么,id是什么,去到type.vue这个文件里
mounted(){
// 把当前页面的路由打印出来
console.log(this.$route)
// 里面有个params属性,是个对象
// 把这个对象取值判断就行
console.log(this.$route.params)
}
除了params
对象,路由还有一个query
对象,就是正常的问号传参,试一下在地址栏上路由的最后面加上【?name=name&age=age】,就会在路由里看到query对象,很好理解,不写栗子了
总结下路由的配置
路由的配置就是复制黏贴,没什么可玩性,按照文档设置好就行
路由的监控
如果我想根据路由的整体的变化做一些判断呢,如果我想控制一些权限呢
在路由的配置页面加上这个方法
new Router({
mode: 'history', // history 和 hash
routes: [{
path: '/:type/:id',
// 先配置一个title属性,你想写什么属性都行
title: "我是title",
component: () => import('page/type'),
}]
})
下面这个监听的代码可以写在router.js里,最好还是单独拆一个文件出来
router.beforeEach((to, from, next) => {
// 这个to就是当前页面的路由的对象,也就是this.$route
console.log(to)
if(to.title){ document.title = to.title }
else{ document.title = "pdt-1997" }
if(user=="pdt"){
console.log("没资格访问")
// 重定向到主页
next({path:'/'})
}else{
// next一定要有,不然路由不执行
next()
}
})
router.afterEach(() => {
})
怎么跳转
上面的测试都是手动去改路由,再刷新页面
首先就是用标签去跳转,理解为a标签,一般不用标签跳转
<router-link to="/">去到主页</router-link>
<router-link :to="{path:'/index',query:{id:'xxx',name:'xxx'}}">
push和replace
push是把当前路由A存起来,然后跳转B,如果点击返回会到A
replace是跳转B,然后把B替换A,如果点击返回A之前的路由或者关闭页面
this.$router.push({ path:"/it/"+data.id ,query:{ page:this.pageNo }})
this.$router.replace({ path:"/it/"+data.id ,query:{ page:this.pageNo }})
应该注意的点
vue文件的template标签的子标签只能有一个
<template>
<div>
<div>HOME</div>
<div>{{ msg }}</div>
</div>
<div> 如果再加上这个会报错 </div>
</template>
hash的实现原理
<a href="#/home">首页</a>
<a href="#/about">关于</a>
<div id="html"></div>
<script>
window.addEventListener('load',()=>{
html.innerHTML = location.hash.slice(1);
});
window.addEventListener('hashchange',()=>{
html.innerHTML = location.hash.slice(1)
})
</script>
history的实现原理
<a onclick="go(/home)">首页</a>
<a onclick="go(/about)">关于</a>
<div id="html"></div>
<script >
function go(pathname) {
history.pushState({},null,pathname)
html.innerHTML = pathname;
}
window.addEventListener('popstate',()=>{
go(location.pathname);
})
</script>