为了追求更好的用户体验,Vue提供了vue-router插件,可以在不改变url的同时改变界面的某些部分,这样用户就可以拥有更好的体验。
SPA前端路由的原理:锚点替换,再加上innerHTML内容的替换
hashchange事件
当url的片段标识符改变时,便会触发hashchange事件
window.addEventListener('hashchange',function(){
console.log(location.hash)
switch(location.hash){
case '#/login':
document.getElementById("contain").innerHTML = '<h1>登录界面</h1>';
break;
case '#/regiest':
document.getElementById("contain").innerHTML = '<h1>注册界面</h1>';
break;
}
})
直接在导航栏上改变,这样你就可以直观的认识hashchange事件
前端路由使用
- 引入vue-router
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
- 安装插件
Vue.use(VueRouter)
- 创建路由对象
var router = new VueRouter()
- 配置路由对象
routes: [
{path: '/login', component: Login, name: 'Login'},
{path: '/music', component: Music, name: 'Music',meta:{isChecked: true}}
]
- 将配置好的路由对象关联到vue实例中
router: router //在new Vue()中
- 指定路由改变局部的位置 ==》留坑
var App = {
template: `<div>
<router-link :to= "{name: 'Login'}">登录去</router-link>
<router-link :to= "{name: 'Music'}">音乐</router-link>
<router-view></router-view>
</div>`
}
使用这五部,就可以很快的建立一个简单的前端路由。
<script>
window.onload = function(){
Vue.use(VueRouter)
var router = new VueRouter({
routes: [
{path: '/', redirect: {name:'login'}},
{name: 'login', path: '/login', component: Login = {
template: `
<div>
我是登陆页面
<router-view></router-view>
</div>`,
created: function(){
this.isLogin = true
}
}, children: [
{name: 'login.women', path: 'women', component: Women = {
template: `
<div>
这里是女士登陆界面
</div>`
},meta:{isChecked: true}
},{name: 'login.men', path: 'men', component: Men = {
template: `
<div>
这里是男士登陆界面
</div>`
}},
]
},{name: 'register', path: '/register/:name', component: Register = {
template: `
<div>
我是注册页面
</div>`
}
},{name: 'music', path: '/music', component: Music = {
template: `
<div>
欢迎访问音乐界面
</div>`
},meta:{isChecked: true}
}
],
})
router.beforeEach(function(to, from, next){
// console.log(to)
// console.log(from)
if(!to.isChecked){
next()
} else {
if(isLogin){
next()
}else{
console.log('请登陆后再进来!!!')
}
}
})
var App = {
template: `<div>
i am App
<hr>
<router-link :to="{name: 'login', query: {id: '11'}}">login</router-link>
<router-link :to="{name: 'register', params: {name: 'abc'}}">register</router-link>
<router-link :to="{name: 'music'}">music</router-link>
<router-link :to="{name: 'login.women'}">login.women</router-link>
<router-link :to="{name: 'login.men'}">login.men</router-link>
<hr>
<router-view></router-view>
</div>`
}
new Vue({
el: '#app',
template: '<app/>',
components: {
app: App
},
router: router
})
}
</script>
在routes部分,更加常写的方法是
<script>
window.onload = function(){
Vue.use(VueRouter);
var router = new VueRouter({
routes: [
{path: '/login', component: Login, name: 'Login',
childern:[
{path: 'women', component: Women, name: 'login.Women'},
{path: 'men', component: Women, name: 'login.Men'}
]},
{path: '/regiest', component: Regiest, name: 'Regiest'}
]
})
var Women = {
template: `<div>
欢迎女士登录。。。。。
</div>`
}
var Login = {
template: `<div>
我是登录页面,下面是子路由页面
<router-view></router-view>
</div>`
}
var Regiest = {
template: `<div>
我是注册页面,下面是子路由页面
<router-view></router-view>
</div>`
}
var App = {
template: `<div>
<router-link :to= "{name: 'login.Women'}">女士登录去</router-link>
<router-link :to= "{name: 'login.Men'}">男士注册去</router-link>
<router-view></router-view>
</div>`
}
new Vue({
el: '#app',
router: router,
components: {
app: App,
},
template: '<app/>'
})
}
</script>
这样分开写,代码更加的清楚,各个部分也很容易看得清楚,但是不知道为什么我用第二种方法写,控制台一直提示我name没有定义,但是我检查了好几遍,也没有发现什么错误,试了试第一种方法就可以正常运行了,如果有人遇到和我一样的问题,你可以试试第一种方法。
在router-link中传递数据
传递数据有两种方法:query和params
{name: 'login', path: '/login', component: Login},
{name: 'register', path: '/register/:name', component: Register}
<router-link :to="{name: 'login', query: {id: '11'}}">login</router-link>
<router-link :to="{name: 'register', params: {name: 'abc'}}">register</router-link>
接受时query方面没有什么要求,但是params要求在path的部分为name留下接受的地方,可以在created里面console.log查看二者
created: function(){
console.log(this.$route.query)
console.log(this.$route.params)
}
一定要注意的是query是用path来引入,而params是由name来引入的,params和path不能共存,所以
this.$route.push({
path: '/login',
params: {
name: 'login.men',
code: 100011
}
})
像这样写的话就是错误的,修改的办法就是将上面的path改为name就可以了。
嵌套路由
所谓嵌套路由就是在连接的路由里面还有一个路由,有时候人们说用单页应用开发多页应用就是指嵌套路由。
- router-view中包含router-view
- 路由规则中存在子路由
这种情况我们就说是嵌套路由,在第一大段代码和第二大段代码里都有路由嵌套,这里就不再说了。
路由meta元数据
路由meta元数据是对于路由规则是否需要验证权限的配置
<script>
window.onload = function(){
Vue.use(VueRouter)
var router = new VueRouter({
routes: [
{name: 'login', path: '/login', component: Login = {
template: `<div>
欢迎登陆访问
</div>`,
created: function(){
isLogin = true
}
}},{name: 'music', path: '/music', component: Music = {
template: `<div>
欢迎听音乐
</div>`
},meta: {isChecked: true}}
]
})
var isLogin = false
router.beforeEach(function(to, from, next){
if(!to.meta.isChecked){
next()
}else{
if(isLogin){
next();
}else{
next({name: 'login'})
//next(false)
alert('请先登陆再访问')
}
}
})
var App = {
template: `
<div>
<router-link :to= "{name: 'login'}">登陆处</router-link>
<router-link :to= "{name: 'music'}">听音乐</router-link>
<router-view></router-view>
</div>`
}
new Vue({
el: '#test',
router: router,
components: {
app: App,
},
template: '<app/>'
})
}
</script>
meta和name是同一级别的,可以称为全局路由访问,用来做条件,判断是否放行
router.beforeEach里面的三个参数就指的是到哪里去,从哪里来,是否同通行。
next有三种使用方法:
- next() 直接放行
- next(name: ‘login’)返回到login页面
- next(false)取消用户导航,这时候用户体验好像没有点击一样
编程导航
编程导航指的是跳到某一指定锚点并显示页面
常用的方法有:
this.$router.push({name: 'login', query: {id: 1}})
this.$router.go(1|-1)
this.$router.replace('/music')
go中1表示向前返回,-1表示向后方返回,一般配合浏览器的history使用
push和replace很相似,但是在历史记录中push相当于
1 ----- 2 ----- 3
但是replace相当于
1 -------3
直接将2替换为3,而不是前进到3中,所以此时,浏览器的历史记录中就会少一条记录
push方法和中的to方式是一样的,本质上运行是会自动在内部运行push方法。