首页
工具
心境语句
相册
建站轨迹
关于
Search
1
微信小程序:计算属性的两种体现方式及应用场景
1,594 阅读
2
Antd Upload 组件上传文件接收数据流并下载
1,059 阅读
3
C#插件火车头采集器动态切换代理IP,及自动切换UserAgent
542 阅读
4
[C#]使用dnSpy对目标程序(EXE或DLL)进行反编译修改并编译运行
537 阅读
5
ADODB.Connection 错误 800a0e7a 未找到提供程序。该程序可能未正确安装解决方法
499 阅读
react
typecho
ASP
Centos
MYSQL
PHP
Sql server
Javascript
nodejs
数据采集
.NET
git
编程算法
管理及流程
Vue
微信小程序
android
python
mongodb
登录
Search
标签搜索
kotlin
node-sass
nuxtjs
C#火车头插件
火车头采集器
火车头代理
C#反编译
程序逆向
dnSpy教程
Antd
InputNumber
NPM教程
NPM命令
rrweb教程
git慢
git镜像
vim命令
git命令
网页音乐插件
网页播放器
Elysian
累计撰写
74
篇文章
累计收到
0
条评论
首页
栏目
react
typecho
ASP
Centos
MYSQL
PHP
Sql server
Javascript
nodejs
数据采集
.NET
git
编程算法
管理及流程
Vue
微信小程序
android
python
mongodb
页面
工具
心境语句
相册
建站轨迹
关于
搜索到
74
篇与
Elysian
的结果
2021-09-11
如何把html字符串转成一个React组件?简单而轻量级HTML字符串到React元素转换库htmr
React对html支持前景dangerouslySetInnerHTMLreact提供了dangerouslySetInnerHTML属性,把html字符串转成react元素:安全性通常来讲,直接设置dangerouslySetInnerHTML存在风险,因为很容易无意中使用户暴露于跨站脚本(XSS) 的攻击。因此,你可以直接在 React 中设置 HTML,但当你想设置 dangerouslySetInnerHTML 时,需要向其传递包含 key 为 __html 的对象,以此来警示你。正如上面所说,直接使用dangerouslySetInnerHTML存在xss的风险。所以我们需要先对html字符串进行过滤、转换,再通过 React.createElement() 把字符串转成React组件。如果需要自己去实现这一步骤的话,可能会比较麻烦(因为还涉及字符串转dom、属性转React属性等操作)。下面会介绍一个实现这个功能的库htmr和内部原理。htmr安装方法$ yarn add htmr # or $ npm install htmr --save使用htmr接收两个参数,html字符串和一个配置对象options。html:stringoptions:Partial<HtmrOptions>={}下面着重介绍下HtmrOptions里面各个属性:preserveAttributes:Array<String | RegExp> - 默认情况下,htmr会将符合要求的html属性转换为React要求的驼峰式属性,如果某些属性不想转换,可以通过该属性来阻止React这个行为。transform - 接受键值对,这些键值对将用于 将节点(键)转换为自定义组件(值),可以使用它来通过自定义组件呈现特定的标签名称。例如,下面这个例子。定义了transform对象,目的是把p标签转成Paragraph组件,把a标签转成span标签:const transform = { p: Paragraph, a: 'span' } htmr('<p><a>Hello, world!</a></p>', {transform}) // 结果 => <Paragraph><span>Custom component</span></Paragraph>在 transform 里面有一个参数叫做defaultTransform, 以符号 _表示,它接受的参数跟React.createElement一致。这个参数非常有用,例如可以在富文本里面处理图片,把图片转成我们自定义的图片组件const transform = { // 参数跟React.createElement一致 _: (nodeName, props, children) => { if(nodeName === 'img) { let src = props.src; return <Image src={src}> } return React.createElement(nodeName, props, children); } }在 transform 里面还有一个参数叫 dangerouslySetChildren ,出于安全原因,默认情况下,htmr仅将危险标签内的样式标记的子项呈现在危险地设置为InnerHTML中。例如,下面例子设置dangerouslySetChildren:['code']:const html = '<div><code><span>xxx</span></code></div>' htmr(html, { dangerouslySetChildren: ['code'] }); // <div><code dangerouslySetInnerHTML={{__html: encode('<span>xxx</span>')}}>工具函数hypenColonToCamelCase把带中划线或者冒号的字符串转成驼峰式,如 color-profile => colorProfile,xlink:role => xlinkRole 。function hypenColonToCamelCase(str: string): string { return str.replace(/(-|:)(.)/g, (match, symbol, char) => { return char.toUpperCase(); }); }convertValuefunction convertValue(value: string): number | string { if (/^\d+$/.test(value)) { return Number(value); } return value.replace(/'/g, '"'); }convertStyle把行内样式字符串转成StyleObject类型:function convertStyle(styleStr: string): StyleObject { const style = {} as StyleObject; styleStr .split(';') .filter(style => style.trim() !== '') .forEach(declaration => { const rules = declaration.split(':'); if (rules.length > 1) { // 属性名 const prop = hypenColonToCamelCase(rules[0].trim()); const val = convertValue( rules .slice(1) .join(':') .trim() ); style[prop] = val; } }); return style; }内部原理htmlServer我们在上面例子用到的htmr函数其实就是htmlServer,它主要做了两件事情:html字符串转成dom;对dom所有节点做转换成符合要求的ReactElement;export default function htmrServer( html: string, options: Partial<HtmrOptions> = {} ) { if (typeof html !== 'string') { throw new TypeError('Expected HTML string'); } const doc = parseDocument(html.trim(), {}); // 1. const nodes = doc.childNodes.map((node, index) => // 2. toReactNode(node, index.toString(), options) ); return nodes.length === 1 ? nodes[0] : nodes; }htmlServer用到一个parseDocument方法,它是 htmlparser2导出的一个函数,能把html字符串转化成dom:import { parseDocument } from 'htmlparser2';toReactNode顾名思义,toReactNode是把dom转成ReactNode,也是这个库的核心。根据dom节点的type属性,做了分类处理:如果type 的值是 'script' 、'style' 和 'tag' 其中之一,执行如下操作:解码所有属性值;执行mapAttribute(把属性转成React属性);根据transform转化标签;const node: HTMLNode = childNode as any; const { name, attribs } = node; // decode all attribute value Object.keys(attribs).forEach((key) => { attribs[key] = decode(attribs[key]); }); const props = Object.assign( {}, mapAttribute(name, attribs, preserveAttributes, getPropName), { key } ); /** * const transform = { * p: Paragraph, * a: 'span', * }; * 例如把 p标签转成 Paragraph标签,a转成span */ const customElement = transform[name];判断当前标签是否在dangerouslySetChildren列表,是的话塞到dangerouslySetInnerHTMLif (dangerouslySetChildren.indexOf(name) > -1) { // Tag can have empty children if (node.children.length > 0) { const childNode: TextNode = node.children[0] as any; const html = name === 'style' || name === 'script' ? // preserve encoding on style & script tag childNode.data.trim() : encode(childNode.data.trim()); props.dangerouslySetInnerHTML = { __html: html }; } return customElement ? React.createElement(customElement as any, props, null) : defaultTransform ? defaultTransform(name, props, null) : React.createElement(name, props, null); }对children节点执行toReactNode;如果存在transform,转化成对应ReactElement并返回;如果存在defaultTransform ,调用defaultTransform 并返回;如果不存在transform和defaultTransform,执行React.createElement;// 5. const childNodes = node.children .map((node, index) => toReactNode(node, index.toString(), options)) .filter(Boolean); // self closing component doesn't have children const children = childNodes.length === 0 ? null : childNodes; // 6. if (customElement) { return React.createElement(customElement as any, props, children); } // 7. if (defaultTransform) { return defaultTransform(name, props, children); } // 8. return React.createElement(name, props, children);如果type是'text',则处理很简单:const node: TextNode = childNode as any; let str = node.data; if (node.parent && TABLE_ELEMENTS.indexOf(node.parent.name) > -1) { str = str.trim(); if (str === '') { return null; } } str = decode(str); return defaultTransform ? defaultTransform(str) : str;接下来,了解一下第2步提到的mapAttribute是如何把html属性转成React属性的。mapAttribute首先,先贴上代码:Object.keys(attrs).reduce((result, attr) => { // 1 if (/^on.*/.test(attr)) { return result; } // 2 let attributeName = attr; if (!/^(data|aria)-/.test(attr)) { // Allow preserving non-standard attribute, e.g: `ng-if` const preserved = preserveAttributes.filter(at => { if (at instanceof RegExp) { return at.test(attr); } return at === attr; }); if (preserved.length === 0) { attributeName = hypenColonToCamelCase(attr); } } // 3 const name = getPropName(originalTag, attributeName); // 4 if (name === 'style') { result[name] = convertStyle(attrs.style!); } // 5 else { const value = attrs[attr] const isBooleanAttribute = value === '' || String(value).toLowerCase() === attributeName.toLowerCase(); result[name] = isBooleanAttribute ? true : value; } return result; }从代码分析:通过正则 /^on.*/.test(attr) 判断是否内联事件,如果是则忽略掉(所有内联事件都不会生效)。转化除了 data-和aria- 并且不在preserveAttributes 数组内的属性成驼峰式。把html属性转化为符合React规范的属性,具体如何转化的下面提供了一个JSON文件:{ "for": "htmlFor", "class": "className", "acceptcharset": "acceptCharset", "accesskey": "accessKey", "allowfullscreen": "allowFullScreen", "autocomplete": "autoComplete", "autofocus": "autoFocus", "autoplay": "autoPlay", "cellpadding": "cellPadding", "cellspacing": "cellSpacing", "charset": "charSet", "classid": "classID", "classname": "className", "colspan": "colSpan", "contenteditable": "contentEditable", "contextmenu": "contextMenu", "crossorigin": "crossOrigin", "datetime": "dateTime", "enctype": "encType", "formaction": "formAction", "formenctype": "formEncType", "formmethod": "formMethod", "formnovalidate": "formNoValidate", "formtarget": "formTarget", "frameborder": "frameBorder", "hreflang": "hrefLang", "htmlfor": "htmlFor", "httpequiv": "httpEquiv", "inputmode": "inputMode", "keyparams": "keyParams", "keytype": "keyType", "marginheight": "marginHeight", "marginwidth": "marginWidth", "maxlength": "maxLength", "mediagroup": "mediaGroup", "minlength": "minLength", "novalidate": "noValidate", "radiogroup": "radioGroup", "readonly": "readOnly", "rowspan": "rowSpan", "spellcheck": "spellCheck", "srcdoc": "srcDoc", "srclang": "srcLang", "srcset": "srcSet", "tabindex": "tabIndex", "usemap": "useMap", "viewbox": "viewBox" }转行内样式成StyleObject;转化布尔属性什么是布尔属性❓总结htmr内部对html字符串进行dom转换,接着递归遍历所有节点,对节点(和属性)过滤、转换,再通过React.createElement()把字符串转成React组件。作者:路一直在_走链接:https://www.jianshu.com/p/36639da716e7来源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2021年09月11日
274 阅读
0 评论
0 点赞
2021-09-09
ADODB.Connection 错误 800a0e7a 未找到提供程序。该程序可能未正确安装解决方法
很久没有处理ASP网站,最近有个老网站换服务器需要处理一下,老网站的服务器已经处于无法打开的情况,换上去后报错,原来是很久以前解决过的问题,但是已经忘记了,解决后做个备忘录,防止下次再出问题。 Windows2008系统 IIS7.5 调试ASP(aspcmsgbk25) 错误号:3706 提示 “未找到提供程序 该程序可能未正确安装”解决办法 有两种报错形式一、错误号:3706 错误描述:未找到提供程序。该程序可能未正确安装。二、“ADODB.Connection 错误 '800a0e7a' 未找到提供程序。该程序可能未正确安装。 ”错误的原因在于在64位系统中,IIS7应用程序池默认没有启用32位程序,也就是说如果使用的是64位操作系统,而没有64位的Jet 4.0驱动程序,那么就要在IIS7中启用32位程序。解决方法如下:Internet信息服务(IIS)管理器 - ‘应用程序池’ - 右边操作中选择‘设置应用程序池默认设置..’,在‘常规’中设置‘启用 32 位程序’为True。如下图:
2021年09月09日
499 阅读
0 评论
0 点赞
2021-09-08
C#插件火车头采集器动态切换代理IP,及自动切换UserAgent
通过代理供应商接口,实时获取代理IP,每个IP使用1分钟,1分钟后重新获取新IP。整合网上抄来的随机UserAgent,合成了一个火车头插件。using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using SpiderInterface; using System.Net; using System.IO; namespace PluginSample { public class Plugin1 : IHTTPTamper { string[] agentList =new string[] { "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60", "Opera/8.0 (Windows NT 5.1; U; en)", "Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0", "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.3.4000 Chrome/30.0.1599.101 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36" }; public void CheckCacheDir() { string Dir = "D:\\IPCACHE\\"; if (!Directory.Exists(Dir)) Directory.CreateDirectory(Dir); } public string GetUrlContent(string url) { using(WebClient wc = new WebClient()){ try { return Encoding.GetEncoding("UTF-8").GetString(wc.DownloadData(string.Format(url))); } catch (Exception e) { throw new Exception(e.ToString()); } } } public string ReadTxt() { string Result = ""; try { string filename = "D:\\IPCACHE\\" + DateTime.Now.ToString("yyyyMMddHHmm") + ".txt"; using (StreamReader sr = new StreamReader(filename)) { Result = sr.ReadToEnd(); } } catch { Result = "缓存不存在"; } return Result; } public string WriteTxt(string val) { try { string filename = "D:\\IPCACHE\\" + DateTime.Now.ToString("yyyyMMddHHmm") + ".txt"; using (StreamWriter sr = new StreamWriter(filename)) { sr.Write(val); } } catch { return "fail"; } return "Success"; } public string GetProxyIp(){ string ProxyApi = "代理IP获取的API, 结果应该是 0.0.0.0.0:xxxx"; CheckCacheDir(); string ip = ""; //检查缓存 string ProxyCache = ReadTxt(); if (ProxyCache != "缓存不存在" && ProxyCache != "") { ip = ProxyCache; } else { ip = GetUrlContent(ProxyApi); WriteTxt(ip); } return ip; } /// <summary> /// 处理下载前的request /// </summary> /// <param name="response"></param> public void BeforeRequest(RequestEntry request) { //Console.WriteLine("BeforeRequest:"+request.Url); //request.Referer=""; //request.Headers. Random r = new Random(); string Agent = agentList[r.Next(agentList.Length)]; request.Headers["User-Agent"] =Agent; var proxy = new WebProxy(GetProxyIp(), true); request.WebProxy=proxy; } /// <summary> /// 处理下载完成后的http响应,网址、默认页、多页、内容分页 /// </summary> /// <param name="response"></param> public void AfterResponse(ResponseEntry response) { Console.WriteLine("AfterResponse:" + response.Url); } } }
2021年09月08日
542 阅读
0 评论
0 点赞
2021-09-01
sql 中的 indexOf 与 lastIndexOf
DECLARE @Name NVARCHAR (50) SET @Name = ‘12345.67890ABCDE.FGHIJKLMNOPQRSTUVWXYZTest’ DECLARE @Position INT –sql first indexof SET @Position = CHARINDEX(‘.’, @Name); SELECT SUBSTRING (@Name, @Position+1,LEN(@Name)-@Position) –sql last indexof SET @Position = LEN(@Name) – CHARINDEX(‘.’, REVERSE(@Name)) + 1 SELECT SUBSTRING (@Name, 0, @Position)
2021年09月01日
89 阅读
0 评论
0 点赞
2021-09-01
快速删除node_modules文件夹
前言当安装了较多模块后,node_modules目录下的文件会很多,直接删除整个目录会很慢,下面介绍些快速删除node_modules目录的方法。方法一:使用rimraf模块的命令在全局安装rimraf模块,然后通过其命令来快速删除node_modules目录:npm install rimraf -g rimraf node_modules方法二:使用命令来删除目录Windows下使用rmdir命令 首先在cmd窗口中进入到node_modules文件夹所在的路径,接着执行命令:rmdir /s/q node_modules Linux下使用rm命令 rm -f /node_modules
2021年09月01日
296 阅读
0 评论
0 点赞
1
...
13
14
15