ReactNative學習筆記八之圖表組件交互(下)

這一篇主要會介紹如何在React-Native中使用Echart,以及native-echart的原理,以及組件與表格之間的交互。本文所舉的例子設計echart的tooltip以及dispatchAction,這裏不清楚的朋友請看一下上一篇文章
ReactNative學習筆記七之圖表組件交互(上)html


native-echart

在一開始打算使用echart的時候,我就選擇的是這個node,可是後來發現不能知足個人要求,因此,就根據他的原理本身修改了一下。
在這裏給一個原做者的github地址:
github.com/somonus/rea…node

原理

若是在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:react

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)}
這段代碼就是爲了渲染表格的:git

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的展現。github

佈局

native-echart在佈局上也不是單單的去使用上面封裝的NativeChart,而是使用再上面又包裹了一層:web

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當中,因此,這裏,開發者能夠根據本身的須要進行修改。json

交互

正常來講,你用RN寫一個組件,是不能跟Webview中的組件進行交互的,可是經過RN的Webview進行交互。交互分爲RN->Echart以及Echart->RNreact-native

RN->Echart

當RN中有組件想傳遞數據給Echart的時候,好比咱們的界面中有一個按鈕,點擊按鈕,echart會執行showtip的操做:bash

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:echarts

_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感興趣,歡迎關注個人公衆號,加入咱們的討論羣:

相關文章
相關標籤/搜索