Vue2

Vue2 的生命周期钩子有哪些?数据请求放在哪

  • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
  • activated、deactivated、errorCaptured
  • 数据请求一般放在 mounted 里面
  • 如果放在created里,会在后端SSR(Server-Side Render)和前端都执行一次,不符合预期
  • updated钩子触发太过频繁,一般数据请求只触发一次

Vue2 组件间通信方式

  1. 父子通信:使用props和事件进行通信
  2. 爷孙通信:
  • 使用两次父子组件通信
  • 使用provide和inject
  1. 任意组件:使用eventBus = new Vue()
  • 主要API是eventBus.$on(监听) 和 eventBus.$emit(触发)
  • 缺点:事件多了容易乱,难以维护
  1. 任意组件:使用Vuex通信(Vue3可用Pinia代替Vuex)

Vuex用过吗?如何理解

  1. 描述:Vuex是一个专为vuejs应用程序开发的 状态管理模式 + 库
  2. 核心概念:
    1
    2
    3
    4
    5
    6
    a. store是一个大容器,包含以下所有内容
    b. State 用来读取状态,带有一个 mapState 辅助函数
    c. Getter 用来读取派生(计算)状态,带有一个mapGetters 辅助函数
    d. Mutation 用于同步提交状态变更(写),带有一个mapMutations 辅助函数
    e. Action 用于异步变更状态(写),但它提交的是mutation,而不是直接变更状态
    f. Module 用来给store划分模块,方便代码维护

VueRouter用过吗?如何理解

描述:官方推荐的路由,适用于做单页面应用

进行导航,传递to来指定链接,最终会呈现一个带有href属性的a标签

router-view

路由出口,路由匹配到的组件将在这里渲染

嵌套路由

在一个路由下还分有子路由,他们分别又对应不同的组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const routes = [
{
path: '/',
redirect: '/account'
},
{
path: '/account',
component: account,
// 使用children属性,实现子路由
// 子路由的path前不带'/',否则永远以根路径开始请求
children: [
{
path: 'login',
component: Login
},
{
path: 'register',
component: Register
}
]
}
]

Hash模式 && History模式

前端路由:找到与地址相匹配的组件并将它渲染出来

本质:改变浏览器地址(更新视图)但不向服务器发出请求

有两种方法可以做到:

  • hash模式 利用URL中的hash(“#”)
  • history模式 利用 history.pushState() API来完成URL跳转而无须重新加载页面,但是需要后端将所有前端路由都渲染同一页面,且IE8以下的浏览器不支持

两种模式的对比:

  • Hash模式只可以更改 # 后面的内容(也就是字符串),History模式可以通过 API 设置任意的同源 URL
  • Hash模式无需后端配置且兼容性好,History模式在用户手动输入地址或者刷新页面的时候会发起URL请求,后端需要配置 index.html页面 用于匹配不到静态资源的时候

路由守卫实现:权限控制 & 加载进度

  • 在系统路由跳转前做权限校验
  • Vue-Router提供了两个钩子函数,前置守卫beforeEach 和 后置守卫afterEach,前者在路由跳转前触发,后者在路由跳转后触发
  • 注册全局路由守卫。当路由跳转时,路由守卫按顺序异步解析执行,只有当所有守卫resolved才会进入resolved状态,否则处在pending状态中

    1
    2
    3
    4
    5
    6
    7
    8
    const router = new VueRouter({ ... })

    router.beforeEach((to,from,next) => {
    // ...
    })
    router.afterEach((to,from,next) => {
    // ...
    })
  • 守卫的回调函数接受三个参数

  1. to:即将进入的路由,一个Route对象
  2. from:正要离开的路由,一个Route对象
  3. next:一个Function,回调函数内部必须执行该方法,令守卫进入resolved状态
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    router.beforeEach((to,from,next) => {
    // 鉴权操作
    const token = getToken()

    if(token) {
    if(to.path === '/login'){
    next('/')
    } else {
    // 其他鉴权操作,如资源是否可访问
    let menus = store.getters['user/menus']
    if(menus.includes(to.path)) {
    next()
    } else {
    next({path: '/403', replace: true}) // replace 替换当前路由,避免用户后退操作导致重复跳转
    }
    }
    } else {
    if(whiteList.includes(to.path)){
    next()
    } else {
    next(`/login?redirect =${to.path}`)
    }
    }
    })

参考文章巧用Vue-Router路由守卫实现路由权限控制和加载进度

路由懒加载

将不同路由对应的不同组件分割成不同的代码块,然后当路由被访问时才加载对应的组件

1
2
3
// 用动态导入代替静态导入
// 将 import UserDetails from './views/UserDetails' 替换成
const UserDetails = () => import('./views/UserDetails')

Vue2 如何实现双向绑定?

  1. 一般使用 v-model/.sync 实现,v-model实际上是v-bind:valuev-on:input的语法糖
    a. v-bind:value => 绑定value,当data改变就去更新UI
    b. v-on:input => 监听input事件,当input被触发就去更新data
  2. 上面两个单向绑定如何实现
    a. 前者通过 Object.defineProperty API 给data的每个属性创建 getter 和 setter,用于监听data的改变。当data发生改变,就会安排UI变
    b. 后者通过 template compiler 给DOM添加事件监听,当DOM input的值变了就会去修改data

参考文章vue的双向绑定原理及实现

0%