Vue3 面试题 (2023-09-26更新)
Vue3 对比 Vue2 做了那些改进?
1. 响应式系统
- vue2 中使用的 Object.defineProperty 实现的响应式,劫持整个对象,递归遍历所有属性,给每个属性添加 getter 和 setter
- vue3 中使用的 Proxy 实现的响应式
2. 编译阶段
- Fragment
Vue3 增加了一个 Fragment
抽象组件,本身不会被渲染到 DOM 中。主要的作用是:模板里面不再需要创建唯一根节点。可以直接放同级标签
- 静态节点提升
Vue2 中,每次数据更新重新渲染时,静态节点,也会在虚拟 DOM 树中重新创建一次。执行 diff 算法来比较旧的虚拟 DOM 树和新的虚拟 DOM 树,通过对静态节点打上标记,来优化 diff 的过程
Vue3 中,是通过将静态节点提升到渲染函数之外,渲染函数内部只会保持对静态节点的引用。这样重新渲染时,并不会创建静态的虚拟节点,从而减少了不必要的计算和操作,提高了渲染性能
下面用一段代码说明,假设我们有如下模板:
<div>
<p>static text</p>
<p>{{ title }}</p>
</div>
在没有静态提升的情况下,它对应的渲染函数是:
function render() {
return (
openClock(),
createClock('div', null, [
createVNode('p', null, 'static text'), // 静态节点被重新创建
createVNode('p', null, ctx.title, 1)
])
)
}
有了静态提升的情况:
const hoist1 = createVNode('p', null, 'text')
function render() {
return (
openBlock(),
createBlock('div', null, [
hoist1, // 静态节点引用
createVNode('p', null, ctx.title, 1)
])
)
}
3. 源码体积
- Vue3 中移除了一些不常用的 API,整体体积变小了
- 使用的函数方法,如 ref、reactive、computed 等,只有再用到的时候才会进行打包
Vue3 有哪些变化?
- 响应式系统
用 Proxy 代替 Object.defineProperty 重构了响应式系统,可以监听到数组下标的变化,对象属性的变化
- 生命周期
用 setup 代替了 beforeCreate 和 created 这两个生命周期
- 指令
- 新增指令 v-memo 可以缓存 html 模板
- 插槽 slot 和 slot-scope 屬性已被废弃,用 v-slot 代替
- 内置 API
移除了 Vue.filter、Vue.mixin、Vue.set 和 Vue.delete
- 编译
组件模板中不再需要唯一根节点,不需要根元素包裹
- 组合式 API
新增 Composition API 可以更好的组织代码,同一功能的代码不至于像以前一样太分散。Vue2 中可以用 minxin 来实现复用代码,但也会存在一些问题,比如方法或属性名会冲突,代码来源不明显等
组合式 API 有什么优缺点?
优点:
- 提供了灵活性和逻辑复用方式,相关的逻辑代码组织在一起,方便了阅读
缺点:
- 对于初学者或已经习惯于响应式 API 的开发者来说,切换到组合式 API 可能需要一些时间来熟悉用法和设计思想
- 组合式 API 提供了更强大的灵活性,开发者可以自由的组织代码和逻辑处理。但这可能会导致代码结构不一致,代码更难以理解和维护
选项式 API 有什么优缺点?
优点:
- 易于学习和使用,写代码的位置已经固定好
缺点:
- 当组件变得复杂时,同一个功能的逻辑被拆分,关注点会变得很分散
- 相似的逻辑代码不便于复用
选项式 API 和 组合式 API 的区别?
- 选项式 API:Vue2 中的
Options API
就是选项式 API。在一个文件内,只能固定使用data
、methods
、computed
等选项来组织代码。在项目变得复杂时,一个功能的属性和方法会存在文件的各个地方,很分散,变的越来越难维护。使用 mixin 重用共用代码,也会有命名冲突,数据来源不清晰的问题 - 组合式 API:Vue3 中的
Composition API
就是组合式 API。通常把一个功能所定义的属性、方法放在一起,可以更灵活的组织逻辑。解决了选项式 API 不好拆分和重用的问题
Vue3 响应式原理 和 Vue2 的区别?
Vue2
数据响应式是通过 Object.defineProperty
劫持属性,在数据变化时发布消息给订阅者,触发相应的监听回调,这其中存在几个问题:
- 初始化数据需要递归遍历对象所有
key
,性能不好 - 通知更新需要维护大量的
dep
实例和watcher
实例,占用额外的内存 - 无法监听到数组元素的变化,只能通过重写数组方法
- 动态新增、删除对象属性无法拦截,只能通过特定
set
、delete
API 代理 - 不支持
Map
、Set
等数据结构
在Vue3
中为了解决这些问题:
- 使用原生
proxy
代理,可以监听到数组下标的变化,对象属性的变化,多达 13 种拦截方法 - 新增数据结构全部支持
- 对象嵌套属性只代理第一层,只有访问某个属性的时候,才会递归代理下一级的属性
- 也不需要维护特别多的依赖关系
Object.defineProperty 和 Proxy 的区别?
Object.defineProperty
是es5
的方法。Proxy
是es6
的方法Object.defineProperty
不能监听到数组下标变化和对象新增属性。Proxy
可以Object.defineProperty
是劫持对象属性。Proxy
是代理整个对象Object.defineProperty
是递归遍历对象属性,只能监听单个属性。Proxy
对象嵌套属性运行时递归,用到的时候再进行代理,也不需要维护特别多的依赖关系,性能提升很大,且首次渲染更快Object.defineProperty
会污染原对象,修改时是修改原对象。Proxy
是对原对象进行代理并会返回一个新的代理对象,修改的是代理对象Object.defineProperty
不兼容 IE8。Proxy
不兼容 IE11
谈谈你对 setup 函数的了解?
- setup 会在 beforeCreate() 之前执行
- setup 不能使用 this
- setup 内部的属性、方法,必须 return 暴露出来。否则没法使用
- setup 内部数据不具有响应式
- setup 不能调用生命周期相关函数,但生命周期函数可以调用 setup 内的函数
setup 方法和 setup 语法糖的区别?
// 方法
setup(props.context) {}
// 语法糖
<script setup></script>
ref 和 reactive 区别?
- 定义数据
ref
通常用来定义基本类型数据,也可以传入引用类型的数据,内部会通过reactive
转化为代理对象,只是不推荐这么做
reactive
用来定义引用类型数据 - 实现原理
ref
通过Object.defineProperty
来实现数据代理
reactive
使用proxy
实现数据代理,并且通过reflect
操作原对象内部的数据 - 操作数据
ref
在 js 中,获取和修改数据需要.value
,template
中不需要
reactive
不需要
reactive 可以创建基本类型的(单一值)响应式数据么?
不可以传入基本类型数据,如果传入则不会返回proxy
对象,由于reactive
是基于proxy
实现响应式的,如果返回的不是proxy
对象,则该数据不会具有响应式
怎么重置 reactive 数据?
- 第一种
import { reactive } from 'vue'
class InitFormData {
userName: string = ''
age: number = 0
}
let formData = reactive(new InitFormData())
// 重置数据
Object.assign(formData, new InitFormData())
- 第二种
import { reactive } from 'vue'
const initFormData = () => {
return {
userName: '',
age: 0
}
}
let formData = reactive(initFormData())
// 重置数据
Object.assign(formData, initFormData())
- 第三种
import {reactive} from 'vue'
const initFormData = {
userName: '',
age: 0
}
const _initFormData = Object.assign({}, initFormData)
let formData = reactive{formData: initFormData}
// 重置数据
formData.formData = Object.assign({}, _initFormData)
打包
说说 wepack 和 vite 的区别?
- 打包过程
webpack
会对项目进行全量构建,首先会分析各个模块之间的依赖关系,形成一个依赖树,然后打包成bundle.js
文件,将打包后的代码在本地服务器进行渲染。这样存在的问题就是,随着模块的增多,打包体积变大,影响热更新的速度vite
不需要向webpack
一样先打包再渲染。它可以直接启动本地服务器进行渲染,它利用浏览器原生的 ES 模块加载功能(现代浏览器本身支持ES-Module
),会自动向依赖的模块发出请求,按需动态编译显示(每个模块可以独立的进行编译和缓存)
- 热更新方面
webpack
当改动了某个模块时,需要将模块以及依赖的模块全部编译一次vite
只需让浏览器重新请求该模块
结果:通过比较可以看出vite
在启动的时候不需要打包,不用分析模块之间的依赖关系,浏览器请求某个模块时,再对模块进行编译。当项目越复杂,模块越多的情况,vite
越优于webpack
怎么开启 gzip?
1. Nginx 在线压缩
通过 CPU 负载换取宽度,客户端请求静态资源时,通过 Nginx 在线压缩 gz 文件返回浏览器,浏览器自动解压缩(支持 gzip 的浏览器)
gzip on;
gzip_min-length 1K;
gzip_buffers 4 16K;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
2. Koa2 开启 gzip
node 直接对源文件进行 gzip 压缩,返回压缩后的资源
[koa-compress]https://www.npmjs.com/package/koa-compress
2.1 安装 koa-compress 中间件
npm install koa-compress --save
2.2 配置 koa-compress 中间件
const app = require('koa')()
const compress = require('koa-compress')
const options = { threshold: 2048 }
app.use(compress(options))
3. webpack 开启 gzip 压缩
服务端进行压缩,如果压缩的文件比较大,压缩的这个过程也比较耗时,体验也不是太好
可以在前端打包的时候,直接打包成 .gz
的文件
3.1 安装 compression-webpack-plugin
npm install compression-webpack-plugin --save-dev
3.2 Vue.config.js 配置
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
configureWebpack: {
plugins: [
new CompressionPlugin({
algorithm: 'gzip', // 使用 gzip 压缩
test: /\.(js|css|html)?$/i, // 匹配文件名
filename: '[path][base].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)
minRatio: 0.8, // 默认 0.8,压缩率小于 1 才会进行压缩
threshold: 10 \* 1024, // 超过 10K 的文件会进行压缩
deleteOriginalAssets: false // 是否删除未压缩的源文件。如果希望提供非 gzip 的资源,可不设置或设置为 false
})
]
}
}
3.3 nginx 配置
gzip_static on;
4. vite 开启 gzip 打包
4.1 安装
npm i vite-plugin-compression
4.2 vite.config.js 配置
import viteCompression from 'vite-plugin-compression'
const plugins = [
vue(),
vueJsx(),
viteCompression({
threshold: 10 * 1024 // 对大于 10K 的文件进行压缩
})
]
Vue3 面试题 (2023-09-26更新)的更多相关文章
- 梦想Android版CAD控件(安卓CAD二次开发,安卓CAD控件)2023.02.26更新
下载地址:https://www.mxdraw.com/ndetail_40240.html1. 增加willBeReturnStart事件2. 增加使用OpenGL缓存3. 优化界面响应时间4. 修 ...
- MxDraw云图平台(H5在线CAD) 网页CAD,网页查看CAD图纸,2023.02.26更新
下载地址:https://www.mxdraw.com/ndetail_40241.html1. 梦想服务上传CAD文件格式转换,增加转换后的文件例表返回2. 增加绘制图片Tag功能3. 修改在一些图 ...
- 前端面试题总结——HTML(持续更新中)
前端面试题总结--HTML(持续更新中) 1.什么是HTML? HTML:HyperText Markup Language超文本标记语言 2.XHTML和HTML有什么区别 HTML是一种基本的WE ...
- VS Code 调教日记(2022.6.26更新)
VS Code 调教日记(2022.6.26更新) 基于msys2的MinGW-w64 GCC的环境配置 下载并安装msys2 到路径...msys2安装路径...\msys64\etc\pacman ...
- 2023.2.26【模板】扩展Lucas定理
2023.2.26[模板]扩展Lucas定理 题目概述 求\(\binom {n}{m} mod\) \(p\) 的值,不保证\(p\)为质数 算法流程 (扩展和普通算法毫无关系) 由于\(p\)不是 ...
- Web前端面试题整合,持续更新【可以收藏】
饭后闲来无事,把这几年带学生用的一些面试题整合一下,供上!拿走,不客气!应付一般公司的二面基本上是够用了.祝你早日拿到心仪的offer. css相关 1. 万能居中 1.margin: 0 auto; ...
- java 面试题整理(不定期更新)
一.Java基础 1.Java面向对象的三个特征与含义 三大特征是:封装.继承和多态. 封装是指将某事物的属性和行为包装到对象中,这个对象只对外公布需要公开的属性和行为,而这个公布也是可以有选择性的公 ...
- iOS面试题总结(持续更新)
过段时间打算跳槽,找了一些面试题来做,在这里做个总结方便review,希望能对要面试的童鞋有帮助. 以下为面试题: 运行以下代码会有什么结果 NSString *str1 = @"str1& ...
- Redis 面试题 - 收藏版 (持续更新、吐血推荐)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- C#逻辑面试题汇总【不断更新中】
(1)产生本月的月历,参考样式: 1 2 3 4 5 6 SU MO TU WE TH FR SA 01 02 03 04 05 06 07 08 09 10 11 12 13 14 ...
随机推荐
- 树状数组 java模板(纯代码)
public class TrieNums { int n; /*Nums start from 0*/ int[] storage; /*TrieNums index start from 1*/ ...
- Unreal Engine4 GPU崩溃或3D设备丢失的解决方案
起因: Unreal Engine4 在渲染时报错GPU崩溃或3D设备丢失 解决办法: regedit 打开注册表 在以下2个路径下 新建 DWORD(32-bit) Value 命名为 TdrD ...
- 25. Socket与粘包问题
1. Socket概念 Socket允许应用程序通过它发送或接收数据,对其进行像对文件一样的打开.读写和关闭等操作,从而允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信.Socket ...
- USB协议详解第6讲(USB描述符-端点描述符)
1.USB描述符 USB描述符有设备描述符.标准配置描述符.接口描述符.端点描述符.字符串描述符,HID设备有HID描述符.报告描述符和物理描述符.今天主要是学习USB端点描述符的组成. 2.端点描述 ...
- 深度学习卷积、全连接层、深度可分离层参数量和FLOPs计算公式
来源 卷积: 输入尺寸 ,卷积核的大小为 * ,输出的尺寸大小为 参数量 (1)不考虑bias:(2)考虑bias: FLOPs (1)不考虑bias 解释:先计算输出的中一个元素需要的计算量, ...
- plt.gca()坐标轴移动
我们可以看到绘制出来的图有四个边框,我们通过gca()对坐标轴进行一些简单处理,代码如下. import torch import torch.nn.functional as F import ma ...
- 2022年最新数据库调查报告:超八成DBA月薪过万,你拖后腿了吗?
数据库管理员属于IT行业高薪职业的一种,近几年关于数据库管理员的薪资统计文章也层出不穷,那么当前,DBA们的薪资究竟到达了怎样的水平呢? 墨天轮数据社区发布最新<2022年墨天轮数据库大调查报告 ...
- iOS比较枚举NSOrderedSame NSOrderedAscending NSOrderedDescending使用小结
项目开发中偶然间看到这种比较枚举,之前没注意过,仔细研究了一下结果还挺有意思,我们可以用升降序相等来帮助理解比较结果. NSString 两个字符串的比较,用 a compare:b 来比,得出的结果 ...
- 018 人生中第一次用 Python 写的一个小程序_猜年龄(再次强调,重视基础)
博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...
- 比赛题解 更新ING
CF Codeforces Round #750 (Div. 2) (水题.组合数学.双指针+搜索.构造.dp.dp) Codeforces Round #747 (Div. 2) (水题.水题.埃筛 ...