最近在研究React Native
,準備用它寫一個筆記APP,可是並無搜到很好用的編輯器插件,所以準備使用WebView
和已有的Web端編輯器本身封裝一個。css
因本人沒有蘋果電腦,所以只嘗試安卓版本html
完整項目地址:Tuzilow/rn-xnotejava
WebView
是一個可以在原生APP上加載HTML頁面的組件,不過它沒有提供瀏覽器的地址欄、導航欄等功能。在原生APP的開發中常常會用到。react
npm install react-native-webview # or yarn add react-native-webview
import React, { Component } from 'react'; import { WebView } from 'react-native'; export default function MyWeb () { return ( <WebView source={{uri: 'https://github.com/facebook/react-native'}} /> ); }
import React, { Component } from 'react'; import { WebView, Platform } from 'react-native'; export default function MyWeb () { return ( <WebView source={ Platform.OS === 'ios' ? require('../../../assets/vditor.html') : {uri: 'file:///android_asset/vditor.html'} } /> ); }
Web到React Nativeandroid
window.ReactNativeWebView.postMessage(message)
該方法接收一個字符串,並將該字符串發送到React Native中。在React Native中使用WebView
組件的onMessage
屬性接收ios
React Native到Webgit
injectedJavaScript
向網頁中注入jsinjectedJavaScriptBeforeContentLoaded
在網頁加載以前向網頁中注入jspostMessage(message)
向網頁中發送消息,與window.ReactNativeWebView.postMessage(message)
相對應。網頁能夠經過監聽message
事件收到消息。更多API請查看WebView文檔github
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" /> <!-- 如下文件建議放到本地使用 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vditor/dist/index.css" /> <script src="https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js"></script> </head> <body> <div id="vditor"></div> <script> // window.options 會在React Native中經過injectedJavaScriptBeforeContentLoaded注入 const vditor = new Vditor('vditor', { ...window.options, // 向編輯器輸入時,經過postMessage向React Native發送消息,觸發onMessage input: (value) => { const message = { type: 'onChange', message: value, }; window.ReactNativeWebView.postMessage(JSON.stringify(message)); } }); // 監聽React Native發送來的消息 window.document.addEventListener('message', (e) => { vditor.setValue(e.data); }); </script> </body> </html>
若是是安卓開發,須要將該文件放到your-project/android/app/src/main/assets/
下,以後經過{uri: 'file:///android_asset/xxxx.html'}
引入web
import React, { useRef, useState } from 'react'; import { WebView, WebViewMessageEvent } from 'react-native-webview'; export default function Vditor() { const webviewRef = useRef<WebView>(null); const [content, setContent] = useState(''); // 注入到網頁中的vditor配置數據 const options = `window.options=${JSON.stringify({ mode: 'ir', toolbar: [], outline: false, debugger: false, placeholder: '可以使用markdown語法...', })}`; //#region 初始化編輯器內容 useEffect(() => { const fetchData = async () => { // 獲取初始化的數據 const data = await request(); setContent(data); }; fetchData(); }, []); useEffect(() => { webviewRef.current?.postMessage(content); }, [content]); //#endregion const onMessage = (e: WebViewMessageEvent) => { const data = JSON.parse(e.nativeEvent.data); if (data.type === 'onChange') { setContent(data.message); } }; return ( <WebView ref={webviewRef} onMessage={onMessage} javaScriptEnabled source={ Platform.OS === 'ios' ? require('../../../assets/vditor.html') : {uri: 'file:///android_asset/vditor.html'} } injectedJavaScriptBeforeContentLoaded={options} style={{ height: Dimensions.get('window').height, width: Dimensions.get('window').width, }} /> ); }
注意:React Native中使用WebView必需要給他設置寬和高,否則可能會致使應用卡死npm
完整項目地址:Tuzilow/rn-xnote