用domString改造React的JSX
看了几天React,总觉得别扭,jsx看起来美好,但是对熟悉html的人来说,各种别扭,加之这些天对es6的了解加深,觉得es6的模板字符串配合domString其实也并不差。
学习React的前几篇,就提到JSX的解析不要在生产环境下使用babel.js
看来jsx非要用node.js本地先编译啥的。
用react就是为了个简单的绑定,结果用了工具,还要用工具的工具来使用工具,nnd,及其不爽。
正好吃饱撑的消化消化,想在js环境下,直接用domString替换JSX。以便以后简单利用react,直接引用react.js无需再烦jsx的问题。
替换jsx有两种思路。
思路1:直接将domString转换为React使用的虚拟dom,再传递给ReactDOM.render进行渲染。
思路2:将domString用React的函数转换为虚拟dom。
第一种思路有点问题在于,就算我完全破解了虚拟dom的内容,react一改,就完全不能用了。
第二种思路相对就简单了,根据babel转换出来的js代码,写个函数,用react的函数,转虚拟dom,react只要不是大变化,理论上是该保持兼容的。
决定使用第二种思路:直接上代码
先来个将domString转换为dom的函数
function getDom(domString){
let mainDom = document.createElement("div")
mainDom.innerHTML = domString
return mainDom.firstChild
}
再将dom通过react的函数转换为虚拟dom,为啥先转为dom呢,主要式懒,js操作dom的函数多。O(∩_∩)O
function getReactDom(domNode,idx=0){
if (typeof(domNode) === 'string'){domNode = getDom(domNode)};
let domChild = [];
// 不加个key,react运行时候会报警告。我就是把虚拟dom和用babel转出来的虚拟dom一模一样都没用。
let domAttrs = {key:idx};
// 属性patch,class-> className
if (domNode.attributes && domNode.attributes.length){
for (let attr of domNode.attributes) {
let n={};
let newName = (attr.name === "class") ? "className" : attr.name;
n[newName]=attr.value;
domAttrs = {...domAttrs,...n};
};
};
// 只处理nodeType是1,3的节点。1是Element,3是TextNode,8是html注释(jsx有html注释会报错,这里直接忽略)
if (domNode.childNodes.length){
for (let dC of domNode.childNodes) {
switch(dC.nodeType){
case 1:
idx ++;
domChild.push(getReactDom(dC,idx));
break;
case 3:
if(dC.nodeValue.trim()) domChild.push(dC.nodeValue);
break;
};
};
};
if (domChild.length ===1){domChild = domChild[0]}
return React.createElement(domNode.tagName.toLowerCase(),domAttrs,domChild)
};
写个简单的react函数
function Rsrvn(props){
let vDom;
switch (props.rslt){
case "succ":
vDom = getReactDom(getDom(`<div id="ab" class="col-xs-10 col-sm-8 col-xs-offset-1 col-sm-offset-2">
f3 <span>f4</span> success<!-- 文档注释部分 -->
</div>`));
break;
case "fail":
vDom = getReactDom(getDom(`<div id="ab" class="col-xs-10 col-sm-8 col-xs-offset-1 col-sm-offset-2">
f5 <span>f6</span> fail
</div>`));
break;
default:
vDom = getReactDom(getDom(`<div id="ab" class="col-xs-10 col-sm-8 col-xs-offset-1 col-sm-offset-2">
请填写相关信息!
</div>`));
}
return vDom
};
弄个数据随便测试一下:
myrslt = {rslt:"succ"};
let element = Rsrvn(myrslt);
ReactDOM.render(
element,document.getElementById("aabb")
);
看着全部都是函数写法的react,顺眼多了。
嗯,开篇我就说了,这个纯粹吃饱撑了,不接受批评。嗯觉得我代码还能优化优化,更简洁,更有效率,可以说一说。
最后:版权声明
版权所有,转载、使用代码均可,但需留本文地址供有想法的同志溯源讨论。