• React Native中使用Markdown编辑器


    最近在研究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向网页中注入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,
             Dimensions.get('window').width,
          }}
        />
      );
    }
    
    

    注意:React Native中使用WebView必须要给他设置宽和高,不然可能会导致应用卡死

    完整项目地址:Tuzilow/rn-xnote

    参考文章

    作者:Tuzilow
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    HDU 6106 Classes【水题】
    HDU 6106 Classes【水题】
    ACM常用解题技巧方法
    ACM常用解题技巧方法
    程序员语录
    数据库设计的三大范式
    IDEA中Java代码存入DB中为乱码
    IDEA中如何添加jar包
    Java的Protected
    Hibernate JPA 如何使用SQL文直接查询
  • 原文地址:https://www.cnblogs.com/xueyubao/p/14409997.html
Copyright © 2020-2023  润新知