ArthurWangCN / notepad

reading notepad
0 stars 2 forks source link

Vue2.x:路由 #21

Open ArthurWangCN opened 1 year ago

ArthurWangCN commented 1 year ago

1. Vue-Router 的懒加载如何实现

非懒加载:

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

(1)方案一(常用):使用箭头函数+import动态加载

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

(2)方案二:使用箭头函数+require动态加载

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

(3)方案三:使用webpack的require.ensure技术,也可以实现按需加载。 这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。

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

路由的hash和history模式的区别

Vue-Router有两种模式:hash模式和history模式。默认的路由模式是hash模式。

1.hash模式

简介: hash模式是开发中默认的模式,它的URL带着一个 #,例如:www.abc.com/#/vue,它的hash值就是 #/vue

特点:hash值会出现在URL里面,但是不会出现在HTTP请求中,对后端完全没有影响。所以改变hash值,不会重新加载页面。这种模式的浏览器支持度很好,低版本的IE浏览器也支持这种模式。hash路由被称为是前端路由,已经成为SPA(单页面应用)的标配。

原理: hash模式的主要原理就是 onhashchange() 事件:

window.onhashchange = function(event){
    console.log(event.oldURL, event.newURL);
    let hash = location.hash.slice(1);
}

使用onhashchange()事件的好处就是,在页面的hash值发生变化时,无需向后端发起请求,window就可以监听事件的改变,并按规则加载相应的代码。除此之外,hash值变化对应的URL都会被浏览器记录下来,这样浏览器就能实现页面的前进和后退。虽然是没有请求后端服务器,但是页面的hash值和对应的URL关联起来了。

2.history模式

简介: history模式的URL中没有#,它使用的是传统的路由分发模式,即用户在输入一个URL时,服务器会接收这个请求,并解析这个URL,然后做出相应的逻辑处理。

特点: 当使用history模式时,URL就像这样:abc.com/user/id。相比hash模式更加好看。但是,history模式需要后台配置支持。如果后台没有正确配置,访问时会返回404。

API: history api可以分为两大部分,切换历史状态和修改历史状态:

虽然history模式丢弃了丑陋的#。但是,它也有自己的缺点,就是在刷新页面的时候,如果没有相应的路由或资源,就会刷出404来。

如果想要切换到history模式,就要进行以下配置(后端也要进行配置):

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

3. 两种模式对比

调用 history.pushState() 相比于直接修改 hash,存在以下优势:

hash模式和history模式都有各自的优势和缺陷,还是要根据实际情况选择性的使用。

ArthurWangCN commented 1 year ago

如何获取页面的hash变化

(1)监听$route的变化

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

(2)window.location.hash读取#值

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

ArthurWangCN commented 1 year ago

$route 和$router 的区别

ArthurWangCN commented 1 year ago

如何定义动态路由?如何获取传过来的动态参数?

(1)param方式

路由定义:

//在APP.vue中
<router-link :to="'/user/'+userid" replaceid>用户</router-link>    

//在index.js
{
   path: '/user/:userid',
   name: 'users',
   component: User,
},

路由跳转:

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

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

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

参数获取: 通过 $route.params.userid 获取传递的值

(2)query方式

路由定义:

//方式1:直接在router-link 标签上以对象的形式
<router-link :to="{path:'/profile',query:{name:'why',age:28,height:188}}">档案</router-link>

// 方式2:写成按钮以点击事件形式
this.$router.push({
  path: "/profile",
  query: {
      name: "kobi",
      age: "28",
      height: 198
  }
});

路由跳转:

// 方法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)

获取参数:通过 $route.query 获取传递的值

ArthurWangCN commented 1 year ago

Vue-router 路由钩子在生命周期的体现

一、Vue-Router导航守卫

有的时候,需要通过路由来进行一些操作,比如最常见的登录权限验证,当用户满足条件时,才让其进入导航,否则就取消跳转,并跳到登录页面让其登录。 为此有很多种方法可以植入路由的导航过程:全局的,单个路由独享的,或者组件级的

1. 全局路由钩子

vue-router全局有三个路由钩子;

具体使用∶

beforeEach(判断是否登录了,没登录就跳转到登录页)

router.beforeEach((to, from, next) => {  
    let ifInfo = Vue.prototype.$common.getSession('userData');  // 判断是否登录的存储信息
    if (!ifInfo) { 
        // sessionStorage里没有储存user信息    
        if (to.path == '/') { 
            //如果是登录页面路径,就直接next()      
            next();    
        } else { 
            //不然就跳转到登录      
            Message.warning("请重新登录!");     
            window.location.href = Vue.prototype.$loginUrl;    
        }  
    } else {    
        return next();  
    }
})

afterEach (跳转之后滚动条回到顶部)

router.afterEach((to, from) => {  
    // 跳转之后滚动条回到顶部  
    window.scrollTo(0,0);
});

2. 单个路由独享钩子

beforeEnter 如果不想全局配置守卫的话,可以为某些路由单独配置守卫,有三个参数∶ to、from、next

export default [    
    {        
        path: '/',        
        name: 'login',        
        component: login,        
        beforeEnter: (to, from, next) => {          
            console.log('即将进入登录页面')          
            next()        
        }    
    }
]

3. 组件内钩子

beforeRouteUpdate、beforeRouteEnter、beforeRouteLeave

这三个钩子都有三个参数∶to、from、next

注意点,beforeRouteEnter组件内还访问不到this,因为该守卫执行前组件实例还没有被创建,需要传一个回调给 next来访问,例如:

beforeRouteEnter(to, from, next) {      
    next(target => {        
        if (from.path == '/classProcess') {          
            target.isFromProcess = true        
        }      
    })    
}

二、Vue路由钩子在生命周期函数的体现

1. 完整的路由导航解析流程(不包括其他生命周期)

2. 触发钩子的完整顺序

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

3. 导航行为被触发到导航完成的整个过程

ArthurWangCN commented 1 year ago

Vue-router跳转和location.href有什么区别

ArthurWangCN commented 1 year ago

params和query的区别

用法:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是 this.$route.query.name 和 this.$route.params.name 。

url地址显示:query更加类似于ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示

注意:query刷新不会丢失query里面的数据,params刷新会丢失 params里面的数据。

ArthurWangCN commented 1 year ago

对前端路由的理解

在前端技术早期,一个 url 对应一个页面,如果要从 A 页面切换到 B 页面,那么必然伴随着页面的刷新。这个体验并不好,不过在最初也是无奈之举——用户只有在刷新页面的情况下,才可以重新去请求数据。

后来,改变发生了——Ajax 出现了,它允许人们在不刷新页面的情况下发起请求;与之共生的,还有“不刷新页面即可更新页面内容”这种需求。在这样的背景下,出现了 SPA(单页面应用)。

SPA极大地提升了用户体验,它允许页面在不刷新的情况下更新页面内容,使内容的切换更加流畅。但是在 SPA 诞生之初,人们并没有考虑到“定位”这个问题——在内容切换前后,页面的 URL 都是一样的,这就带来了两个问题:

为了解决这个问题,前端路由出现了。

前端路由可以帮助我们在仅有一个页面的情况下,“记住”用户当前走到了哪一步——为 SPA 中的各个视图匹配一个唯一标识。这意味着用户前进、后退触发的新内容,都会映射到不同的 URL 上去。此时即便他刷新页面,因为当前的 URL 可以标识出他所处的位置,因此内容也不会丢失。

那么如何实现这个目的呢?首先要解决两个问题:

从这两个问题来看,服务端已经完全救不了这个场景了。所以要靠咱们前端自力更生,不然怎么叫“前端路由”呢?作为前端,可以提供这样的解决思路: