本文主要讲 React 的诞生以及 JSX形成的由来。
React 的诞生
在Web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而复杂或频繁的DOM操作通常是性能瓶颈产生的原因(如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标)。React为此引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的
因此我们分别使用原生JS和React编写出一个简单的加减器
原生JS
我们一般将操作页面中的DOM分为三步:
- 首先从页面中获取DOM,
- 其次在JS中对这个DOM进行操作,
- 最后把修改好的DOM重新填入到页面中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<span id="result">0</span>
<button id="add">+</button>
<button id="minus">-</button>
</body>
</html>
let result = document.querySelector('#result ')
let add = document.querySelector('#add')
let minus = document.querySelector('#minus')
add.addEventListener('click', function () {
let number = parseInt(result.innerText)
number += 1
result.innerText = number
})
minus.addEventListener('click', function () {
let number = parseInt(result.innerText)
number -= 1
result.innerText = number
})
从上面的JS部分的代码我们可以看出,首先我们从页面中获取span里面的内容,然后点击按钮使用JS操作span里面的内容,然后把操作后得到的结果回填到页面中。这样子看起来很麻烦,而且频繁的操作DOM会影响性能,因此Fackbook的开发者就决定自己写一套前端框架。React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。
React
原生JS中有3步,React程序员觉得这样很麻烦就把从页面取数据去掉。即,直接往页面里填东西,而不需要用从页面里获取数据了,页面上显示的永远是最新生成的数据。
React为此引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新,这也叫做局部更新。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
let number = 0
let onClickButton = () => {
number += 1
render()
}
let onClickButton2 = () => {
number -= 1
render()
}
render()
function render() {
//创建span标签,内容为number,即初始页面span内的数字为0
let span = React.createElement('span',{className:'showMoudle'},number)
//创建button标签,监听点击事件实现加法
let button = React.createElement('button',{onclick:onClickButton},'+')
//创建button2标签,监听点击事件实现减法
let button2 = React.createElement('button',{onclick:onClickButton2},'-')
//添加div标签,将上面所有创建好的标签放入里面作为其子标签。
let div = React.createElement(
'div',{className:'overall'},span,button,button2
)
ReactDOM.render(div,document.querySelector('#root'))
}
JSX形成的由来
上面的代码还是有很多的重复,React设计者觉得这样子还是不太好,就将上面JS中相同的语法声明成一个h。即:
let h = React.createElement
然后用h将它们替换,span、button、button2都只使用了一次,所以把这三个标签直接写进去,即:
let div =
h( 'div', { className: 'overall' },
h('span', { className: 'showMoudle' }, number),
h('button', {onClick: onClickButton}, '+'),
h('button', {onClick: onClickButton2}, '-')
)
这段代码看上去有点像HTML格式,div是父元素,span、两个button是子元素。h代表这里可以转化成标签,正括号(代表<>、反括号)代表</>、className代表标签的命名,即:
let div =
<div class="overall">
<span class="showMoudle">number</span>
<button onClick="onClickButton">+</button>
<button onClick="onClickButton2">-</button>
</div>
所以 JSX 就被发明出来了,为了能够区分变量和字符串,变量要用{}来包住变量,而且为了和 HTML 区分 onclick 变成 onClick、class 变成 className,如果不报错也可以直接写成class。 我们把最终写好这个div直接写入 ReactDOM.render(div,document.querySelector('#roo'))里面,即:
function render() {
ReactDOM.render(
<div class="overall">
<span class="showMoudle">{number}</span>
<button onClick={onClickButton}>+</button>
<button onClick={onClickButton2}>-</button>
</div>,
document.querySelector('#root'))
}
最终React版本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
let number = 0
let onClickButton = () => {
number += 1
render()
}
let onClickButton2 = () => {
number -= 1
render()
}
render()
function render() {
ReactDOM.render(
<div class="overall">
<span class="showMoudle">{number}</span>
<button onClick={onClickButton}>+</button>
<button onClick={onClickButton2}>-</button>
</div>,
document.querySelector('#root'))
}
优点:
React速度很快
- 与其它框架相比,React采取了一种特立独行的操作DOM的方式。
- 它并不直接对DOM进行操作。
- 它引入了一个叫做虚拟DOM的概念,安插在JavaScript逻辑和实际的DOM之间。
- 这一概念提高了Web性能。在UI渲染过程中,React通过在虚拟DOM中的微操作来实对现实际DOM的局部更新。
缺点
React本身只是一个V而已,所以如果是大型项目想要一套完整的框架的话,也许还需要引入Flux和routing相关的东西。
参考资料
React中文文档 https://reactjs.org/
React 入门实例教程 http://www.ruanyifeng.com/blog/2015/03/react.html
颠覆式前端UI开发框架:React http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react
React的工作原理 https://blog.csdn.net/a1943206465/article/details/60570567
网友评论