分享内容
- 全局属性Context
- 性能监控
- debug工具
一.全局属性Context
1.概念
当你不想在组件树中通过逐层传递props或者state的方式来传递数据时,可以使用Context来实现跨层级的组件数据传递。
上图,使用props或者state传递数据,数据自顶下流。
使用Context,可以跨越组件进行数据传递。
使用Context
如果要Context发挥作用,需要用到两种组件,一个是Context生产者(Provider),通常是一个父节点,另外是一个Context的消费者(Consumer),通常是一个或者多个子节点。所以Context的使用基于生产者消费者模式。
对于父组件,也就是Context生产者,需要通过一个静态属性childContextTypes声明提供给子组件的Context对象的属性,并实现一个实例getChildContext方法,返回一个代表Context的纯对象 (plain object) 。
export default class extends Component {
// 声明Context对象属性
static childContextTypes = {
navigation: PropTypes.object
};
constructor(props) {
super(props);
}
// 返回Context对象,方法名是约定好的
getChildContext() {
return {
navigation: this.props.navigation
};
}
}
而对于Context的消费者,需要在静态属性中声明要使用的属性,子组件需要通过一个静态属性contextTypes声明后,才能访问父组件Context对象的属性,否则,即使属性名没写错,拿到的对象也是undefined。
export default class InfoView extends PureComponent {
// 声明需要使用的Context属性
static contextTypes = {
navigation: PropTypes.object
};
onPressEdit = () =>{
this.context.navigation.push('Choice');
};
}
2.几个可以直接获取Context的地方
实际上,除了实例的context属性(this.context),React组件还有很多个地方可以直接访问父组件提供的Context。比如构造方法:
- constructor(props, context)
比如生命周期:
- componentWillReceiveProps(nextProps, nextContext)
- shouldComponentUpdate(nextProps, nextState, nextContext)
- componetWillUpdate(nextProps, nextState, nextContext)
对于面向函数的无状态组件,可以通过函数的参数直接访问组件的Context。
const StatelessComponent = (props, context) => (
......
)
2.关注Context的可控性和影响范围
React App的组件是树状结构,一层一层延伸,父子组件是一对多的线性依赖。随意的使用Context
其实会破坏这种依赖关系,导致组件之间一些不必要的额外依赖,降低组件的复用性,进而可能会影响到App的可维护性。
通过上图可以看到,原本线性依赖的组件树,由于子组件使用了父组件的Context
,导致<Child />
组件对<Node />
和<App />
都产生了依赖关系。一旦脱离了这两个组件,<Child />
的可用性就无法保障了,减低了<Child />
的复用性。
思考
适用于Context的应用场景
参考
https://juejin.im/post/5a90e0545188257a63112977#heading-6
二.性能监控
背景
现在大规模采用RN开发,但尚缺乏自动化、工具级性能采集监控,导致以下问题
目标
针对开发和项目过程痛点,我们期望的目标如下:
- 项目性能评估客观可量化
- 自动化侦测性能缺陷
- 问题定位辅助决策
方案拆解思路:首先是找到针对React Native的性能相关性数据,也就是当性能出现下滑时,可以通过哪些维度的数据表现出来;然后有了数据样本需要进行记录;之后时对瞬时和一段周期内的样本进行自动化分析;最后时提供结果反馈。
解决方案
首先是性能相关性数据的实时采样模块,包括MRT(消息响应及时性)、GCP(绘图指令生效推迟)、逻辑同步帧率等。
其次是对样本的记录,记录模块目前支持两种记录模式,一种是存储在手机本地,一种是提供外放协议可以把数据投递到外部对接系统。
之后是实时分析,基于记录的各个维度数据进行缺陷侦测并生成预警。通过输出模块输出到开发者日志和可视化报表,这里我们后期有计划自动生成对应项目的性能bug对接到QA系统。
如何采集相关性数据、分析规则与调优策略
在行业缺乏相关方案的背景下,最难地方在于寻找React Native应用的性能相关性数据都是什么,在哪里,围绕RN的实现原理我们挖掘到了这些维度:
- MRT(消息相响应及时性)
- GCP(绘图指令延迟)
- 无SCU优化、冗余render调用侦测
- 绘图帧率与逻辑同步帧率
- 关键线程CPU负载
- 内存用量
- 流量消耗
实践——针对SCU做的性能监控
支持全组件监控插件
利用高阶组件在声明周期hock方法上埋点
- 计算渲染时间
-
记录组件渲染次数
mobx组件渲染时间监控
- mobx源码
componentDidMount: function componentDidMount() {
if (isDevtoolsEnabled) {
reportRendering(this);
}
},
componentDidUpdate: function componentDidUpdate() {
if (isDevtoolsEnabled) {
reportRendering(this);
}
},
function reportRendering(component) {
var node = findDOMNode$1(component);
if (node && componentByNodeRegistry) componentByNodeRegistry.set(node, component);
renderReporter.emit({
event: "render",
renderTime: component.__$mobRenderEnd - component.__$mobRenderStart,
totalTime: Date.now() - component.__$mobRenderStart,
component: component,
node: node
});
}
- 使用
安装依赖
npm install mobx-devtools --save-dev
在page/index.js中统一监听时间
import { renderReporter } from 'mobx-react';
export default class extends Component {
constructor(props) {
...
renderReporter.on((report) => {
console.warn(report.component.constructor.name + ' renderTime' + report.renderTime + ' totalTime' + report.totalTime);
});
}
}
参考
//www.greatytc.com/p/943c3e7a8cd1
三.debug工具
1.mobx-监控工具
能力
- 实时观测mobx数据,不用debug就可以看到数据结构
- 监测mobx数据变化
- 监测mobx数据处理时间
依赖
npm install mobx-remotedev --save-dev
npm install remotedev-server --save-dev
使用
在所有state地方加上@remotedev(配置)
// detail/state.js
@remotedev({ remote: true, onlyActions: true, global: true, hostname: 'localhost', port: 8000, })
export default class State {
// page
@observable result = {};
@observable pageState = PAGE_STATE.INIT;
@action setResult(data) {
this.result = data;
}
@action setPageState(state) {
this.pageState = state;
}
}
启动remotedev服务,配置以下命令手动开启
"scripts": {
"remotedev": "remotedev --hostname=localhost --port=8000"
},
问题
- mobx.getDebugName is not a function
解决方案
需要把本地node_module/mobx-remotedev/lib目录下的
spy.js和utils.js里面的mobx.getDebugName(obj)改个名字
最终解决方案
升级mobx版本
"mobx": "^5.15.0",
"mobx-react": "^5.4.4",
- socket hang up
socket服务没连上
检查是否执行了remotedev
ios调试模式不支持localhost,需要把hostname设置成电脑ip地址
2. 彩蛋debug in webstrom
设置
chrome静默debug能力
-headless --disable-gpu
参考
https://github.com/zalmoxisus/mobx-remotedev/issues/9
https://github.com/zalmoxisus/remotedev-server