实战json、html、jsx的互转

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 在编译的时候调用某个函数。我们可以通过这个函数来生成我们需要的操作。

做法
  • 方法一
    配置 .babelrc
    json
    {
    "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));
时间: 2024-12-09 10:14:22

实战json、html、jsx的互转的相关文章

如何识别一个字符串是否Json格式

前言: 距离上一篇文章,又过去一个多月了,近些时间,工作依旧很忙碌,除了管理方面的事,代码方面主要折腾三个事: 1:开发框架(一整套基于配置型的开发体系框架) 2:CYQ.Data 数据层框架(持续的更新,最近也加入了Sybase的支持) 3:工作流流程图设计器. 由于这三个方面都涉及到Json,所以就谈谈这些天在Json上花下的心思. 关于造轮子: 很多人对于造轮子都会有自己的看法,这里提一下个人的观点:  个人认为: 1:首要是要具备造轮子的能力,然后再讨论造不造与浪不浪.轮子与时间的问题.

Json序列化之.NET开源类库Newtonsoft.Json的研究

原文:Json序列化之.NET开源类库Newtonsoft.Json的研究 一.Json简介                                                                                                                    JSON(全称为JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集. JSON采用完全独立于语言

GSON解析 json转java对象问题

问题描述 GSON解析 json转java对象问题 使用Gson将JSONObject objectObj 对象转换为Charge对象部分代码: Gson gs = new GsonBuilder().setDateFormat("yyyy-MM-dd").create(); Charge charge = gs.fromJson(objectObj.toString(), Charge.class); 问题是结果charge与objectObj结构一致但是某些字段的值不一样了!!!

终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了

前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说过  这么多年 秋天有两点没变 一是还是单身 另外一个就是cyq.data还没开源  终于等到开源了! 也许吧,只有把cyq.data最终开源了,才能解决单身问题,不然我在这上面花的时间太多,都没时间和妹子聊天了.   几个重要网址: 源码SVN地址:https://github.com/cyq11

jsp页面用Highcharts绘制图表实例

Highcharts 提供了比较简单的方式来为网页插入漂亮的.交互式的图标.目前支持各种折线图.区域图.柱状图.散列图,以及几种图的混合使用,此外还支持仪表.地热.雷达.极区.金字塔.瀑布等专业的图表.和收费的FusionCharts和AnyCharts比起来,HighCharts免费(Free-Non-Commercial许可证),并且扁平化的设计感很有优势,并且官方提供了大量的示例供研究. 在jsp页面使用Highcharts 参照教程首先引入jquery库和highcharts.js文件,

C#中如何解决JSON / XML互转的问题

最近在一个POC的项目中要用到JSON和XML的相互转换, 虽然我知道很多类库如JSON.NET具备这种功 能, 但是我还是另辟蹊径的使用Spider Studio结合一个在线工具网站快速实现了这个功能. 在线工具网站: http://www.utilities-online.info/xmltojson 必备工具: Spider Studio (采集工作站): http://www.gdtsearch.com/products.spiderstudio.htm 1. 打开Spider Stud

ASP.NET JSON字符串与实体类的互转换的示例代码

 本篇文章主要是对ASP.NET JSON字符串与实体类的互转换的示例代码进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 还是先封装一个类吧! 这个类网上都可以找到的!有个这个类,一切都将变得简单了,哈哈. 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Runtime.Serialization.Json; using Sys

JSON与String互转的实现方法(Javascript)_javascript技巧

JSON => String: jsonToString: function(obj){ var THIS = this; switch(typeof(obj)){ case 'string': return '"' + obj.replace(/(["\\])/g, '\\$1') + '"'; case 'array': return '[' + obj.map(THIS.jsonToString).join(',') + ']'; case 'object': i

Swift学习笔记(2)网络数据交换格式(XML,JSON)解析 [iOS实战 入门与提高卷]

Swift学习笔记(2)网络数据交换格式(XML,JSON)解析 参考书籍及资源:iOS实战 入门与提高卷 关东升 参考书籍地址 用NSXML来解析XML文档 用TBXML来解析XML文档 用NSJSONSerialization来解析JSON文档 目录 Swift学习笔记2网络数据交换格式XMLJSON解析 目录 用NSXML来解析XML文档 示例文档Notesxml 创建XMLParser类 调用与运行结果 用TBXML来解析XML文档 准备工作 创建XMLParser类 调用与运行结果 用