Vue(router)

279 阅读3分钟

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步骤

  1. 创建路由组件
  2. 配置路由映射关系
  3. 使用路由通过和
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)=>{
    
})