vue|关于路由☕☕的几种知识点

141 阅读5分钟

1、 路由懒加载

1.非懒加载

import List from '@/components/list.vue'
const router = new VueRouter({
  routes: [
    { path: '/list', component: List }
  ]
})

2.箭头函数+import【懒加载】

const List = () => import('@/components/list.vue')
const router = new VueRouter({
  routes: [
    { path: '/list', component: List }
  ]
})

3.箭头函数+require【懒加载】

const router = new Router({
  routes: [
   {
     path: '/list',
     component: resolve => require(['@/components/list'], resolve)
   }
  ]
})

4.webpack

// r就是resolve
const List = r => require.ensure([], () => r(require('@/components/list')), 'list');
// 路由也是正常的写法  这种是官方推荐的写的 按模块划分懒加载 
const router = new Router({
  routes: [
  {
    path: '/list',
    component: List,
    name: 'list'
  }
 ]
}))

6.为什么需要路由懒加载

如果没有配置懒加载,打包后的组件都在同一个文件bundle.js中,这样不管访问哪个界面,都要下载bundle.js 文件,这是资源的浪费,也会造成前端页面响应速度慢的问题

7.懒加载的优点

(1)将路由对应的组件打包成一个个js文件

(2)只有路由被访问时,才会加载对应的组件

8.实例

const Home=()=>import('../components/Home')
const HomeNews=()=>import('../components/HomeNews')
const HomeMessage=()=>import('../components/HomeMessage')

const About=()=>import('../components/About')
const User=()=>import('../components/User')

5个懒加载组件,对应打包后的5个js文件

其中:app.xxx代表自己写的代码;ventor代码引入的第三方文件;manifest代表支持的底层代码;

image (5).png

2、hash和history的区别

hash模式

1.简介

image (6).png

hash是开发的传统模式,他的url中带着#,如上所示hash值就是#title

2.特点

hash值会出现在url中,但是不会出现在http请求中,对后端完全没有影响,所以改变hash值,不会向后端发请求,只会对前端自己的路由生效

3.原理

// hash模式的原始就是onhashchange事件
window.onhashchange = function(event){
  console.log(event.oldURL, event.newURL);
}

onhashchange事件的好处就是hash值变化时,不会向后端发送请求,window就能监听事件的变化,然后加载响应的代码,除此之外,hash值的变化会被浏览器记录下来,所以就可以实现前进和后退操作,使用hash模式把页面的hash值和对应的url关联起来了

history模式

1.简介

history的url中没有#,它使用的是传统的路由分发模式,即一个用户输入url时,服务器就会接受这个请求,做出相应的逻辑处理

2.特点

history需要后台配置支持,如果后台没有对应的访问地址,就出报404

3.原理

history模式利用了html5提供的2个新的API pushState()和replaceState()修改浏览器的历史状态 利用forward()、back()、go()三个方法完成切换历史状态

4.API

pushState()、replaceState()、forward()、back()、go()

对比

1.获取2个值

hash——即地址栏URL中的#符号。比如在 http://localhost:8080/#/donate 中,hash的值就是#/donate,我们在浏览器中可以通过BOM中的变量获取到

image (7).png

history——history模式即是通过在host之后,直接添加斜线和路径来请求后端的一种URL模式。我们把demo中的vue-router调整到了history模式,获取window.location如下图:

image (8).png

2.是否向后台传参

在hash模式中,我们刷新一下上面的网页,可以看到请求的URL为http://localhost:8080/, 没有带上#/donate,说明在hash模式下,#后面的内容是不会包含在请求中的,只是会被前端浏览器利用

image (9).png

在history模式中,刷新一下网页,明显可以看到请求url为完整的url,url完整地请求了后端

image (10).png

3.是否刷新界面

调整到hash模式,在页面中通过 window.location.hash = '#/trans' 做了一个hash的跳转,我们可以看到浏览器的Network中没有进行新的请求,也就是说修改了hash参数,前端浏览器不会重新请求后端,只是会对前端自己的路由生效。

在history模式中,页面中通过 window.location.pathname = '/trans' 做一个路由跳转。可以看到,在对pathname重新赋值后,页面产生了新的请求trans。说明在history模式下,通过修改pathname直接修改路由,浏览器是会重新产生一个新的请求的。

image (11).png

3、如何获取页面的hash值

1.watch监听

// 监听,当路由发生变化的时候执行
watch: {
  $route: {
    handler: function(val, oldVal){
      console.log(val);
    },
    // 深度观察监听
    deep: true
  }
},

2.window.location.hash

window.location.hash 的值可读可写,读取来判断状态是否改变,写入时可以在不重载网页的前提下,添加一条历史访问记录。

4、$route$router 的区别

$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数

111.png

$router 是“路由实例”对象包括了路由的跳转方法,钩子函数等。

image (12).png

💡思考

push、replace区别

可以把路由router想象成一个访问记录栈,push是向栈中加入一个新记录,replace是替换掉栈顶 一般情况下要前进后退的浏览器管理,基本选择push,一些特殊的情况需要用到replace 比如,有一个授权页,用户在按流程操作时,某一步需要授权,是直接跳到授权页,授权页提交授权请求,直到成功授权后,跳到流程中的下一步操作的地址。此处,授权请求的那页面应该用replace去替换掉自身的访问记录,防止用户跳到下一步流程后按后退键回退到授权页,而导致重复授权。

5、路由动态传参的方式

params 方式

1.路由定义

//在index.js
{
   path: '/user/:uname',
   component: User,
},

2.跳转方式

// 方法1:
<router-link :to="{ name: 'users', params: { uname: wade }}">按钮</router-link

// 方法2:
this.$router.push({name:'users',params:{uname:wade}})

// 方法3:
this.$router.push('/user/' + wade)

3.获取参数

this.$route.params.uname

4.特点

但是params有一个特点就是刷新界面,参数会丢失,如果不想丢失就要在path后面加上参数,那就会url中显示参数,和query没有区别

query方式

1.路由定义

{
     path: '/user',
     name: 'user',
     component: user
}

2.路由跳转

// 方法1:
<router-link :to="{ name: 'users', query: { uname: james }}">按钮</router-link>

// 方法2:
this.$router.push({ name: 'users', query:{ uname:james }})

// 方法3:
<router-link :to="{ path: '/user', query: { uname:james }}">按钮</router-link>

// 方法4:
this.$router.push({ path: '/user', query:{ uname:james }})

// 方法5:
this.$router.push('/user?uname=' + jsmes)

3.获取参数

this.$route.query.uname

4.特点

params和 name 的传参方式,相当于post,强制刷新参数会丢失,url中不显示参数 query和path的传参方式,相当于get,刷新参数不会丢失,url中会显示参数

5.区别

引入:

query用name或者path引入,params用name引入

刷新:

query刷新不会丢数据,params刷新会丢数据

请求:

query想到于get请求,看得见参数,params相当于post请求,看不见参数

总结

1.手写完整的 path:

    this.$router.push({path: `/user/${userId}`});
 
    获取参数:this.$route.params.userId

2.用 params 传递【刷新不丢失,路由配置了:userId】:

    this.$router.push({name:'user', params:{userId: '123'}});
 
    获取参数:this.$route.params.userId
 
    url 形式:url 不带参数,http:localhost:8080/#/user/123

3.用 params 传递【刷新丢失】:

    this.$router.push({name:'user', params:{userId: '123'}});
 
    获取参数:this.$route.params.userId
 
    url 形式:url 不带参数,http:localhost:8080/#/user

4.用 query 传递:

    this.$router.push({path:'/user', query:{userId: '123'}});
 
    获取参数:this.$route.query.userId
 
    url 形式:url 带参数,http:localhost:8080/#/user?userId=123

6、路由生命周期

路由守卫分类

1.全局路由

全局路由:beforeEach、afterEach、beforeResolve

// 1.前置守卫
router.beforeEach((to, form, next) => {
    // to:到哪里去
    // form:从哪里来
    // next() 跳转,一定要调用
    // next(false) 不让走
    // next(true) 继续前进
    // next('/login') 走到哪里
    next({ path: '/detail/2', params: {}, query: {} }) //带参数的
    if (to.path === '/login' || to.path === '/reg') {
        next(true)
    } else {
        if (没有登录过) {
            next('/login')
        } else {
            next(true)
        }
    }
})
// 2.后置守卫
router.afterEach((to, form) => {
    // 全局的后置守卫
})

2.组件内路由

组件内路由:beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave

// 组件内部钩子
beforeRouteEnter(to, from, next) {
    // ...
    // 不能获取组件实例this
    //   因为当守卫执行前,组件实例还没有创建
}
beforeRouteUpdate(to, form, next){

}
beforeRouteLeave(to, form, next){
    // 导航离开时,调用
    //  可以访问组件实例this
}

3.路由独享

路由独享:beforeEnter

// 3.路由独享守卫
{
    path: '/user',
        component: User,
            beforeEnter: (to, from, next) => {
                // ...
                console.log('路由独享守卫');
                if (Math.random() < .5) {
                    next()
                } else {
                    next('/login')
                }
            }
}

路由生命周期

路由导航、keep-alive、和组件生命周期钩子结合起来的,触发顺序,假设是从a组件离开,第一次进入b组件

beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。

beforeEach:路由全局前置守卫,可用于登录验证、全局路由loading等。

beforeEnter:路由独享守卫

beforeRouteEnter:路由组件的组件进入路由前钩子。

beforeResolve:路由全局解析守卫

afterEach:路由全局后置钩子

beforeCreate:组件生命周期,不能访问tAis。

created;组件生命周期,可以访问tAis,不能访问dom。

beforeMount:组件生命周期

deactivated:离开缓存组件a,或者触发beforeDestroy和destroyed组件销毁钩子。

mounted:访问/操作dom。

activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。

执行beforeRouteEnter回调函数next。

参考👀

www.jianshu.com/p/535ce23e3…

blog.51cto.com/u_15127544/…