Vue router是Vue.js官方的路由管理器,它和Vue.js的核心深度集成,让构建单页面变得易如反掌。(spa/single page web application)
路由是什么
路由是用来分发请求的
路由的三种模式 (hash/history/memory)
都是前端路由,目的是改变url不刷新页面
hash
hash模式(锚点)本质上是改变window上的location.hash
任何时候都可以用hash做前端路由,缺点seo不友好(服务器收不到hash,也就是#号之后的内容)
history
history模式使用的html5中的history interface 中新增的 pushState() 和 replaceState() 方法。
后端将所有前端路由都渲染到同一页面
histroy模式相对更灵活,但是如果页面刷新会真的会向服务器发起请求,如果没有对应资源会404,用重定向可以解决这个问题
memory
hash实现前端路由
const app = document.querySelector('#app')//找到挂载点
//将来需要分发的内容
const div1 = document.createElement('div')
div1.innerHTML = '1'
const div2 = document.createElement('div')
div2.innerHTML = '2'
const div3 = document.createElement('div')
div3.innerHTML = '3'
const div4 = document.createElement('div')
div4.innerHTML = '4'
//表驱动编程
const routeTable = {
'1': div1,
'2': div2,
'3': div3,
'4':div4
}
//
function route(app) {
let number = window.location.hash.substr(1)//获取url参数<a标签参数>
number = number || 1
//#获取界面
let div = routeTable[number]//拿到对应内容
if (!div) {//如果没找到分发到404
div = document.querySelector('#div404')
}
div.style.display = 'block'
//展示界面,插入前移除其它节点
if (app.children.length > 0) {
app.children[0].style.display = 'none'
document.body.appendChild(app.children[0])
}
app.appendChild(div)
}
route(app)//init
//监听路由变化
window.addEventListener('hashchange', () => {
route(app)//
})
history实现原理
const app = document.querySelector('#app')
const div1 = document.createElement('div')
div1.innerHTML = '1'
const div2 = document.createElement('div')
div2.innerHTML = '2'
const div3 = document.createElement('div')
div3.innerHTML = '3'
const div4 = document.createElement('div')
div4.innerHTML = '4'
const routeTable = {
'/1': div1,
'/2': div2,
'/3': div3,
'/4': div4
}
function route(app) {
let number = window.location.pathname
if (number === '/') {
number = '/1'
}
//#获取界面
let div = routeTable[number]
if (!div) {
div = document.querySelector('#div404')
}
div.style.display = 'block'
//展示界面
if (app.children.length > 0) {
app.children[0].style.display = 'none'
document.body.appendChild(app.children[0])
}
app.appendChild(div)
}
//获取到所有 用来做路由的a标签类
const allA = document.querySelectorAll('a.link')
//创建一个回调函数用来监听路由变化
route(app)
const stateChange = (params) => {
console.log(`当前路径:${params}`)
route(app)
}
//遍历a标签对象添加事件
allA.forEach(item => item.addEventListener('click', (e) => {
e.preventDefault()//阻止默认跳转
const params = item.getAttribute('href')//每一次点击获取href对应的参数
window.history.pushState(null, `page ${params}`, params)//将参数添加到url后面
stateChange(params)//回调state监听变化
}))
memory实现路由
主要通过localStorage储存路由信息
//其他代码基本与上面一致只需更换route里的内容和监听click内容
let number = window.localStorage.getItem('url')
if (!number) {number = '/1'}
allA.forEach(item => item.addEventListener('click', (e) => {
e.preventDefault()//阻止默认跳转
const params = item.getAttribute('href')//每一次点击获取href对应的参数
window.localStorage.setItem('url',params)
stateChange(params)//回调state监听变化
}))
使用vue-route步骤
- 创建路由组件
- 配置路由映射关系
- 使用路由通过和
import Vue from 'vue'
improt Router from 'vue-router'
Vue.use(Router)
const routes = [
{
path:'/index',
component:()=>import('@/pages/index/template.vue')
//懒加载,也可以写成直接引入组件
}
]
const router = new Router({
routers,
})
//
在vue组件中可以通过<router-link to="/"></router-link>去访问路由
<router-viwe />显示当前路由对应的页面
重定向
const routers = [
{
path:'/',
redirect:Index//组件名
}
]
切换模式
const router = new Router({
routers,
mode:'history',
//默认hash模式
activeClass:'active',
//修改活跃router-link标签class属性
})
router-link参数
<router-link to="/home" tag="button">首页</router-link>
//tag:也可以是li
<router-link to="/home" replace>首页</router-link>
//关闭返回操作
<router-link to="/home" active-class="active">首页</router-link>
//修改活跃按钮的class名称,方便修改css样式
触发路由跳转
methods:{
homeClick(){//点击事件名称
this.$router.push('/home')
this.$router.replace('/home')//
}
}
动态路由
const routers = [
{
path:'/user/:userId',
redirect:user//组件名
}
]
computed:{
userId{
return this.route.params
}
}
<roter-link :to=" `user/${userId}`">个人主页</router-link>
拿到上面computed计算属性返回的参数
路由嵌套
实际应用界面,通常由多层嵌套的组件组合而成。 比如,我们 “首页”组件中,还嵌套着 “登录”和 “注册”组件,那么URL对应就是/home/login和/home/reg。
//定义子路由
const routers = [
{
path:'/home',
component:Home,
children:[
{
path:'login',//子组件不需要加/
conponent:()=>import('/src/components/login'),
},
{
path:'rigister',//子组件不需要加/
conponent:()=>import('/src/components/rigister'),
}
]
}
]
我们需要在父组件中加上router-link 和router-view
<div>
<h2>首页</h2>
<router-link to="/home/login">登录</router-link>
<router-link to="/home/rigister">注册</router-link>
<router-view></router-view>
</div>
路由传参
传参主要有两种方式params和query
params的类型:
配置路由格式:/router/:id
传递的方式:在path后面跟上对应的值
传递后形成的路径:/router/123,/router/abc
第一种方式请看动态路由
qurey传参
query
<!--父组件传递参数-->
<router-link :to="{paht:'/profile',query:{name:'why',age:18}}">首页</router-link>
<!--子组件接受参数-->
<h2>我是子组件<h2>
<h2>{{$route.query.name}}</h2>
点击跳转并且传递参数
vue模板
<button @click="profileClick">个人信息</button>
methods:{//定义点击事件,跳转并且传参
profileClick(){
this.$router.push({
path:'/profile',
query:{
name:'why',
age:18
}
})
}
}
子组件接收参数
<h2>我是子组件<h2>
<h2>{{$route.query.name}}</h2>
导航守卫
全局导航守卫监听路由跳转,当发生跳转的时候做某些事
router.beforeEach((to,from,next)=>{
})