乐趣区

关于react.js:2020前端面试系列之JSX是什么

前言

家喻户晓 React Native 开发中,页面 View 书写布局采纳了 React 的 JSX 语法,而在 ReactNative 面试中可能会遇到无关 JSX 相干的面试题,明天和大家分享无关 JSX 的常识,为你的面试助一臂之力。

JSX 的定义

JSX 到底是什么?咱们先看看 React 官网的定义。

JSX is a syntax extension to JavaScript. It is similar to a template
language, but it has full power of JavaScript. JSX gets compiled to
React.createElement() calls which return plain JavaScript objects
called“React elements”.
JSX 是 JavaScript 的一种语法扩大,相似一种模板语言,然而它领有 JavaScript 的全副能力。JSX 被编译成 React.createElement(), React.createElement()返回一个名为“React element”的 JavaScript 对象。

从以上定义能够看到 JSX 是作为一种扩大存在的,那就会呈现在低版本的浏览器或者其余开发环境中的兼容性问题。怎么解决这个问题呢?下面定义中也提到了,JSX 被编译成 React.createElement()并返回一个 js 对象。

JSX 编译工具 -Babel

将 JSX 编译成 js 对象就是由 Babel 实现的。
Babel 官网的定义:

Babel 是一个工具链,次要用于将 ECMAScript 2015+ 代码转换为以后和旧版本浏览器或环境中向后兼容的 JavaScript 版本。

比方在 ES2015 中呈现的箭头函数,转成 ES5 环境的反对

// Babel Input: ES2015 arrow function
[1, 2, 3].map((n) => n + 1);

// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {return n + 1;});

相似的,Babel 也能够编译 JSX 语法。

Babel can convert JSX syntax! Check out our React preset to get
started. Use it together with the babel-sublime package to bring
syntax highlighting to a whole new level.

如下一段代码是 ReactNative 经典的入门 Hello World.

import React from 'react';
import {Text, View} from 'react-native';

const HelloWorldApp = () => {
  return (
    <View
      style={{
        flex: 1,
        justifyContent: "center",
        alignItems: "center"
      }}>
      <Text>Hello, world!</Text>
    </View>
  )
}
export default HelloWorldApp;

咱们将布局文件应用 Babel 工具编译一下, 看看编译后的代码是什么样子的

从编译后果能够看到,所有的 JSX 标签都被编译成了 React.createElement 调用了,所以咱们书写 JSX 其实就是在写 React.createElement()函数调用。

JSX 形容小结

JSX 的正确形容应该是它是 JavaScript 调用函数 React.createElement()的语法糖。

为什么 React 应用 JSX

在下面剖析中咱们看到通过 Babel 转换 JSX 后其实就是 React.createElement 的调用,为什么咱们不间接应用 React.createElement,而要应用 JSX 语法糖呢?
其实从下面 Babel 编译截图上能够看到,布局中只有两个元素 View,Text,间接写 React.createElement 的代码就很多了,如果是很多元素的嵌套,那画面没法设想了,首先代码浏览体验不好,布局的嵌套也十分的凌乱。相比较而言 JSX 就显得层次分明,嵌套关系清晰。

论断:应用 JSX 语法糖能够应用开发人员应用类 Html 的标签创立虚构 DOM 进行布局,既进步了开发效率和体验,也升高了学习老本。

JSX 是如何映射为虚构 DOM 的

咱们曾经晓得了 JSX 会通过 Babel 编译成 React.createElement()调用,咱们看一下这个办法的源码实现:

function createElement(type, config, children) {
  var propName = void 0;

  // 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;}
    if (hasValidKey(config)) {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, childen。

  • type:标识节点的类型。能够是标记名字符串(例如 ’div’ 或 ’span’)、React 组件类型(类或函数)或 React 片段类型。
  • config: 组件的所有属性以键值对的模式存储在 config 中,以对象的模式传递。
  • childen: 组件的嵌套内容,也就是子元素,子节点,也是以对象的模式进行传递。

createElement 函数次要做了如下工作:
1. 依据 config,解决 key, ref, self, source 的赋值工作
2. 遍历 config,刷选适宜的属性放入到 props 中
3. 获取子元素放入到 children 中
4. 解决 defaultProps
5. 最终调用 ReactElement 来创立元素。

如何渲染到 DOM

ReactElement 是通过 React.render()办法渲染到 DOM。
上面是一个示例

const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

render()

ReactDOM.render(element, container[, callback])

ReactDOM.render 函数承受三个参数,第一个是代表元素或者节点,第二个 container 是一个真是的 DOM 节点,作为一个 DOM 容器,用于蕴含渲染的元素内容。

总结

JSX 只是一种语法糖,你也能够不应用 JSX 进行书写页面布局,然而应用 JSX 会使页面布局层次分明,嵌套逻辑清晰,不便前端开发人员应用相熟的类 Html 标签进行开发,调高了开发体验和效率,并且也提供了更多有用谬误和正告信息。
通过以上内容,置信面试的时候遇到此类问题,肯定能够答复的比拟深刻了。

感觉文章不错的,给我点个赞哇,关注一下呗!
技术交换可关注公众号【君伟说】,加我好友一起探讨
交换群:wayne214(备注技术交换)邀你入群,抱团学习共提高

退出移动版