这一篇主要会介绍如何在React-Native中使用Echart,以及native-echart的原理,以及组件与表格之间的交互。本文所举的例子设计echart的tooltip以及dispatchAction,这里不清楚的朋友请看一下上一篇文章
ReactNative学习笔记七之图表组件交互(上)
native-echart
在一开始打算使用echart的时候,我就选择的是这个node,但是后来发现不能满足我的要求,所以,就根据他的原理自己修改了一下。
在这里给一个原作者的github地址:
github.com/somonus/rea…
原理
如果在React-Native中直接使用echart会出现"undefined is not an object (evaluating 'ua.match')" when importing an incompatible (browser) library.
这个错误,这是由于,Echart不支持ReactNative,但是使用js是可以的啊,所以,基本思路是,写一个html的网页,然后加入echart,然后用ReactNative的Webview组件打开即可。
所以在工程中会有一个tpl.html
。
这时写一个组件,封装WebView,打开这个html:
export default class NativeChart extends React.Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(nextProps) {
if(nextProps.option !== this.props.option) {
this.refs.chart.reload();
}
}
webview: WebView
postMessage = (data) => {
this.webview.postMessage(data)
};
render() {
return (
<View style={{flex: 1, height: this.props.height || 400,}}>
<WebView
ref={chart => this.webview = chart}
scrollEnabled = {false}
onMessage={this.props.onMessage}
injectedJavaScript = {renderChart(this.props)}
style={{
height: this.props.height || 400,
}}
source={require('./tpl.html')}
/>
</View>
);
}
}复制代码
这里需要注意,在使用WebView的时候插入了一段js
代码injectedJavaScript = {renderChart(this.props)}
这段代码就是为了渲染表格的:
export default function renderChart(props) {
const height = props.height || 400;
return `
document.getElementById('main').style.height = "${height}px";
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption(${toString(props.option)});
window.document.addEventListener('message', function (e) {
const message = JSON.parse(e.data);
if (message.command === 'get info') {
myChart.dispatchAction({type: 'showTip', seriesIndex: '1', dataIndex: '1'});
window.postMessage('success');
}
});
`
}复制代码
也就是我们将表格参数通过RN传递给他的组件,组件在通过js注入的方式传入网页当中,实现了echart的展示。
布局
native-echart在布局上也不是单单的去使用上面封装的NativeChart,而是使用再上面又包裹了一层:
export default class Echart extends Component {
constructor(props) {
super(props);
}
// echart: NativeEchart
postMessage = (data) => {
this.refs.chart.postMessage(data);
};
render() {
return (
<Container width={this.props.width}>
<NativeEchart
ref="chart"
{...this.props} />
</Container>
);
}
}复制代码
真正使用的是这个Echart,通过上述代码我们可以发现,我们传入的width值是没有意义的,只是被设定为容器的宽度,并没有真正设置到Echart当中,所以,这里,开发者可以根据自己的需要进行修改。
交互
正常来说,你用RN写一个组件,是不能跟Webview中的组件进行交互的,但是通过RN的Webview进行交互。交互分为RN->Echart以及Echart->RN
RN->Echart
当RN中有组件想传递数据给Echart的时候,比如我们的界面中有一个按钮,点击按钮,echart会执行showtip的操作:
render() {
return (
<View style={styles.container}>
<Echarts
ref="chart"
option={this.state.option}
onMessage = {this.handleMessage}
height={200}/>
<TouchableHighlight onPress={this._onPressButton.bind(this)}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableHighlight>
</View>
);
}复制代码
点击按钮,执行_onPressButton:
_onPressButton() {
var thiz = this;
const data = {
command: 'get info', // 表明意图
payload: { // 表明内容
property: 'nickname'
}
}
thiz.refs.chart.postMessage(JSON.stringify(data));
}复制代码
这里需要注意一个问题,只有使用了this._onPressButton.bind(this),才能在里面使用 thiz.refs.chart,如果用this._onPressButton,this表示的不再是这个类,而是这个方法。
我们可以看到,点击按钮,实际调用的是Echart类的postMessage方法,发送了一个json过去。
在上面介绍代码的时候也提到过:
postMessage = (data) => {
this.webview.postMessage(data)
};复制代码
会调用到上述方法,把json传递给webview。
这是再看一下js内部:
window.document.addEventListener('message', function (e) {
const message = JSON.parse(e.data);
if (message.command === 'get info') {
myChart.dispatchAction({type: 'showTip', seriesIndex: '1', dataIndex: '1'});
window.postMessage('success');
}
});
有个监听器,这个监听器监听到传过来的json,进行dispatchAction操作myChart.dispatchAction({type: 'showTip', seriesIndex: '1', dataIndex: '1'});
Echart->RN
看到上面一段代码,可以发现,除了dispatchAction还有一个window.postMessage('success');
这是回传事件,也就是html中想ReactNative发送一个事件,上述代码假设这是一个字符串success
。
这时我们需要定义一个接收:
handleMessage = (evt: any) => {
const message = evt.nativeEvent.data
ToastAndroid.show(message, ToastAndroid.LONG)
}复制代码
假设就是这样吧。有了这个方法,我们需要告知Webview:
<WebView
ref={chart => this.webview = chart}
scrollEnabled = {false}
onMessage={this.handleMessage}
injectedJavaScript = {renderChart(this.props)}
style={{
height: this.props.height || 400,
}}
source={require('./tpl.html')}
/>复制代码
上述代码中:onMessage={this.handleMessage}
这个就是指定Webview接收事件。
总结
整体的交互到这里就介绍完了,同时也介绍了一下native-echart的工作原理,需要的朋友也可以自己进行修改。
之前文章合集:
Android文章合集
iOS文章合集
ReactNative文章合集
如果你也做ReactNative开发,并对ReactNative感兴趣,欢迎关注我的公众号,加入我们的讨论群: