序言
简单记录一下在么么直播遇到的问题以及解决办法,项目技术栈跨度比较大,有 6-7 年前 jquery 项目,也有 React + MST(mobx state tree) + SSR 项目,还有纯 React 项目,遇到的问题比较广泛,记录一下常见的问题,帮助学习。
React 的更新机制
Ref 的一些用法
受控组建和非受控组件
命名空间
Canvas 实现弹幕组件
实现弹幕的核心是 Canvas 的 measureText()方法,该方法可以计算出画布上字体的宽度,由于弹幕的内容一般是由
相对固定的图片加未知长度的文案构成,渲染复杂的单条弹幕首先需要解决弹幕总长度,拿到了总长度,那么不管是总体的弹幕背景还是图片文案的未知都能
准确无误的渲染出来,React 可以把功能做成一个组件,一次完成,多次复用,这里我简单列举两种弹幕的实现,一种是普通的弹幕,构成是背景色 + 用户头像 + 相对固定的文案(比如抽奖弹幕,头像 + XXX 在 VVV 活动中 抽中了 AAAA x 99 次), 一种是特殊弹幕,比如春节期间产品上线了祈福送礼需求,用户发送祝福语,然后立即在屏幕上弹幕形式出现,每条祝福语弹幕的背景样式不同,🈶️ 新春对联、燕子高飞、柳树纸条等,切每个用户输入的祝福语长度取决于用户自己,有时候一条弹幕就几个字,有的有几十字,知道每条弹幕的长度有两个用处,一是弹幕的背景位置渲染,而是弹幕采用四行并存的形式,那么弹幕插入哪一行也取决于哪一行的弹幕稀疏程度,话不多少,上图上代码:
1 | // common 弹幕的引用文件 |
抽空把这个弹幕写个 demo ,光干巴巴的文字是在难以理解啊
Node 的版本控制
这个一般使用 nvm 或者 n 命令
移动端和 H5 的桥接通信
使用 jsBridge 进行 H5 和移动端的通信。具体后面整理一下。
直播礼物的动画播放队列实现
Video 播放 mp4 的注意点
react 中播放 mp4 格式,会有一些 iOS 机型的兼容问题,不如 iOS 不能自动播放等
1 | //React中播放mp4的情况,一帮情况下播放GIF或者SVGA |
poster属性可以在视频未加载完成前展示一张封面图片,视频加载后自动播放视频。
hooks 封装
其实相比自己封装有针对性的 hooks 外,阿里的 ahooks3.0 也可以使用,功能还是值得期待的
React 中挂载滑动函数
抽奖
一些 CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
-webkit-tap-highlight-color: rgba(0,0,0,0)
// 解决iOS和iPad设备上点击状态出现默认蓝色高亮,很常见
& + & {}
取巧,选择非第一个开始的所有同类型元素
font-size: 0;
父元素设置改属性可以有效解决行内元素的默认间距,例如span
padding-bottom: 6%;
ol li:before {
content:counter(sectioncounter) "、";
counter-increment:sectioncounter;
}
//有序元素的符号替换展示
.gift-show-area[gift-id='7777'] {}
//可以这样查找元素
background-image: linear-gradient(135deg, red, blue);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
// 文字颜色渐变
::-webkit-input-placeholder
// placeholder样式次修改
- 复杂表格项合并
rowSpan colspan 行列合并
按需加载优化
项目已经很庞大的情况下,还要考虑hybrid的体验情况,需要进行项目优化,按需加载比较适合某些场景下,这里采用《react-intersection-observer》中的hooks useInView 来判断元素是否在可视窗口内。进而判断是否渲染该元素。
1 | // 这里封装一个图片按需加载的公用组建 |
Modal封装
不论是PC页面,还是hybrid原生页面,都需要大量形形色色的弹窗来通知用户处理业务逻辑,封装几种常见的Modal
CSS 点九图
最近年中和周年庆开始,铺天盖地的活动。UI 设计的风格和一往不太一样,举一个栗子: 在投票页面中,每个被投票的主播都是单独的一张特殊背景图包裹,该容器可能会根据被投票人的信息长短不一,不规则背景边框图也要自动适应。类似这样的需求,一般有这么几种方法实现:
三段图重复
就是把不规则的背景图切成三段。头部、中间部分、底部,中间部分利用背景图的 repeat 来自适应,缺点就是不灵活,需要找 UI 切图,里面内容的间距控制不精准点九图
点九图是移动端的一种做法,就是一张图切四刀,四个角不伸缩,保持原图比例。四条边进行伸缩,中间的部分用来填充,一共九个部分,所以称点九图。CSS3 也可以实现点九图,且效果不错,举个例子:
写一个业务组件,只用来做 wrap 包裹,用点九图,这样其他的同样式的组件都可以复用。
1 | import React from 'react' |
使用 ‘border-image-slice’ 属性来完成点九图,它接受 4 个参数,分别在图片的上右下左切一刀,把图片分为 9 个部分,一中心,四个角,四个边。伸缩只会让边进行伸缩,所以需要调整切的位置,尽量在规则的地方下刀。此时,若父容器的宽高未给定,则完全由内容撑开宽高,
上面栗子中,宽度做了限制,高度未限制,传入的 children 会撑开点九图组件的高度,做到每个子组件高度根据内容自适应,但整体的样式不会发生变化。
Hybrid全面屏
H5页面在iOS和安卓应用,通常是移动端给了屏幕空间,用来展示H5页面,不包含顶部电池栏tab,新的沉浸式体验则需要H5页面也要控制电池区域,铺满整个移动端屏幕。
每个手机设备的电池区域高度不尽相同,且设备的dpi也不一致,iOS是相对固定的22像素,安卓则是五花八门,这里需要桥接通信拿到移动端的“tab高度”和设备dpi,有这两个参数,H5页面则可以实现统一的全面屏幕沉浸式体验。
dpi :当前显示设备的物理像素分辨率与CSS像素分辨率之比,需要进行转化为H5的px单位,基本算法分为:
1 | // res 为桥接通信移动端返回的数据 |
iOS的高度不需要额外转换,一般iOS机型返回都是22px,安卓则需要除以dpi得到CSS像素。
拿到最终的状态栏高度,进行app-header的布局,基本tab栏高度一般为 88 像素,再加上状态栏(电池栏)的高度,如果整个头部整体需要fixed布局,全局则增加padding-top 取巧实现。整个H5页面总体分为两个区域,tab栏和content内容页,一般tab栏使用纯色背景,内容页则有时候会使用渐变色,此时,content的高度无法确定,则整体页面使用 flex布局,tab栏使用 shrink: 0 ; 禁止缩放,content则使用 flex: 1; 自动填充满视口,这样,内容页的渐变色则和tab页无缝衔接。
hybrid touch bar判断
js判断当前手机是否有touch bar,如果存在 touch bar ,则App全局头部添加样式类名,后续业务只需根据对应CSS标识处理不同的样式。
解决: iOS 手机屏幕底部存在白线(操作栏),会遮挡页面的一部分,常见的页面底部会存在用户点击按钮或其他UI,操作栏会降低用户的体验。判断iOS存在 touch bar ,则增加全局样式,在对应子业务中修改样式即可避免。
1 |
|
iframe 跨域通信
在对接一些第三方的游戏时,采用 App客户端 嵌入 Hybrid H5前端,前端对接第三方。比如,抖音直播间火起来的弹幕游戏和其他趣味游戏,在直播间接入这些三方游戏,在关闭游戏、支付等方面,涉及三端跨域通信。
这里有一个案例,游戏是第三方的,但游戏内充值兑换货币的页面是我们的。游戏最终需要在客户端、Web端、桌面端(window app, 主要是开播工具)三端展示。这里页面互相嵌套,但本质就是子父页面通信。
// 父页面监听单个事件
window.addEventListener('message', _handleMsg)
const _handleMsg = (event) => {
// doSomeThing
}
// 子页面发送事件
// window.parent.postMessage('你的参数, '*') 第二个参数即解决跨域问题,也可填写父窗口的域名 window.parent.postMessage('你的参数, 'https://0.0.0.9200')
// window.parent 返回父窗口
// window.top 返回最顶层窗口,不一定是父窗口
const closeWebView = () => {
window.parent.postMessage(
{
type: 'webViewEvent',
source: 'xxx',
event: 'close',
},
'*',
);
};
自定义hooks
在手写较多的 useEffect 的时候,就应该抽一个 hooks 出来。 React的官网原话也有: 如果你发现自己经常需要手动编写 Effect,那么这通常表明你需要为组件所依赖的通用行为提取一些 自定义 Hook。