实战json、html、jsx的互转

简介: # jsx2html ## 场景 将下面的jsx转换为html ```javascript const items = ['one', 'two', 'three']; const SearchData = ({ data = [] }) => { let list = null; if (data.length) { list = data.map((l,

jsx2html

场景

将下面的jsx转换为html

const items = ['one', 'two', 'three'];
const SearchData = ({ data = [] }) => {
  let list = null;
  if (data.length) {
    list = data.map((l, k) => (<p key={k}>{l}</p>));
  } else {
    list = (<p>暂无数据</p>);
  }

  return (
    <div className="mod-search-data">
      <div>
        <h3>匹配的员工:</h3>
        <div>{list}</div>
      </div>
    </div>
  );
};

const jsx = (
  <div className="foo">
    <p>列表展示 {items.length} 项:</p>
    <div>
      <p>SEARCH DATA:</p>
      <SearchData data={items} />
    </div>
  </div>
);

方案

方案一:自己遍历

所有的jsx你拿到的时候,都已经是 Babel 帮你转义过的了。所以,你其实拿到的是转义后的对象。所以你只需要将这对象转成你想要的结果。我们知道 Props 除了 key、ref、children 这几个特殊的,剩下的都对应到 dom 的 attribute

做法

1、获取 displayName 作为 Tag
2、处理 props 作为 attribute
3、如果有children,则重复1、2、3、4,遍历 children,作为子元素
4、拼装 html 字符串

代码
function getDisplayName(ele) {
  if (typeof ele.type === 'string') {
    return ele.type;
  }
  return ele.type.name || ele.type.displayName || 'No Name';
}

function getAttrs(attrs) {
  return Object.keys(attrs).map(attr => (attr === 'children' ? '' : `${attr}="${attrs[attr]}"`)).join('');
}

function transfer(ele) {
  if (typeof ele === 'string' || typeof ele === 'number') {
    return ele;
  }

  const props = ele.props || {};
  const children = React.Children.toArray(props.children || []);

  const html = children.map(transfer);
  const tag = getDisplayName(ele);

  return `<${tag} ${getAttrs(props)}>${html.join('')}</${tag}>`;
}

console.log(transfer(jsx));

// 如果函数式的组件你也需要解析的话,则需要执行这个函数
// congsole.log(transfer(SearchData({items: data})))
类库

react-element-to-jsx-string

方案二:通过 Babel 直接转

我们可以指定 Babel 在编译的时候调用某个函数。我们可以通过这个函数来生成我们需要的操作。

做法
{
  "plugins": [
    ["transform-react-jsx", {
      "pragma": "dom" // default pragma is React.createElement
    }]
  ]
}

但是这种方法修改全部的 babel 转换行为。非常不推荐

  • 方法二

在代码中加一个注释/* @jsx h /,告诉 Babel ,用 h 函数处理 Babel 编译后的行为。参考WTF is JSX

代码
/** @jsx h */
function getDisplayName(ele) {
  if (typeof ele === 'string') {
    return ele;
  }
  return ele.name || ele.displayName || 'No Name';
}

function h(name, attrs, ...children) {
  const html = Array.isArray(children) ? children.join('') : children;

  console.log('###################################');
  console.log('name:', name);
  console.log('attrs:', attrs);
  console.log('children:', children);
  
  const attr = Object.keys(attrs || {}).map(a => `${a}='${attrs[a]}'`).join(' ');

  return `<${name} ${attr}>${html}</${name}>`;
}

console.log(jsx);
类库

vhtml

jsx2json

与上面的情况了类似,如果我们要将那部分 jsx 转换为 json 格式的怎么办呢?答案很简单,不用刻意去转(?!)。因为 Babel 已经帮你转过了。你需要做的是把 Babel 编译后的 json 转成你想要的格式。此外,刚才的两种方案也是生效的。不同的是,之前的返回值是一段 html 文本,现在需要返回 json 格式的。我们以上面的方案二举例:

/** @jsx h */

function h(name, attrs, ...children) {
  /*
  // 函数式的组件(functional component)请根据需要转换
  if (typeof name === 'function') {
    return name(attrs);
  }
  */

  return {
    tag: name,
    attrs,
    children,
  };
}
console.log(jsx);

html2jsx

场景

将下面的 html 转换为 jsx:

const html = `
  <div className='foo' id="18" data-node="12">
    <h1>Hi!</h1>
      <p>Here is a list of 3 items:</p>
    <ul>
      <li>one</li>
      <li>two</li>
      <li>three</li>
    </ul>
  </div>
`;

方案

将 html 转为 jsx,实际上就是用 React.createElement 将 html 的结构重新生成一下,做到without jsx

做法

1、将 html 片段转成 dom
2、读取 dom 的 attributes, 处理特殊的 attribute,作为 ReactElement 的 props
3、读取 dom 的 tagName, 作为 ReactElement 的 type
4、如果 dom 有 children,则重复 2、3、5步,将返回值作为 ReactElement 的 children
5、返回 React.createElement(type, props, children)

代码
const div = document.createElement('div');
div.innerHTML = html;

function makeArray(arrayLike) {
  return [].slice.call(arrayLike, 0);
}

function getProps(ele) {
  const props = {};
  makeArray(ele.attributes).forEach(({ name, value }) => {
    props[name === 'class' ? 'className' : name] = value;
  });
  return props;
}

// Node.nodeValue https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeValue
// Node.nodeName  https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeName
// Element.tagName https://developer.mozilla.org/zh-CN/docs/Web/API/Element/tagName
function transfer(ele) {
  if (ele.tagName) {
    return React.createElement(ele.tagName, getProps(ele), makeArray(ele.childNodes).map(transfer));
  }
  return ele.nodeValue;
}

ReactDOM.render(transfer(div.firstElementChild), document.body);
类库

react-magic

html2json

将 html 转为 json的做法与上面转为 jsx 的做法雷同。只不过第 5 步返回的是一个 json 对象,而不是一个 ReactElement。

function getProps(ele) {
  const props = {};
  makeArray(ele.attributes).forEach(({ name, value }) => {
    props[name === 'class' ? 'className' : name] = value;
  });
  return props;
}

function transfer(ele) {
  if (ele.tagName) {
    return {
      type: ele.tagName,
      props: getProps(ele),
      children: makeArray(ele.childNodes).map(transfer),
    };
  }

  return ele.nodeValue;
}

console.log(transfer(div.firstElementChild));
目录
相关文章
|
10天前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
27 1
|
2月前
|
JSON 前端开发 JavaScript
|
2月前
|
缓存 Java 应用服务中间件
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
这篇文章详细介绍了在SpringMVC中创建JSP页面的全过程,包括项目的创建、配置、Tomcat的设置,以及如何实现页面跳转和配置模板解析器,最后还对比了JSP和HTML模板解析的差异。
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
|
2月前
|
存储 缓存 移动开发
不来看一看HTML请求后端性能优化的实战总结吗?
本文主要总结了在ICBU的核心沟通场景下服务端在此次性能优化过程中做的工作,供大家参考讨论。
|
2月前
|
JSON Java API
解码Spring Boot与JSON的完美融合:提升你的Web开发效率,实战技巧大公开!
【8月更文挑战第29天】Spring Boot作为Java开发的轻量级框架,通过`jackson`库提供了强大的JSON处理功能,简化了Web服务和数据交互的实现。本文通过代码示例介绍如何在Spring Boot中进行JSON序列化和反序列化操作,并展示了处理复杂JSON数据及创建RESTful API的方法,帮助开发者提高效率和应用性能。
68 0
|
2月前
|
JSON JavaScript 数据格式
html jquery from 表单提交 application/x-www-form-urlencoded 改成 json
html jquery from 表单提交 application/x-www-form-urlencoded 改成 json
32 0
|
4月前
|
移动开发 前端开发 JavaScript
HTML5+CSS3+JavaScript网页实战
HTML5+CSS3+JavaScript网页实战
|
4月前
|
JSON fastjson 数据格式
使用jackson和fastjson实现list与json互转
使用jackson和fastjson实现list与json互转
|
4月前
|
前端开发 安全 数据安全/隐私保护
Web实战丨基于django+html+css+js的在线博客网站
Web实战丨基于django+html+css+js的在线博客网站
68 2
|
4月前
|
数据库 数据安全/隐私保护 Python
Web实战丨基于Django与HTML的新闻发布系统(二)
Web实战丨基于Django与HTML的新闻发布系统(二)
37 1

热门文章

最新文章

下一篇
无影云桌面