JSX浅学

72 阅读1分钟

JSX

什么是JSX

Javascript的语法拓展,既不是HTML也不是字符串,具有Javascript所有功能。JSX可以生成React元素。

为什么使用JSX

React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合。即在JSX中,需要包含如下内容:绑定事件的处理,订阅状态变化及更新UI,准备好UI展示的数据。

JSX表示对象

Babel中会把JSX转译成React.createElement()函数进行使用:

const element = <div>
    <h1 className='jsx'>
        Hello world!!
    </h1>
</div>

// babel转译后

const element = React.createElement(
    'h1',
    {className: 'jsx'},
    'Hello world'
)

// 等效于
const element = {
  type: 'h1',
  props: {
    className: 'jsx',
    children: 'Hello, world!'
  }
};

JSX 可以防止XSS攻击

React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串:

<img src="empty.png" onerror="alert(xss)" />

// 转义后
&lt;img src=&quot;empty.png&quot; onerror=$quot;alert(%#x27;xss%#x27;)&quot;&gt

在熟悉JSX后,如果我们尝试使用特殊构造的JSX转义对象由服务端进行XSS注入攻击,也是无法成功的:

const jsonStr = `{
  "ref": null,
  "type": "body",
  "props": {
    "dangerouslySetInnerHtml": {
      "_html": "<img src=\"empty.png\" onerror=\"alert('xss')\" />"
    }
  }
}`

const parseData = JSON.parse(jsonStr)

render() {
  return <span> {parseData} </span>
}

上述代码执行会报错:

Uncaught (in promise) Error: Objects are not valid as a React Child...

在JSX转义的过程中,会在属性中加入使用Symbol.for创建的唯一$$typeof标识,一旦打算使用xss攻击生成React元素时,ReactElement在运行中发现不存在$$typeof或者值不同时,就会报错不继续执行。$$typeof是个symbol属性,进行JSON.parse()值会丢失

参考资料:JSX 简介

参考资料:容易遗忘的$$typeof属性