一、JSX的使用思想
React 的发明有一个目标是让DOM元素组成可复用的组件。但是 React 是 js 啊,用 js 写可复用的 html 组件,最好的方式是什么?用 js 对象把组件写成一个个对象,这样每次复用组件的时候,实例化一个对象就行。例如要写一个 button:
<button class="btn btn-blue">
<em>Confirm</em>
</button>
如果转换成 json 对象,那么是这样的:
{
type: 'button',
props: {
className: 'btn btn-blue',
chidren: [
{
type: 'em',
props: {
chidren: 'Confirm'
}
}
]
}
}
用一个函数封装这个 button 对象,每次调用函数就能生成一个 button 元素:
const Button = ({ color,text}) => {
return {
{
type: 'button',
props: {
className: 'btn btn-blue',
chidren: [{
type: 'em',
props: {
chidren: 'Confirm'
}
}]
}
}
}
}
但是你想啊,组件一写十几二十个的,每次构造这么多对象多不人道啊,既然是写 dom ,为什么我不直接在一个文件里写 dom ,然后通过工具自动解析这个文件,把文件中的 dom 自动解析为一个个 js 对象呢。这个文件,就是 jsx,这个工具,就是 babel,babel 对 es6 -> es5 的编译,正是干这种把 js 抽成 语法树的活,把 jsx 丢进 babel,让 babel 把 jsx 中的组件解析成一个个的 js 对象,美滋滋。
二、 JSX 的基本语法
挑几个印象深刻的写:
- JSX 中既有 DOM 元素又有组件元素,那么 JSX 是如何区分的呢? —— JSX 规定,DOM 元素用小写开头,组件元素用大写开头,这就是为什么组件要用大写开头命名吧。
- JSX 是有命名空间的,防止相同命名组件冲突:
const App = () => {
<MUI.RalseButton label="Default" />
}
- Boolean 属性:省略 Boolean 属性会让 JSX 认为 bool 值设为了
true
:
// 等同于 <Checkbox checked={true} />
<Checkbox checked />
- HTML 转义
JSX 会将所有要实现到 DOM 的字符做转义,防止 XSS ,实践中出现的问题是,一串有 DOM 标签的字符串,想要输出在界面上,让 DOM 标签生效,但是实际结果是 DOM 标签会被转为字符串:
let str = '有问题请咨询客服<a href="xxx">客服</a>';
// 输出 '有问题请咨询客服<a href="xxx">客服</a>'
let rules = () => {
return (
<div>
<a>{str}</a>
</div>
)
}
解决方法是使用 dangerouslySetInnerHTML
,这样就避免了 DOM 被转义:
let rules = () => {
return (
<div>
<a dangerslySetInnereHTML={__html: str}></a>
</div>
)
}
三、 前端的组件化之路
传统的前端组件化方案,组件又叫 UI 组件,通过对交互动作上的抽象,针对这些交互动作,利用 js 操作 html 和 styles 样式来控制。就是先想好在这个组件上会可能有什么交互,针对不同交互产生的结果,修改 html 和 styles。还有就是有简单的生命周期(比如init和组件销毁的destroy)。
这类组件的思想还是哪里需要变化,我就用 js 直接操作 dom ,以操作 dom 为主。
(产生的问题)这种 UI 组件的问题就是,当一个组件交互非常复杂,逻辑非常复杂的时候,我们就要为这个组件预留很多样式 class ,什么 hide,toggle,show这些都算简单的,交互一复杂这类 class 就满天飞。一个组件里要写的方法也就很多,还有很多样本 html 用于发生不同交互后不同 dom 元素的插入。(造成的结果)由此产生了大量的 dom 操作,开发和维护的成本很高。
四、React 与 DOM
React 为了实现在不同端上可运行,在 0.14版本将 dom 从 React 中剥离了出来,这也是为什么会有 ReactDOM 这个东西——专门用来操作 dom 的。ReactDOM 中的 API 只有几个,用来做 DOM 操作:findDOMNode
、unmountComponentAtNode
和 render
。
findDOMNode
既可以用来获取原生 dom 也可以获取 Rea'ct 组件。
render
不是生命周期中的那个 render ,而是在顶层组件要把 Virtual DOM 渲染到浏览器 DOM 的时候才会用到:
ReactDOM.render(<App />, document.getElementById('root'));
unmountComponentAtNode
很少用到,用来做卸载操作。
网友评论