记2023.02.08前端面试

121 阅读8分钟

参考链接

1.vue2和vue3区别

参考链接

1.双向数据绑定

vue2是通过ES5的Object.definedProperty()对数据进行劫持结合发布-订阅模式来实现双向数据绑定;

vue3是通过ES6的Proxy API对数据代理来监听属性的变化,从而实现对数据的监控。

Proxy优势如下:

  1. Object.definedProperty()只能遍历对象属性进行劫持;Proxy可以劫持整个对象,并返回一个新的对象;
  2. Object.definedProperty()无法监听数组,vue2需要重写数组方法,额外增加set、delete方法;Proxy可以监听数组,不用单独对数组进行特异性操作;
  3. Proxy有多种拦截方法,如deleteProperty、ownKeys等等。
2.生命周期
vue2vue3(setup)描述
beforeCreatesetup()创建实例前
createdsetup()创建实例后
beforeMountonBeforeMountDOM挂载前调用
mountedonMountedDOM挂载后调用
beforeUpdateonBeforeUpdate数据更新之前调用
updatedonUpdated数据更新之后调用
beforeDestroyonBeforeUnmount组件销毁前调用
destroyedonUnmounted组件销毁后调用
3.新增了Composition API

vue2使用Options API,通过定义data,methods,computed,watch等属性与方法,共同处理页面逻辑,当组件变得复杂,导致页面对应属性的列表也会增长,导致组件难以阅读和理解;

vue3推出了Composition API,组件根据逻辑功能来组织,一个功能所定义的所有API放在一起(高内聚,低耦合)

2.nextTick API的作用

Vue在更新DOM时是异步执行的,当数据发生变化,Vue将开启一个异步更新队列,视图需要等待队伍中所有数据变化完成后,再进行统一更新。

1.使用场景

希望在修改数据后立刻更新DOM结构,可使用nextTick

2.实现原理
  1. 把回调函数放入callbacks等待执行
  2. 将执行函数放到微任务或者宏任务中
  3. 事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调

宏任务包括:setTimeout setInterval Ajax DOM事件

微任务:Promise async/await

微任务比宏任务执行时间早

3.ref和reactive区别

参考链接

  1. ref通过Object.defineProterty()的get和set来实现响应式;reactive通过Proxy来实现响应式,并通过Reflect操作源对象内部的数据
  2. ref多用来定义基本数据类型(也可定义对象,内部会自动通过reactive转为代理对象),而reactive只能用来定义对象数组类型
  3. ref操作需要.value(在模板template中使用时不需要.value,会自动解包),reactive操作数据不需要.value

4.keep-alive作用及参数

参考链接

keep-alive是Vue内置的组件,可以使被包含的组件保留状态,或避免重新渲染。

被包含在keep-alive中创建的组件,会多出两个生命周期的钩子:activated和deactivated:

  1. activated当keep-alive包含的组件再次渲染的时候触发
  2. deactivated当keep-alive包含的组件销毁的时候触发
参数情况

keep-alive可以接收3个属性作为参数进行匹配对应的组件进行缓存

  1. include:包含的组件,可以为字符串,数组以及正则表达式,只有匹配的组件会被缓存
  2. exclude:排除的组件,可以为字符串,数组以及正则表达式,匹配的组件不会被缓存
  3. max:缓存组件的最大值,可以为字符或者数字,控制缓存组件的个数

5.watch和watchEffect区别

参考链接

watch:既要指明监听的属性,也要指明监听的回调。默认是惰性执行(设置immediate:true时为非惰性,页面首次加载时就会执行),监听源可以是具有返回值属性的getter函数,也可以直接是一个ref

watchEffect:不用指明监听哪个属性,监听回调中用到哪个属性就监听哪个属性,会根据其中的属性,自动监听其变化

6.聊一聊虚拟DOM

参考链接

真实的DOM节点,哪怕一个最简单的div也包含这很多属性,操作DOM的代价是昂贵的,频繁操作还会出现页面卡顿,影响用户体验。

虚拟DMO的本质是用树形结构的js对象来描述真实的DOM结构的信息,这个树结构的js对象包含了整个DOM结构的信息。

1.虚拟DOM的优缺点

优点:

  1. 降低浏览器性能消耗,因为js对象的运算速度远大于DOM操作的执行速度
  2. diff算法,减少回流和重绘(触发回流一定会触发重绘)
  3. 跨平台,虚拟DOM本质是js对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如:服务器渲染、weex开发等等

缺点:

  1. 首次显示较慢,首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢
  2. 无法进行极致优化
2.虚拟DOM实现原理
  1. 用js对象结构表示DOM树的结构
  2. 当数据状态变更的时候,重新构造一棵新的对象树,通过diff算法,比较新旧虚拟DOM树的差异
  3. 根据差异,对真正的DOM树进行增删改

7.渲染函数 & JSX

1.渲染函数介绍

在绝大多数情况下,Vue推荐使用模板语法来创建应用,然而某些场景下,我们真的需要用到js完全的编程能力,即使用渲染函数用js构建DOM。

2.渲染函数的基本用法
1.创建Vnodes(虚拟节点)

Vue提供了一个h()函数用于创建vnodes(类型必填,其它参数可选)

import { h } from 'vue'
const vnode = h( 'div', // type
{ id: 'foo', class: 'bar' }, // props
[ 
    /* children */
] )
2.声明渲染函数

使用render选项来声明渲染函数:

import { h } from 'vue'

export default {
    data() {
        return {
            msg: 'hello'
        }
    },
    render() {
        return h('div', this.msg)
    }
}
   

render()函数可以访问同一个this示例,除了返回一个单独的vnode之外,还可以返回字符串或是数组。

3.Vnodes必须唯一

组件树中的vnodes必须是唯一的。

3.JSX/TSX

JSX是js的一个类似XML的扩展,在jsx文件中,有如下写法(使用大括号来嵌入动态值)

const vnode = <div>hello</div>

const vnode = <div id={dynamicId}>hello, {name}</div>

8.vue3如何设计公共方法

参考链接

  1. main.js文件中:app.config.globalProperties添加
  2. main.js文件中:app.mixin添加

9.vuex如何设计

参考链接

1.基本定义

Vuex是专为Vue.js应用程序开发的状态管理模式+库,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

使用场景:在中大型单页面应用中,需要考虑组件外部管理状态

2.五个核心概念
  1. state:vuex的基本数据,用来存储变量,定义我们所需要管理的数组、对象、字符串等
  2. getters:从基本数据(state)派生的数据,相当于state的计算属性,getter会接收state作为第一个参数,而且getter的返回值会根据它的依赖被缓存起来,只有getter中的依赖值(state中的某个需要派生状态的值)发生改变的时候才会被重新计算
  3. mutations:提交更新数据的方法,必须是同步的,每个Mutation都有一个字符串的事件类型(type)和一个回调函数(handler),state作为第一个参数,提交载荷作为第二个参数,执行回调函数方法:store.commit
  4. actions:action类似于mutation,不同在于:action提交的是mutation,而不是直接变更状态;action可以包含任意异步操作。action通过store.dispatch方法触发
  5. modules:模块化vuex,每一个模块拥有自己的state、mutation、action、getter,使得结构清晰,便于管理
3.store目录结构
|--modules
   |--user.js
|--getters.js
|--index.js

index.js文件如下:

import { createStore } from 'vuex'
import user from './modules/user'
import getters from './getters'
const store = createStore({
  modules: {
    user
  },
  getters
})

export default store

modules/user.js文件如下:

const user = {
  state: {
      userInfo: getStore({
          name: 'userInfo'
        }) || {}
  },
  actions: {},
  mutations: {}
}
export default user

getters.js文件如下:

const getters = {
    userInfo: state => state.user.userInfo
}
export default getters
4.pinia和vuex区别
  1. pinia是轻量级的,体积小,适用于中小型应用;vuex是重量级的,适用于大规模、复杂的项目
  2. pinia没有mutations,只有state, getters, actions(同步、异步)
  3. pinia没有modules配置,每一个独立的仓库都是defineStore生成的

10.vue中的mixin混入

mixin(混入),来分发vue组件中的可复用功能,其本质是一个js对象,可以包含我们组件中任意功能选项,如data、components、methods、created、computed等等

var myMixin = {
    created: function() {
        this.hello();
    },
    methods: {
        hello: function() {
            console.log('hello world');
         }
    }
}

组件通过mixins属性调用mixin对象

Vue.component('componentA', {
    mixins: [myMixin]
})

当组件存在与mixin对象相同的选项的时候,进行递归合并的时候组件的选项会覆盖mixin的选项;当相同选项为生命周期钩子的时候,会合并成一个数组,先执行mixin钩子,再执行组件的钩子