⚠️⚠️传送门⚠️⚠️
寒冬期前端准备总结---JS篇
寒冬期前端准备总结---浏览器篇
寒冬期前端准备总结---服务器和网络篇
寒冬期前端准备总结---CSS篇
[寒冬期前端准备总结---框架篇]
寒冬期前端准备总结---算法篇
技术选型:考虑项目、团队、框架发展程度和生态等问题
react-native和native和H5
* 页面布局灵活度:H5 > react-native(flex) > native
* 内存:native < react-native/h5;rn/h5内存包含框架大小,可优化
* 更新成本:H5 < react native < native,h5随时更新,rn可以部分热更新,native跟版本
* 用户体验:native > react native > h5
react native的UI组件为原生应用的一致,跨平台且有热更新能力
react native的热更新(jsbundle的拆分和加载原理)
- react-native-update插件校验app启动时是否有新版本可以下载
- react-native-code-push 在rn中配置热更新
- Vue和React对比
**相同**
* 两者都只是JS的UI框架,路由和状态管理等功能都是和框架分离的组件;数据的单向流动(单向下流绑定)
* 虚拟DOM:改变实际的DOM状态花销远大于对一个JS对象的改变,计算新旧虚拟DOM的效率取决于diff算法的性能
* 都提供模块化
**不同**
* 使用jsx语法(在js中写html);Vue使用HTML模板系统,便于原生项目迁移
* state对象在react应用中时不可以直接改变的,需要使用setState方法异步更新状态;vue中的data参数都是数据的直接保存者,可以直接改变
* vue的组件可以全局注册、局部注册;react是import在模版中按需引用
* react更适合大型应用和更好的可测试性
* vue实例实现了事件接口,方便通信,小型项目可以不使用状态管理
* 数据更新时,vue会从根节点渲染整个虚拟DOM,而react会从调用setState的这个组件开始渲染子虚拟DOM
生命周期:
* vue:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
* react:
getDefaultProps
getInitialState
~~(componentWillMount)~~
componentDidMount
shouldComponentUpdate
~~(componentWillUpdate)~~
** getDerivedStateFromProps** 新增
**render**
**getSnapshotBeforeUpdate** 新增
componentDidUpdate
~~ (componentWillUnmount)~~
componentUnmounted
- React的setState机制
* 每一次的setState调用会进入到react的state的更新队列中,react会对这个队列做合并处理也就是说setState的key值相同时会被合并
* 通过addEventListener和setTimeOut等回调方法中的setState会被同步执行同步更新;在react原生方法OnClick、onChange或者生命周期中的setState方法会被react的state的更新机制合并后最后批量更新。
this.setState({count: state.count + 1});
this.setState({count: state.count + 1});
// 等同于
Object.assign({count: state.count + 1}, {count: state.count + 1});
// 被合并只执行最后一次的set
- RN和flutter
RN中通过NativeModules调用原生定义的模块化的方法,实现通信;
flutter是偏服务端语言的语言,一个无关UI的SDK
- React V16的改动
* 删除了WillMount WillReceiveProps WillUpdate三个周期
* react V17 开启异步渲染模式:组件的渲染可以被打断,避免造成渲染过长,页面无法交互等问题,比如不同的事件处理同时对数据更新,会造成渲染冲突,实现异步渲染的机制保证每一次的更新都能被捕捉到
* WillMount并不能保证渲染时数据已经请求完成,避免首屏渲染空白问题接口请求应该放在constructor
* 增加getDerivedStateFromProps静态方法:用来监听新的props和setState以及强制重新渲染,返回新的state对象或者null
* 增加getSnapshotBeforeUpdate用在DidUpdate之前,render之后,可以保证此时读取的DOM状态与更新后的相同
- react组件类型
* pure component纯组件,不会带副作用,具体理解就是:shouldComponentUpdate不能重写,组件直接根据props数据的变化来判断是否刷新视图,基本类型的数据改变会重新渲染,引用类型的数据只要引用地址不变就不会触发视图更新,可以用来解决react的渲染问题
* react函数式组件没有生命周期,纯返回dom,接收props参数,且新出的react hook增加只能在函数组件中使用的state功能
- vue 中图片存放目录
* assets文件夹中的图片会被打包成base64的js文件,需要require引入相对路径(CommonJS)或者import(ES6)进来
* static文件夹中的图片不会,可以直接使用
- vue的computed和watch
* computed: 依赖基础data数据,根据基础数据计算得到的新数据,当基础数据没有变动时,会从缓存获取结果
* watch:监听data数据的变化,回调处理,可以设置immediate(初始值处理)和deep
- vue组件通信
// 父向子
组件属性 + props
// 子向父
this.$emit + @自定义事件
this.$parent.event 直接调用父组件方法
// 兄弟
bus.$emit + bus.$on
- vue子父组件的生命周期执行顺序(由外到内,再由内到外)
* 加载渲染:父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMounted -> 子mounted -> 父mounted
* 子组件更新:父beforeUpdate -> 子beforeUpdate -> 子Updated -> 父Updated
* 父组件更新:父beforeUpdate -> 父Updated
* 销毁:父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
- vue的data为函数的原因
当组件被多次重用时,如果数据都指向同一个data对象,会存在数据被同步修改(对象存储引用地址)
- vue的props
prop属性的值可以进行类型设定,让父组件传递到子组件时类型更准确
- vue生命周期的实际应用
* beforeCreated:loading
* created: 异步请求
* mounted: 获取DOM节点 ,可以进行视图操作,但是不一定所有的字组件会被挂载,可以使用$nextTick回调处理
- 状态管理对比(flux、redux、vuex)
flux的核心思想是数据和逻辑永远是单向流动的,三部分:
* dispatcher负责分发时间
* store负责保存数据,同时响应事件并更新数据
* view负责订阅store中的数据,并使用这些数据渲染相应的页面
redux和vuex都是基于flux思想实现的
* redux只有一个全局的store,内置State对象,更新的逻辑也不是在store中,而是在reducer函数中
* redux没有dispatcher的概念,使用reducer函数(返回一个新的state对象)
* vuex基于redux,使用mutation代替redux的reducer
react的mobx核心是通过action出发state的变化,进而触发state的衍生对象,使用更灵活,observable、autorun、action等装饰器
**redux**
- 核心对象:store
- 数据存储:state
- 状态更新提交接口:dispatch
- 状态更新提交参数:带type和payload的action
- 状态更新计算:reducer
- 限制:reducer必须是纯函数,不支持异步
- 特性:支持中间件
store dispatch action ;action 调用reducer修改state(同步);subscribe注册订阅事件
**vuex**
- 核心对象:store
- 数据存储:state
- 状态更新提交接口:commit
- 状态更新提交参数:带type和payload的mutation
- 状态更新计算:mutation handler
- 限制:mutation handler为非一步方法
- 特性:支持带缓存的getter,用于获取state经过某些计算后的值
store dispatch actions(异步); actions commit mutation(同步); mutation set state
- Virtual DOM和diff算法
渲染视图的实现原理是diff+特定的DOM更新,和直接操作原生DOM的性能对比取决于节点数以及diff算法
当小数量的数据更新是Virtual DOM的性能可能会高于直接操作原生DOM(全部重新渲染)
* diff算法区别
react和vue(V3.0会更新diff算法⚠️)都是同级比较,新旧NodeTree的头尾四个指针,两两对比。
react是逐层比较,一层之后比下一层;vue是一层中的某个节点,先对比完节点下的所有子节点;也因此,react的渲染是根据当前组件为根节点渲染整个节点数,而vue是只重新渲染更新的节点,精准度更高
附 https://www.jianshu.com/p/398e63dc1969
- webpack
构建流程
1 找到入口文件
2 并针对不同的模块使用不同的loader,对模块进行解析,并递归该模块中用到的模块,进行解析
3 解析完模块后,得到模块的内容以及他们之间的依赖关系
4 根据入口文件和模块之间的依赖关系,组装成包含多个模块的chunk
5 把chunk转化成单独的js文件加入到输出列表中
6 根据输出配置,把文件内容写入到文件系统中
loader在module.rules中配置,用于为模块的解析增加规则
plugin在plugins数组中配置,用于扩展webpack的功能,比如html文件压缩等
webpack的热更新原理:应用在运行状态下,不重新刷新就能更新、增加、移除模块的机制
* 通过热更新接口向webpack声明模块是否能够热更新,以及更新的前后进行的处理
* 接受热更新,需要开发者自己再模块被替换之前清除或保留必要的数据、状态;并在模块被替换后恢复之前的数据和状态
* 在使用vue、react开发时,vue-loader插件已经帮我们做掉了这些事情
- webpack优化前端性能
- 压缩代码
- 提取公共代码
- 修改静态资源的路径为CDN上对应的路径
- dll:把不常更改的js等静态文件提前打包生成CDN连接,以外链脚本的方式引用到应用中
打包配置sourcemap:用于线上代码debug
- 数据绑定
单向绑定:model的更新引起view视图的变化
双向绑定:同时view的更新引起model的数据更新,例如input组件的输入、checkbox变更等
* MVC:
model包括数据格式、数据的基本操作方法
view即视图
controllor包括注册事件,监听用户交互,调用model方法更新数据
**model驱动view**
* MVVM:
model只包括数据
view即视图
view-model包括处理用户交互、事件处理,model数据处理
**view和model没有直接关联,VM中间处理**
数据绑定的方法
* 发布者-订阅者模式(backbone.js):使用vm.set(‘property’, value)的方式更新数据
* 脏值检查(angular):脏值检测对比数据有无更新,通过setInterval定时轮询检测数据变化,在特定的事件触发时进入脏值检测
* 数据劫持(vue):通过Object.defineProperty()来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。Object.defineProperty(object,property,des)在对象上添加或修改一个属性,des包括writable、value、get等
vue的数据绑定:设置数据绑定的入口,劫持Vue实例中的data,使用Observer监听数据的变更,并对Vue实例的el对象,通过Compile进行解析模版指令,最后利用Watcher来将前两者关联起来
* Observer:使用**Object.defineProperty**覆写data属性的setter、getter,实现对数据变更的监听,收集依赖,通过set扩展调用notity触发更新
* Compile:解析模版指令,在每个指令对应的节点中实例化订阅者Watcher,绑定更新函数,数据变更时通知更新函数,进而变更视图
* Watcher:往data属性中添加订阅者watcher,data属性通知数据变化时,调用自身的update方法,触发Compile中绑定的回调,更新视图
附:vue3.0的数据劫持使用es6 proxy