- A+
所属分类:Web前端
最近在研究React Native
,准备用它写一个笔记APP,但是并没有搜到很好用的编辑器插件,因此准备使用WebView
和已有的Web端编辑器自己封装一个。
因本人没有苹果电脑,因此只尝试安卓版本
完整项目地址:Tuzilow/rn-xnote
React Native WebView
WebView
是一个能够在原生APP上加载HTML页面的组件,不过它没有提供浏览器的地址栏、导航栏等功能。在原生APP的开发中经常会用到。
安装
npm install react-native-webview # or yarn add react-native-webview
基本使用
引入URL
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 Native之间的通信
Web到React Native
window.ReactNativeWebView.postMessage(message)
该方法接收一个字符串,并将该字符串发送到React Native中。在React Native中使用WebView
组件的onMessage
属性接收
React Native到Web
injectedJavaScript
向网页中注入jsinjectedJavaScriptBeforeContentLoaded
在网页加载之前向网页中注入jspostMessage(message)
向网页中发送消息,与window.ReactNativeWebView.postMessage(message)
相对应。网页可以通过监听message
事件收到消息。
更多API请查看WebView文档
封装Vditor
准备HTML文件
<!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'}
引入
React Native组件
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必须要给他设置宽和高,不然可能会导致应用卡死
完整项目地址:Tuzilow/rn-xnote