上一份工作及总结

1. 主播赋能页面迭代

项目介绍:通过引导主播更好地开播来产生业务价值,并收集主播反馈以改善引导服务

项目职责:迭代主播赋能页面,并支持灰度用户使用新版本

描述: 

(1) 使用React来写前端页面组件,Router做前端路由,mobx管理业务数据

      React框架认为一切皆组件,它基于js并提供一种更友好的编程方式。比如用户操作导致需要局部更新页面时,之前是需要直接操作DOM并将需要触发的执行函数绑定到节点的对应属性上,但用React框架的话,可以直接在声明组件的时候将执行函数加到组件的生命周期中,也可以通过hooks来模拟生命周期。组件的更替,我们在jsx中直接切换,剩下的框架会帮我们做,它使用虚拟DOM,以对象的形式来模拟DOM结构,使用diff算法在js对象中进行变更节点的定位,定位好了再执行原生DOM的操作。

      项目是单页面应用,前端路由使用react-router,通过将路由跳转逻辑从后端转移到前端,只需要重新组件而不用执行请求-返回-解析-渲染这一套逻辑。当时做需求是新加了一个页面,就在路由配置中将这个页面组件加到路由配置中,路由配置之前用withRouter这个高阶组件,Route更新后使用useRoutes,只需要配置对象即可配置路由,页面的前进回退跳转使用useNavigate

      mobx与Redux一样都是React状态管理的一种替代方案,React中使用useContext+useState/useReducer,但对于组件内部逻辑侵入较大,让组件开发不专注于组件功能本身,而且当共享数据的两组件不是直接关联还会影响不相关组件。Redux通常是在整个项目外创建一个store来保证使用同一份数据,

(2) 具体用过的hooks

a. useContext 

     接口返回数据需要在React树中不同深度的组件里使用,通过props传递每一层都要写太麻烦,通过redux来做又有些浪费,就使用React里的useContext,通过Provider包裹组件最外层实现数据共享

b. useEffect

     有时需要在组件的不同状态时执行特定操作,在类组件中可以添加到组件的生命周期方法中,在函数组件中需要借助hooks完成,useEffect能对应多个生命周期方法,例如在页面加载完成时发起数据请求,在第二个参数中设置依赖数组为[]即可(借助useState惰性初始化也能做但不推荐),如果需要在某些数据改变时重新执行,将他们加到依赖数组中;退出时的清理操作可以放在回调函数的返回中,组件下一次调用useEffect时会先调用上一次的返回来执行清理,所以一些事件的注册和注销可以分别放到同一个useEffect的回调函数中的函数体和返回值中。但建议按不同的事件分为多个useEffect

c. useState

     维护组件内部状态,返回一个state和更新state的函数,当调用更新函数时,组件会得到已更新的消息重新渲染。useState接收一个参数作为初始值,如果这参数是函数可以做到惰性初始化。更新state的函数也可以接收值或函数,值的话直接更新,使用函数的话可以根据之前的状态更新从而不依赖setState的顺序。setState本身是同步的,但react调度机制会对setState进行优化,延迟执行合并修改,但可以通过不走react调用方式来做到同步修改,例如setTimeout、setInterval、DOM绑定原生事件等。

d. useRef

     绑定DOM结构或是作为在组件生命周期中稳定的存储容器,当需要在父组件上使用子组件时,可以先在父组件通过useRef创建一个ref,传给子组件,在子组件中执行绑定,父组件中便可以通过这个ref的current属性使用子组件的方法

e. useCallback

      缓存组件中的方法,组件更新时,里面的方法会重新声明一次。建议当函数定义需要大量计算,或需要比较引用来确定是否更新时,才使用useCallback

f. useMemo

      缓存组件中的值,不同于useCallback的是会执行其中的回调函数并将返回结果缓存。

g. useReducer

      当组件需要维护的state太多时,对state的修改分散在各处不方便维护,使用useReducer能做到只设置一个状态,通过匹配不同的action来在state上做相应的修改

(3) 使用权限校验支持灰度用户加载新版本

做这个目的是因为运营不确定修改页面带来的收益值不值得让主播去用新页面,就想先在小范围中发布,后续效果好再扩展到全部公会。所以需要区分灰度用户和非灰度用户,然后进入对应页面即可。团队是通过查看用户有没有接口权限,来判断用户是否具有接口对应功能的权限,灰度非灰度也可以认为是一种能否使用新页面的权限,在服务端配置灰度用户,并将当前用户的所有权限传给前端,前端通过js的字符串拼接与匹配查看有没有新页面接口权限,来判断灰度非灰度用户。

(4) 使用浏览器缓存和后端存储限制用户单日反馈次数

因为用户数据和对应的建议每天更新一次,运营是想收集针对这次建议的反馈,所以设定每天只收集一次反馈。主要借助后端存储来判断,并使用前端缓存来在同浏览器不同页面间同步限制,但不同浏览器或无痕模式间用这种方式做不到同步限制,倒是可以借助数据库来做,但这场景比较少见,这次不引入,在后端根据传参判断。

2. 圈人平台开发

项目介绍:以组件方式,为其他平台提供可定制的圈选能力

做了什么:为其他团队提供接入方案,协助开发,并完善使用文档

项目中有遇到过什么问题:

  • 添加请求的取消:支持请求超时取消,并以axios的AbortController处理竞态问题

描述:需求是当用户修改选中的规则时,能展示最后选中规则对应的查询结果,而由于服务端查询和网络传输的影响,最后一次选中并不对应最后一次返回,所以防抖节流都不适合,最合适的方案是自动取消上一次正在执行的请求,项目使用axios,将AbortController的signal配置到请求参数signal来做取消,同时在请求配置中设置timeout来配置超时时间减少等待。

  • 限制请求时机:使用自定义hooks添加防抖节流

描述:使用hooks能更好地封装状态逻辑,而请求返回的数据需要在处理后作为组件的状态,相比普通函数使用hooks更合适。在自定义hooks中封装了请求与useState,并限制请求时机。

3. 基础组件开发

做了什么:编写组件设计文档,使用jest做单元测试

  • 使用jest做接口数据模拟及功能测试

描述:使用jest.spyOn模拟接口数据,使用expect与toBe进行组件内文本的校验,每项测试前创建DOM元素作为渲染目标并加到页面DOM树上,退出该项测试时执行清理操作。使用act在检测前进行一些预处理,例如先进行相关声明再把组件渲染到测试用的DOM元素上,了解到如果要测试组件对事件发生的变化是否符合预期,可以在测试的DOM元素上通过dispatchEvent模拟事件

  • npm包本地测试并发布到bnpm

描述:npm包可以很方便的在不同项目间实现代码复用,所以开发好的组件以npm包的形式发布到字节内网的bnpm上,bnpm就相当于字节内部的npm。

发布前先进行本地测试看看能不能正常引用,在组件根目录下执行build打包生产环境,然后npm link创建全局引用,在需要的项目中npm link+包名链接到指定包上,测试完后npm unlink+包名释放连接

发布到bnpm上与发布到npm上流程非常相似,不过是从npm publish改到了bnpm publish

4. 权限管理系统展示优化

项目描述:不同子页面共享接口类型数据,并在服务端对请求用户做鉴权

项目职责

  • 使用React、Redux与localStorage共同维护项目数据,以semi组件展示
  • 通过node中间件对当前用户进行鉴权

描述:

    因为功能要的数据是通过接口传递的,所以我们团队当时是通过查看用户有没有接口权限,来判断它是否具有接口对应功能的权限,而这个系统就负责分配接口权限。做这个需求是运营想在分配权限时同时展示接口的类型,并在自己没有分配权限的时候跳转到申请页面。

    接口数据在后端传入后在多处展示及修改,就是用redux做数据状态管理,并结合react的useSelector和useDispatch进行读写。

    通过中间件对当前用户鉴权,是因为权限的分配是高度敏感的,只能在服务端进行,并对每次用户请求单独判断,所以鉴权适合做成中间件。项目使用内部框架gulu,这框架基于koa,我做的就是开发具体的中间件并在洋葱模型中新加一层,中间件以async/await来支持异步,内部通过字符串的拼接与匹配来检查用户所具有的角色和权限,成功了就说明有权限,调用next进入下一个中间件,失败了就直接设置context的statusCode和message开始返回,并在客户端对status进行判断,需要的时候跳转。

总结

一. 项目中做过哪些优化?

  • 优化加载

1) 减少传输内容:依赖按需引用,减少用到的依赖项;代码使用es6来写得更精简,webpack使用compression-webpack-plugin插件开启gzip压缩并设置为生产环境降低代码体积

2) 减少传输次数:使用浏览器缓存与状态管理库redux、mobx缓存数据,使用雪碧图来减少页面中小图标传输数量

3) 降低DNS解析延时的影响:使用dns-prefetch提前解析DNS

4) 减少DNS查找与传输耗时:大文件使用cdn

  • 优化渲染

1) 组件样式的改变通过使用库classname操作类名实现

2) 减少页面重排:经常变化的组件使用子绝父相将它们提取到文档流外,只重排它自身而不用重排整个页面。

3) 使用防抖节流来减少短时间的重复操作、项目使用axios,配置超时中断并支持用户取消请求

4) 页面骨架和loading加载配合,拿到异步数据后再次渲染,让用户能感觉到页面在逐渐加载

5) 组件延迟加载:通过React.lazy+动态import延迟组件的获取,并配合React.Suspense组件实现等待时间内加载效果的展示

6) 计算过程比较耗时的结果使用useMemo包裹,来避免组件更新时的重复计算,传递给子组件的对象或函数使用useMemo或useCallBack包裹,来避免不必要的渲染。(类组件中可以通过继承React.PureComponent或修改生命周期方法shouldComponentUpdate做类似实现)

  • 页面性能分析

使用浏览器的开发者工具分析当前性能和可优化项,可以在Network、Performance、Lighthouse这三个板块查看,还有些别的插件也可以做这事

二、项目中遇到的难题及如何解决的

      项目中遇到的问题有技术上的也有项目推进上的。

      技术上的挺好解决的,通常结合项目中已有实现和自己的平时积累出技术方案,评审由mentor和其他相关方指出方案上的不足,新技术不了解可以去官网或技术博客上查询,一项技术能够流行起来那么它的使用肯定是不会太难,我按这种方式在项目中用过mobx做业务数据管理。

      相比下,项目推进更难,难的在于如何和其他方协作一起保证如期交付,我觉得最重要的是结合业务理解需求,排期管理和随时响应,别的按项目流程做就好。需求文档只是从产品视角来看这次可以从哪些方面去优化业务,但总有几率漏掉点什么,当我们结合业务去理解需求就可以降低风险,并能和同事一起把产品做得更好。排期管理能直观地展示当前项目进展和整体工期安排,确保各方都了解自己何时参与项目,工期多久,也方便做风险管理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值