3、Vue 使用
高级特性:
自定义 v-model:双向数据绑定
1 | <input :value="text" @input="$emit('change', $event.target.value}" /> |
$nextTick:DOM 渲染之后触发,获取最新 DOM 节点
refs
slot
动态组件 :is
异步组件
keep-alive
mixin
问题:
1、Vue 组件如何通信
2、描述组件渲染和更新的过程:
首次渲染 → 更新渲染 → 异步更新
解析模板 → 生成 render→ 生成 vnode→ 触发 patch 和 diff→vnode 更新触发 set→ 更新 dom
- 1、解析模板为 render(vue-loader)
- 2、触发响应式,监听 data 属性 getter setter
- 3、执行 render 函数,生成 vnode,patch 创建新 elem:在执行 render 的时候会触发 getter 收集模板的依赖
- 4、修改 data,触发 setter
- 5、重新执行 render 函数,生成 newVnode,patch(old, new)
3、双向数据绑定 v-model 原理:object.defineProperty
4、Vue 原理
组件化和 MVVM(数据驱动视图)
响应式
vdom 和 diff
模板编译
组件渲染过程
前端路由
4.1 组件化和 MVVM
组件化:其实就是复用,web component
数据驱动视图:
Vue MVVM
React setState
View ⬅️➡️ View Model ⬅️➡️ Model(data)
4.2 Vue 响应式
监听不到以下操作:object.defineProperty 缺陷
新增属性
删除属性
数组方法
还有缺点:
深度监听需要一次性递归,性能比较差
增加 Vue.set 和 Vue.delete
重新定义数组方法
1 | const oldArrayProperty = Array.prototype; |
4.3 虚拟 dom 和 diff
h,vnode,patch,diff,key
为什么出现:
DOM 操作比较耗费性能,js 操作比较快,模拟 DOM 结构,减少变更操作 DOM
js 模拟 DOM:
1 | var vdom = { |
h 函数:
返回一个 vnode
diff 算法:
最早时间复杂度 O(n^3)不可用:遍历树 1,遍历树 2,排序
最右优化到 O(n):
1、只比较同级,不级别比较
2、tag 不同,则直接删除重建,不再深度比较
3、tag 和 key 都相同,认为是相同组件,不再深度比较
当认为是相同组件后,进行 patch 函数:
先判断是否有 text,有则表示没有 children,则直接替换
没有则认为有 children,则进行新旧 children 对比
新 children 有,旧 children 无,则老分支增加 children addVnodes
旧 children 有,新 children 无,则旧分支删除 children removeVnodes
如果都有,则进行 while 循环向中间靠拢对比 updateVnodes
如果遇到相同则再进行 patch
如果都不同,则拿 newKey 来和老的同级别的 key 循环对比看有没有相同的
4.4 模板编译
里边含有指令,插值,js 表达式
js 的 with 语法:打破作用域规则,易读性差,不建议用
vue template complier 将模板编译成 render 函数
执行 render 函数生成 vnode
模板转义:
vue-loader 处理
1 | const template = `<p>{{message}}</p>`; |
写一个 render 函数:
1 | Vue.component('heading', { |
4.5 异步渲染
$nextTick
汇总 data 修改,一次性渲染
减少 DOM 操作,提升性能
4.6 路由
hash:
触发页面跳转,即前进后退
不刷新页面
不提交到 server 端
监听 hashChange
history:
不刷新页面
pushState
popState 只能监听浏览器按钮的前进后退
优势就是 seo
注意:
不触发 popstate 可以重写 pushState 来增加一个钩子
https://segmentfault.com/q/1010000010612425
https://www.xiabingbao.com/post/fe/hash-history-router.html
5、Vue 面试真题
1、必须用 key,不能用 index
diff 算法是通过 tag 和 key 来判断是否相同的
因为如果插入整个 index 都会变化
减少渲染次数,提升渲染性能
2、声明周期及父子组件声明周期
创建阶段(注册实例与挂载): beforeCreate、created、beforeMount、mounted
运行阶段:beforeUpdate、updated
注销阶段:beforeDestroy、destroyed
父子组件:
parent create //先创建父组件间
parent beforeMount
child create //父组件挂载之前创建子组件
child beforeMount
child mounted //先挂载子组件
parent mounted //挂载父组件
3、父子组件如何通信
:on=和他还 this.$emit
this.$parents
eventBus
vuex
Vue.observable()
4、渲染更新过程
5、v-model 的原理
input 的 value 绑定到一个 name
input 增加绑定事件 this.name = event.target.value
data 触发 re-render 更新
6、computed 特点 可扩展原理
缓存,data 不变不会重新计算
提高性能
7、data 为什么是一个函数
export default 最后是一个 class,使用的时候是实例化
放在闭包中,数据不会互相影响
8、将所有 props 传给子组件
$prop
9、自己实现 v-model
10、mixin
11、使用异步组件
加载大组件
路由异步加载
12、何时试用 keep-alive 可扩展原理
缓存组件,不需要重复渲染
多个 tab
13、何时试用 beforeDestory
解绑自定义事件 this.$off
清除定时器
解绑自定义 dom 事件,scroll
14、什么是作用域插槽
15、vuex 的 action 和 mutation 有什么区别
action 要处理异步,mutation 不可以
mutation 做原子操作,每次只有一个事
action 可以整合多个 mutation
16、用 vnode 描述一个 dom 结构
1 | var vnode = { |
17、diff 时间复杂度
由 O(n^3) → O(n)
5.6 vue 常见性能优化
合理使用 v-show 和 v-if:频繁切换使用 v-show
合理使用 computed
v-for 时加 key,避免和 v-if 同时使用:v-for 优先级高,每次 v-for 都要 v-if
自定义事件、DOM 事件及时销毁-导致内存泄漏
合理使用异步组件
合理使用 keep-alive
data 层级不要太深-监听太深执行太多,最好扁平一些
其他:
webpack 层优化
通用性能优化
6.Vue3.0 Proxy
缺点:
兼容性不好,无法 polyfill
优点:
深度监听性能更好
可监听新增、删除属性
可监听数组变化
1、特点:
全部 ts 重写
性能提升,代码量少
调整部分的 api
2、vue2.过时了吗?
vue3 推广还需要时间
vue2 应用广泛,大量项目需要维护
proxy 没有 polyfill
3、Proxy 重写响应式
Reflect.set/Reflect.deleteProperty 会返回设置成功失败
Proxy 的深度监听是再 get 时触发的,而 Object.definedProperty 是最开始递归监听的
1 | function reactive(target = {}) { |
10、Webpack 原理
1、前端代码为何要进行构建和打包?
代码层:体积更小,加载更快,编译高级语法,兼容性,错误检查
工程化:高效的开发环境、统一的构建流程和产出标准,集成公司构建规范,工程化管理
2、module chunk bundle 分别是什么意思,有何区别?
module(源码)-各个源码文件,可以 import 引入的都是 module
chunk(中间态 webpack)-多模块合并成的,entry,import(),splitChunk
bundle(最终)-最终输出的文件
3、loader 和 plugin 区别
loader 模块转换器, plugin 是扩展插件
4、babel 和 webpack 的区别
babel-JS 新语法编译工具 webpack-打包构建工具
5、webpack 如何实现懒加载
import()
6、webpack 常见性能优化
构建+生产的优化
7、babel-runtime 和 babel-polyfill 区别
不会污染全局,适合开发 lib 库,polyfill 会污染全局
8、为何 Proxy 不能被 Polyfill?
因为现有的方法无法模拟
2.1 基本配置
安装配置
dev-server: 用 devServer/whistle
解析 ES6: 用 loader
解析样式 : 用 loader
解析图片文件 : 用 loader
常见 loader 和 plugin
loader 执行顺序:从后往前
1 | module.exports = { |
2.2 高级配置
1、多入口
2、抽离和压缩 css: 默认是打包到 js 中的,需要配置 rule+plugin+optimization 来抽离,mini-css-extract-plugin+压缩 css terser-webpack-plugin 和 optimize-css-assets-webpack
3、抽离公共代码: optimize 中设置 splitChunks
4、懒加载:import(‘’).then(res=>{res 是内容})
5、处理 React 和 Vue:用 babel 配置
1 | module.exports = { |
抽离 css
2.3 优化打包-构建速度
优化 babel-loader:cacheDirectory 开启缓存+明确范围 include/exclude
IgnorePlugin:手动引入中文包,忽略掉这个整体的包
noParse:无第三方依赖,不用解析。noParse: ‘/jquery|lodash/‘
happyPack:开启多进程打包(项目小,不需要,因为进程开销)
ParallelUglifyPlugin:开启多进程压缩 js(项目小,不需要,因为进程开销)
DllPlugin:稳定第三方库,webpack4 性能很好,vue,react 已删除,和 split 也冲突
自动刷新:整个页面刷新,watch 属性设置为 true,watchOptions 设置,
热更新:不刷新,状态不丢失
详细过程
1、使用 express 启动本地服务,当浏览器访问资源时对此做响应。
2、服务端和客户端使用 websocket 实现长连接
3.webpack 监听源文件的变化,即当开发者保存文件时触发 webpack 的重新编译。
- 每次编译都会生成 hash 值、已改动模块的 json 文件、已改动模块代码的 js 文件
编译完成后通过 socket 向客户端推送当前编译的 hash 戳
4.客户端的 websocket 监听到有文件改动推送过来的 hash 戳,会和上一次对比
一致则走缓存
- 不一致则通过 ajax 和 jsonp 向服务端获取最新资源,对 bundle 进行替换
https://blog.csdn.net/chern1992/article/details/106893227
2.4 优化产出代码
小图片 base64 编码
bundle 加 hash
IgnorePlugin
使用 CDN
提取公共代码
懒加载
production:自动压缩代码+删除调试代码+开始 Tree-Shaking(删除无用代码,必须用 es6 module,因为是静态引入)
scope hosting:合并模块,减少函数作用域
2.5 构建流程
2.6 babel
presets:集合了大部分 es6 转 es 的 plugins 的集合
plugins:是 presets 的扩展
按需加载组件:
1 | // 正常 |
默认只是语法转换:例如箭头函数变 function
polyfill:直接用 core.js 和 regenerator,补全 API,例如 Promise, includes 等
按需引入:presets 内 useBuiltIns 配置 usage
污染全局环境
runtime:不会污染全局环境,加了个_Promise, 开发第三方库
12. 项目流程
1、PM 开发过程中增加需求,怎么办?
不能拒绝,走需求变更流程
有规则走规则
没有规则,发起项目组和 leader 重新评审,重新评估
2、项目即将延期,怎么办?
和 leader 汇报
给出原因
给出解决方案
给出排期
3、如何保证项目质量?
符合开发规范
写开发文档
单元测试(看清空)
Code Review
4、我的电脑没问题呀
不要说这句话
让 QA 帮你复现
让 QA 提供设备
12.1 流程细节
1、需求评审:
评估需求背景,目标,收益,合理性
闭环-结果统计实现
开发难度评估,风险点
是否需要其他支持-客户端(调研)
项目优先级
2、技术方案设计
求简,不过度设计
产出文档
找准设计重点-组件怎么设计
组内评审-看有没有公司更好的方法工具(新人)
和 RD 和客户端沟通
发出会议结论(看公司,表示沟通完成)
给排期-预留 buffer(1/4 时间)+并行工作+协作人时间 UI、RD 客户端
3、开发
符合开发规范:git、注释、模块命名
写开发文档
单元测试(看清空)
Mock API
Code Review
4、联调
技术联调
UE 确定视觉效果
PM 确定产品功能
6、测试
提测发邮件,抄送项目组
测试问题要详细记录
有问题及时沟通
7、上线
同步 PM 和项目组
通知 QA 回归
有问题,立即回滚