深入理解JSX

更新日期: 2022-07-01阅读: 903标签: jsx

What is JSX ?

官方定义:JSX 是 react.createElement(components, props, ...children) 函数语法

<Mybutton color="blue" shadowSize={2}>
Click Me
</Mybutton>

上方函数会被编译为下方代码

React.createElement(
  Mybutton,
  {color: 'blue', shadowSize: 2},
  'Click Me'
)

打开 React 的源码,找到 createElement 函数:

function createElement(type, config, children) {
  var propName; // Reserved names are extracted

  var props = {};
  var key = null;
  var ref = null;
  var self = null;
  var source = null;

  if (config != null) {
    if (hasValidRef(config)) {
      ref = config.ref;

      {
        warnIfStringRefCannotBeAutoConverted(config);
      }
    }

    if (hasValidKey(config)) {
      {
        checkKeyStringCoercion(config.key);
      }

      key = '' + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object

    for (propName in config) {
      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
        props[propName] = config[propName];
      }
    }
  } // Children can be more than one argument, and those are transferred onto
  // the newly allocated props object.

  var childrenLength = arguments.length - 2;

  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    var childArray = Array(childrenLength);

    for (var i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }

    {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }

    props.children = childArray;
  } // Resolve default props

  if (type && type.defaultProps) {
    var defaultProps = type.defaultProps;

    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }

  {
    if (key || ref) {
      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;

      if (key) {
        defineKeyPropWarningGetter(props, displayName);
      }

      if (ref) {
        defineRefPropWarningGetter(props, displayName);
      }
    }
  }

  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}

从源码中,我们可以看到 createElement 函数接收三个参数: type(标签类型)、config(标签中的属性)、children(子标签)

但是,在编写 JSX 的时候,一个标签通常会包含多个子标签,那么该函数是如何接收这些子标签呢 ?

我们关注源码的这一部分:

  var childrenLength = arguments.length - 2;

  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    var childArray = Array(childrenLength);

    for (var i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }

    {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }

    props.children = childArray;
  } // Resolve default props

我们知道,arguments 对象中包含有所有参数,那么 childrenLength 就是排除前两个参数之外剩余参数的个数

若 childrenLength 为 1,则只有一个子元素(可以是文字也可以是新的JSX) 若 childrenLength 大于 1,则创建一个长度为 childrenLength 的数组,利用 for 循环将arguments 中的对象添加到数组中

简化版 React.createElement

ReactElement 对象定义:

function ReactElement(type, key, props) {
    return {
        $$typeof: Symbol.for('react.element'),
    type,
    key,
    props
    }
}

createElement() 函数实现:

function createElement(type, config, children) {
    const props = {};
  if (config) {
        // 将 config 中的键值对添加到 props 中
    for (propName in config) {
      if (hasOwnProperty.call(config, propName)) {
        props[propName] = config[propName];
      }
    }
  }

  const childrenLength = arguments.length - 2;
  // 多个children使用数组的形式
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[2 + i];
    }
    props.children = childArray;
  }
  
  return ReactElement(type, null, props);
}

当仅有一个 dom 节点时,调用 createElement 函数:

let a = createElement(
  'div',
  {width:'20px', height: '20px'},
)

打印出a,其结果为:

{
  '$$typeof': Symbol(react.element),
  type: 'div',
  key: null,
  props: { width: '20px', height: '20px' }
}

由于并没有子元素,所以 props 中没有 children 属性

当父节点含有多个子节点时:

let a = createElement(
  'div',
  {width:'20px', height: '20px'},
  createElement(
    'p'
  ),
  createElement(
    'a'
  ),
)

打印出a,其结果为:

{
  '$$typeof': Symbol(react.element),
  type: 'div',
  key: null,
  props: { width: '20px', height: '20px', children: [ [Object], [Object] ] }
}

可以看到,当含有多个子元素时,children 以数组的形式存储这些子元素。

链接: https://fly63.com/article/detial/11837

vue2.0写组件使用jsx语法_webpack在vue项目中支持jsx

Vue 2.0中的render中使用JSX,由于Vue框架并没有特意地去支持JSX,Vue和JSX为什么能配合在一起使用呢? 很简单, 因为Vue支持虚拟DOM, 你可以用JSX或者其他预处理语言,只要能保证render方法正常工作即可。

jsx是什么?_JSX语法简介

JSX就是Javascript和XML结合的一种格式,利用HTML语法来创建虚拟DOM。将XML语法直接加入JS中,通过代码而非模板来高效的定义界面。之后JSX通过翻译器转换为纯JS再由浏览器执行。

JSX 这么6?

本文会先解释一下JSX的工作原理,再介绍一下如何用不寻常的方式来使用JSX。

如何在iview组件中使用jsx

最近选用的框架iview表单组件的render写法让人有点不习惯,尤其是在写比较复杂的逻辑的时候,还是感觉模 板式的写法比较方便且可读性较强。而render函数除了支持配置写法外,还支持jsx的写法。由于之前有用过react,因此对jsx并不陌生,可以直接上手。

react本质:JSX如何转化为javascript

react中基本都使用JSX来开发,但JSX其实是javascript的一种语法糖。语法糖就是提供了一种全新的方式书写代码,但是其实现原理与之前的写法相同。

React和JSX基础

脚手架工具:选用React官方推荐的脚手架工具create-react-app,安装npm install create-react-app -g。项目初始化步骤:

可替代的JSX

不仅仅是在React(或受JSX启发模板),对于在各种框架中进行模板化,JSX是如今一个非常受欢迎的选择。然而,如果你不喜欢使用JSX,或者你的项目想避免使用它,又或者只是受好奇心驱使

Vue中jsx的最简单用法

JSX就是Javascript和XML结合的一种格式。React发明了JSX,利用HTML语法来创建虚拟DOM。当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析.

JSX在render函数中的应用

JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模版语言,但它具有 JavaScript 的全部功能。Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。

React中JSX和虚拟dom

这被称为 JSX,是一个 JavaScript 的语法扩展。建议在 React 中配合使用 JSX,JSX 可以生成 React “元素”,而且JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模版语言,但它具有 JavaScript 的全部功能。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!