公司建设网站产生哪些费用,三合一 网站 前端,政和县建设局网站公告,怎么做动漫网站需求
支持文本插入#xff0c;比如 xxx {product_name} xxx #xff0c;如果提供了product_name变量的值为feedback#xff0c;则可以渲染出 xxx feedback xxx。支持链接解析#xff0c;比如 [baidu](https://www.baidu.com/)#xff0c;可以直接渲染成超链接的形式。支持…需求
支持文本插入比如 xxx {product_name} xxx 如果提供了product_name变量的值为feedback则可以渲染出 xxx feedback xxx。支持链接解析比如 [baidu](https://www.baidu.com/)可以直接渲染成超链接的形式。支持插入reactnode元素比如 xxx {jump_node} xxx且jump_node是一个reactnode元素则可以将node节点插入到{}位置上。
实现
步骤
先解析链接 返回这样子的数据结构。超链接返回url-text的对象非超链接直接返回文本字符串
export interface LinkPart {text: string;url?: string;onClick?: string;
}export type ParsedTextPart string | LinkPart;[{text: baidu,url: https://www.baidu.com/,},other content,other content,
];遍历解析后的超链接数组如果是对象则渲染超链接如果是字符串继续解析解析字符串判断需要解析的{}里面的文本是否是纯文本如果是纯文本则直接Text渲染如果是react元素则渲染该元素
TextTemplate.tsx:
import React, { ReactNode } from react;
import { routeCenter } from shopeepay-rn/route-center;
import { usePageContainerContext } from shopeepay-rn/page-container;
import { StyleProp, Text, TextStyle, View, ViewStyle } from react-native;
import { parseLinkText } from ../../utils;
import styles from ./styles;interface Props {template: string;// eg: {product_name:spp, click_node:Text/Text}replaceValueMap: Recordstring, string | number | ReactNode;textStyle?: StylePropTextStyle;containerStyle?: StylePropViewStyle;
}/*** 支持解析字符串、解析react元素、解析超链接* param template 需要解析的字符串* param replaceValueMap 需要替换的key-valuevalue支持字符串和react元素* param textStyle 字体样式* param containerStyle 容器样式* returns react元素*/
export const TextTemplate ({template,replaceValueMap,textStyle,containerStyle,
}: Props) {const { rootTag } usePageContainerContext();const parseText (text: string, index: number) {const result: React.ReactNode[] [];let lastIndex 0;text.replace(/{(\w)}/g, (match: string, key: string, offset: number) {const replaceValue replaceValueMap[key];if (offset lastIndex) {// 未被匹配到的result.push(Text key{index} style{textStyle}{text.substring(lastIndex, offset)}/Text);}if (React.isValidElement(replaceValue)) {// 需要替换的是reactnode元素result.push(React.cloneElement(replaceValue, { key: index }));} else if (typeof replaceValue string) {// 需要替换的是字符串result.push(Text key{index} style{textStyle}{replaceValue}/Text);}lastIndex offset match.length;return ;});if (lastIndex text.length) {result.push(Text key{index} style{textStyle}{text.substring(lastIndex)}/Text);}return result;};const parseTemplate (text: string) {// 解析链接const linkTexts parseLinkText(text);return linkTexts?.map((part, index) {return typeof part string ? (// 对于字符串需要解析 纯字符串 还是 reactnode元素parseText(part, index)) : (Textkey{index}style{styles.link}onPress{() routeCenter.navigateWeb(part.url || ,{navbar: {title: part.text || ,},},rootTag)}{part.text}/Text);});};return (View style{[styles.textView, containerStyle]}Text{parseTemplate(template)}/Text/View);
};
parseLinkText.ts:
export interface LinkPart {text: string;url?: string;onClick?: string;
}export type ParsedTextPart string | LinkPart;const parseLinkText (text: string): ParsedTextPart[] {const regex /\[([^\]])\]\(([^)])\)/g;const parts: ParsedTextPart[] [];let lastIndex 0;text.replace(regex,(match: string, p1: string, p2: string, offset: number) {if (offset lastIndex) {parts.push(text.substring(lastIndex, offset));}parts.push({ text: p1, url: p2 });lastIndex offset match.length;return ;});if (lastIndex text.length) {parts.push(text.substring(lastIndex));}return parts;
};// FIXME: 添加 unit test
export { parseLinkText };使用
TextTemplatetemplate{you can test the TextTemplate component, parse {string_text}, parse [baidu](https://www.baidu.com/) link, parse {click_node} to show popup}replaceValueMap{{string_text:test string,click_node:Textother react node/Text}}textStyle{styles.titleText}
/