支付宝小程序将 HTML String 转化为 nodes 数组

2020-05-01

支付宝小程序将 HTML String 转化为 nodes 数组

支付宝小程序的rich-text 富文本不支持html代码,所以我写了个方法来转,注意根据自己的需求稍微修改下。

/**
 * html转换为node节点
 * @param htmlStr
 * @returns {[]}
 */
export function htmlToNodes(htmlStr) {
    let nodes = [];
    let htmlNodes = new DOMParser().parseFromString(htmlStr, 'text/html');
    if (!htmlNodes) {
        return nodes;
    }
    let bodyNodes = htmlNodes.body.children;
    let len = bodyNodes.length;
    for (let i = 0; i < len; i++) {
        nodes.push(getChildrenNodes(bodyNodes[i]));
    }
    return nodes;
}

let imgStyle = 'max-width: 80%; height: auto;';
let pStyle = 'text-indent:2em;line-height: 30px;color: #333;word-break: break-all;';

/**
 * 获取单个node对象
 * @param nodes
 * @returns
 */
function getChildrenNodes(nodes) {
    if (nodes.nodeType === 1) {
        let style = '';
        let attrs = {};
        if (nodes.nodeName.toUpperCase() === 'P') {
            style = pStyle;
        } else if (nodes.nodeName.toUpperCase() === 'IMG') {
            style = imgStyle;
            // 拿到src路径
            let jLen = nodes.attributes.length;
            let src = '';
            for (let j = 0; j < jLen; j++) {
                if (nodes.attributes[j].nodeName.toUpperCase() === 'SRC') {
                    src = 'https://www.wyzda.com' + nodes.attributes[j].textContent;
                }
            }
            attrs['src'] = src;
        }
        attrs['style'] = style;
        let len = nodes.childNodes.length;
        let childrenArr = [];
        if (len > 0) {
            for (let i = 0; i < len; i++) {
                childrenArr.push(getChildrenNodes(nodes.childNodes[i]));
            }
        }
        return {
            name: nodes.nodeName,
            attrs: attrs,
            children: childrenArr,
        };

    } else if (nodes.nodeType === 3) {
        return {
            type: 'text',
            text: nodes.textContent
        };
    }
}

调用 htmlToNodes(html源码) 方法即可返回node数组。

但上面的方法仅能在模拟器上运行,原因在于 new DOMParser().parseFromString(htmlStr, 'text/html'); 这个方法不能在小程序里运行,所以我们需要改一下我们的代码。

安装react-native-html-parser库

文档:https://www.npmjs.com/package/react-native-html-parser

安装方法:npm install react-native-html-parser

修改htmlToNodes方法

引入库

let MyDomParser = require('react-native-html-parser').DOMParser;

修改dom生成方法。

let htmlNodes = new MyDomParser().parseFromString(htmlStr, 'text/html');
    if (!htmlNodes) {
        return nodes;
    }
let bodyNodes = htmlNodes.childNodes;

以上改完了即可以正常使用了。

完整htmlToNodes方法,getChildrenNodes方法无需任何修改!

/**
 * html转换为node节点
 * @param htmlStr
 * @returns {[]}
 */
export function htmlToNodes(htmlStr) {
    let nodes = [];
    let htmlNodes = new MyDomParser().parseFromString(htmlStr, 'text/html');
    if (!htmlNodes) {
        return nodes;
    }
    let bodyNodes = htmlNodes.childNodes;
    let len = bodyNodes.length;
    for (let i = 0; i < len; i++) {
        nodes.push(getChildrenNodes(bodyNodes[i]));
    }
    return nodes;
}

小程序内使用

this.setData({
	content: htmlToNodes(content)
});