最近在研究React Native
,准备用它写一个笔记APP,但是并没有搜到很好用的编辑器插件,因此准备使用WebView
和已有的Web端编辑器自己封装一个。
因本人没有苹果电脑,因此只尝试安卓版本
完整项目地址:qiyuor2/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
向网页中注入js -
injectedJavaScriptBeforeContentLoaded
在网页加载之前向网页中注入js -
postMessage(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必须要给他设置宽和高,不然可能会导致应用卡死
完整项目地址:qiyuor2/rn-xnote
参考文章
- 手摸手带你封装 React Native 富文本编辑器