为什么 React 需要 JSX
JSX 由来
React 通过创建虚拟元素来管理整个虚拟 DOM
虚拟元素与真实元素是对应的,它的构建和更新在内存中完成(废,过程不会反映给真实 DOM。
React 的虚拟元素分为:1-DOM 类。2 - 组件类。这些元素与 JSX 密切联系。
在 JSX 代码中,组件的 tag 名是大写字母开头,而那些 DOM 标签的 tag 名则以小写字母开头。
1 DOM 元素
一个 Web 页面由 HTML 元素嵌套组合,使用 JS 怎么描述这个嵌套?
我们可以使用简单的 JSON 完成。
例如,一个按钮的 HTML 代码:
<button class="btn btn-blue">
<em>Confirm</em>
</button>
使用 JSON 表示这个按钮:
{
type: 'button',
props: {
className: 'btn btn-blue',
// 子元素可以是一个数组
children: [
{
type: 'em',
props: {
children: 'Confirm'
}
},
]
}
}
这样就可以在 JS 中创建虚拟 DOM 元素了。
这些对象表示的元素就可以指示 React 如何去显示真实的 DOM。
2 组件元素
既然可以用 JS 代码表示 DOM 元素了,那就可以进一步封装上面的” 虚拟 DOM“按钮。
const Button = ({ color, text }) => {
return {
type: 'button',
// 属性又是一个对象
props: {
className: `btn btn-${color}`,
// 按钮的子元素是一个字符串
children: {
type: 'em',
props: {
children: text
}
}
}
}
}
我们可以很方便地调用 Button({ color:'red', text:'ENG' })
生成一个按钮实例。
再想一想,其实还可以通过 ** 标签的方式 ** 创建一个按钮实例,标签名就是 Button,标签的元素属性就是参数,此时就具备了标签名,属性这两大条件,这样的方式构建的元素称为 组件元素
。
这也是 React 的核心思想之一。因为有公共的表达方法,我们就可以让元素们彼此嵌套或混合。这些层层封装的组件元素,就是所谓的 React 组件,最终我们可以用递归渲染的方式构建出完全的 DOM 元素树。
可以以这个按钮最为原型,继承出更多按钮。
例如,封装一个表示危险操作的按钮:
const DangerButton = ({ text }) => (
{
type: Button,
props: {
// 红色的按钮
color: 'red',
children: text
}
}
)
接着,我们可以很轻松地运用它,继续封装新的组件元素:
const DeleteAccount = () => {
type: 'div',
props: {
className: 'delete-account',
children: [
{
type: 'p',
props: {
children: '确定吗?'
}
},
{
type: Deletebutton,
props: {
children: '确定'
}
}
]
}
}
这个 DeleteAccount 只有两个子元素,就显得比较冗余,当遇到更大的组件,就难以阅读了。
这让我们想起使用 HTML 书写结构时的畅快感受,JSX 语法为此应运而生。假如我们使用 JSX 语法来重新表达上述组件元素,只需这么写:
const DeleteAccount = () => {
<div>
<p > 确定吗?</p>
<DangerButton > 确定 </DangerButton>
</div>
}
JSX 将 HTML 语法直接加入到 JavaScript 代码中,再通过翻译器(babel)转换到纯 JavaScript 后由浏览器执行。
JSX 的出现为我们省去了这个烦琐过程,使用 JSX 写法的代码更易于阅读与开发。
JSX 语法
标签
- 定义标签时,有且只能有一个标签包裹 JSX 结构。因为这些 JSX 要被使用 React.createElement 调用,最外层没有被包裹,显然无法转译成方法调用。
- 标签必须闭合
属性
HTML 存在的那些标签,在 JSX 里的属性不变,class 和 for 除外。
由于 JSX 内可以写 JS 代码和 HTML 代码,但是 HTML 的
for class
和 JS 关键字冲突,所以将 HTML 代码的for class
改为htmlFor className
HTML 类标签的 data-
自定义属性也是有效的。
组件标签的属性是完全自定义的属性,也可以理解为实现组件所需要的参数。
布尔属性
布尔属性如果缺值,则默认是 true
例如,<CheckBox checked={true} />
可以简写属性为 <CheckBox checked/>
组件名的命名空间
- JSX 可以使用命名空间,解决组件名称相同问题。
const App = () => ( <MUI.PaisedButton label="Default" /> );
JSX 内的注释
虽然 JSX 里可以写 JS,但是与 JSX 注释与 JS 不同。
在标签外,可以在 { /**/ }
内写那种多行注释,不能写单行注释。
在组件标签内,可以直接写多行注释
const App = (
<Nav>
{/* 节点注释 */}
<Person
/* 多行
注释 */
name={window.isLoggedIn ? window.name : ''}
/>
</Nav>
);
HTML 转义
一些 HTML 实体字符无法被正确显示。例如 ©
有几种解决办法:
- 直接使用 UTF-8 字符 ©;
- 使用对应字符的 Unicode 编码查询编码;
- 使用数组组装
<div>{['cc', <span>©</span>, '2015']}</div>;
- 直接插入原始的 HTML
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。