06月12, 2017

jsx解析

前段时间有同事让我把之前写的Modal组件,将里面的content参数能够支持jsx语法。

于是乎开始查阅一些资料,查到几个相关的:

上面几个都是建立在babel5的基础上,如果使用babel7(默认安装),会报以下的类似错误:

babel-error

前面两个都是利用了jsx-runtime的register方式。

一个是:

var renderer = jsx.register('DOM', {
  before: function(element) {

  },
  tags: {
    '*': {
      enter: function(tag, props) {

      },
      leave: function(parent, tag) {

      },
      child: function(child, parent) {

      },
      children: function(children, parent, tag) {

      }
    }
  }
});

另外一个是:

var renderer = jsx.register('HTML', {
  tags: {
    '*': {
      enter: function(tag, props) {

      },
      leave: function(parent, tag) {

      },
      child: function(child, parent) {

      },
      props: function(props) {

      },
      children: function(children, parent, tag) {

      }
    }
  },
  after: function(tag) {

  }
});

看起来比较像之前的parse-html的语法糖。

第三个在文章中已经讲的比较清楚了。如果要在项目中使用babel-loader 7的话,配置则要写成这样的:

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

官方所言,它会将

var profile = <div>
  <img src="avatar.png" className="profile" />
  <h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;

解析成

var profile = h( "div", null,
  h("img", { src: "avatar.png", className: "profile" }),
  h("h3", null, [user.firstName, user.lastName].join(" "))
);

当然h需要我们自己去实现,下面简单看一下文中作者对h函数的实现:

class VNode {
    constructor(nodeName, attributes, children) {
        this.nodeName = nodeName;
        this.attributes = attributes;
        this.children = children;
    }
}

function render(vNode, parent) {
    let builtDOM = buildDOMByVNode(vNode);
    parent.appendChild(builtDOM);
    return builtDOM;
}

function buildDOMByVNode(vNode) {
    if (typeof vNode === 'string') {
        return document.createTextNode(vNode);
    }

    let {nodeName, attributes: attrs, children} = vNode;
    if (typeof nodeName === 'string') {
        let node = document.createElement(nodeName);
        if (attrs) {
            for (let key in attrs) {
                if(!attrs.hasOwnProperty(key)) continue;
                setAttributes(node, key, attrs[key]);
            }
        }
        if (children) {
            children.forEach(child => {
                let subNode = buildDOMByVNode(child);
                node.appendChild(subNode);
            });
        }
        return node;
    }
}

function h(nodeName, attributes, ...args) {
    let children = args.length ? [].concat(...args) : null;
    return new VNode(nodeName, attributes, children);
}


function setAttributes(node, attr, value) {
    node.setAttribute(attr, value);
}

export default {
    render,
    h
}

本文链接:www.my-fe.pub/post/jsx-parse.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。