ReactNative学习笔记八之图表组件交互(下)

这一篇主要会介绍如何在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感兴趣,欢迎关注我的公众号,加入我们的讨论群:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值