初衷
学习React有一段时间了, 一直想找个时间写一个React的系列文章。忙里抽闲,完成了第一篇。写这系列文章的初衷是总结这段时间的技术学习,以及给那些想学习React的同学们一点帮助。我会尽量以通俗易懂的语言阐述我对React的理解,希望能照顾到更多的新手。相信大家应该都明白一个道理,最能够带领你进步的,并不是比你强很多很多的大牛,而是刚好比你走得快那么一步的脚印。
为什么是React
这是2018年现代前端框架的使用情况统计,图片来自JavaScript 如日中天,2018趋势报告来啦!,数据仅供参考。可以看到这是个前端框架三足鼎立的时代,选择React并不是因为其他框架不够好,而是React本身有其独特的魅力,吸引着开发者的聚集。就好比喜欢一个人,并不是因为其他人不好才喜欢他,而是被他独特的魅力所吸引才产生了感情。所以对新手来说,大可不必太过纠结于框架的选择,框架只是个帮助我们开发的工具而已。你只需要知道,React本身足够强大,能够让你在大前端的世界里走的更远!
Hello World
我们从最简单的Hello World开始,进入React的世界,使用的是最新的React 16版本。
Document// 引入react及react-dom库
// 引入babel
// 在babel编译的环境下执行
const vDom =
Hello World
const root = document.getElementById('root')
ReactDOM.render(vDom, root)
在使用React之前,我们需要先引入React相关的js库。
react.development.js 这是React的核心库,用于构建页面UI
react-dom.development.js 这是React的DOM相关操作库,可以将你构建的UI渲染到浏览器中
除此之外,还需引入babel进行语法解析转换。
我们来详细解析下上面的demo,其实script标签中一共就写了3句代码,但其中包含了React的核心知识点——虚拟DOM和JSX。
const vDom =
Hello World
const root = document.getElementById('root')
ReactDOM.render(vDom, root)
JSX
JSX是React的灵魂,全称JavaScript XML。顾名思义,它可以让你在JS中使用XML标记的方式去直接声明界面的DOM,这是React独有的语法糖。
请看HelloWorld的例子
const vDom =
Hello World
// 创建h1标签,右边千万不能加引号const root = document.getElementById('root') // 找到
ReactDOM.render(vDom, root) // 把创建的h1标签渲染到root节点上
这里我们在JS里直接创建了一个
Hello World
标签,并赋值给vDom,这就是JSX语法。如果我们将react库的引入注释掉
会发现浏览器中报错
原因就是原生JS语法并不支持直接声明DOM标签,这是JSX的语法,需要React.js库的支持。
ReactDOM.render()这个是react-dom库中的方法,用于将你创建好的HTML模板(虚拟DOM节点)插入到某个节点上,并渲染到页面上。第一个参数是HTML模板,第二个参数是指定的DOM节点。
在上述JSX语法中有几个值得注意的地方:
右边的h1标签千万不能加引号。如果加上引号的,JS引擎会将其解释为字符串类型。其实从本质来说,
Hello World
这是一个对象,叫做虚拟DOM对象,后面会讲到。将 JSX 语法转为 JavaScript 语法,这一步很消耗时间。所以现在前端项目,都会使用工作流的形式来构建,不会在html页面中直接引入react、写js代码等等。
简单来说,就是JSX赋予我们在JS中直接创建HTML标签的能力,因为HTML标签实在是太弱小了。
当然我们也可以不使用JSX的语法创建DOM节点,直接使用React给我们提供的普通JS写法,React.createElement()API来创建。
const vDom = React.createElement(
'h1', // 第一个参数是标签名,例如h1、span、table...
{ className: 'hClass', id: 'hId' }, // 第二个参数是个对象,里面存着标签的一些属性,例如id、class等,因为class是保留字,所以要写成className的形式
'hello world' // 第三个参数是节点中的文本
)
const root = document.getElementById('root')
ReactDOM.render(vDom, root)
可以看到和之前的JSX写法const vDom =
Hello World
效果是一样的在使用React.createElement()这种写法时,我们并不需要用babel进行解析,因为这本身就是JS的语法,JS引擎可以解析。
其实本质上,JSX就是为了简化直接调用React.createElement() API的一颗语法糖而已,他执行最终会被babel解析转换为React.createElement()的形式,所以推荐使用JSX的语法来创建页面的UI(也就是HTML的一些DOM)。
JSX的优点
类XML语法结构清晰
增强JS语义
屏蔽DOM操作
···
我们以前在操作时,需要经过以下流程
创建节点 -> 找到插入位置 -> 插入节点,若是还有子节点,还需要继续添加,一切都需要手动实现。
而使用React的JSX语法只需要const vDom = xxx 然后ReactDOM.render(vDom, root)就可以。
换句话说,以前都是过程式操作,你不仅知道要做什么,还需要自己手动去实现。而现在变成了声明式操作,就好比在下命令一样,你只需要下命令创建怎样的DOM节点,然后下命令插入,中间的过程全部都由React框架帮你自动实现,让开发者可以完全屏蔽DOM的操作。
JSX基本语法规则
遇到 HTML 标签(以 < 开头),就用 HTML 规则解析
遇到代码块{}或括号(),就用 JavaScript 规则解析
我们把Hello World的例子提升下
let title = 'Hello World'
const vDom = (
{title}
)
const root = document.getElementById('root')
ReactDOM.render(vDom, root)
上述代码在执行时,当遇到
虚拟DOM
我们在写前端页面时,手动操作DOM,繁琐又容易出错,在大规模应用下维护起来也很困难。
并且每次修改DOM,浏览器的DOM树都需要重绘重排,效率十分低下。
既然DOM手动操作太繁琐且效率低下,那就在每次状态更新时重新渲染整个页面
每次都重新渲染整个页面效率十分低下,所以就加上一个虚拟DOM
每次修改时,先在虚拟DOM上更新,最后在批量更新整个页面,这样页面只需要一次大的更新,效率很高
虚拟 DOM 是在 DOM 的基础上建立的一个抽象层,我们对DOM中的数据和状态所做的任何改动,都会被自动且高效的同步到虚拟 DOM,最后再批量同步到 DOM 中。React会在内存中维护一个虚拟 DOM 树,当我们对这个树进行读或写的时候,实际上是对虚拟 DOM 进行的。当数据变化时,React会自动更新虚拟 DOM树,然后拿新的虚拟DOM树和旧的虚拟DOM树进行对比(当中有DOM diff算法,这个之后再说),把不同的虚拟节点放到一个队列里,最终在渲染时一次批量更新这些队列中的虚拟节点到真实DOM中,这是对DOM渲染效率上的一个质的提升。
一点小结
React以JS为中心,以JSX的独特语法糖将"HTML"放到了JS里,而JS远比HTML要强大。因此,与其增强HTML让其拥有逻辑,不如增强JS让其支持标签化,这样一来既丰富了JS操控领域,又提升了页面渲染的性能。所以,你若是新手也没关系,只要你JS能力足够强,相信一定能在React的世界里策马奔腾!
我的github地址:https://github.com/FightingHao
如果有什么不懂的地方,欢迎评论,希望和大家一起探讨React有关的知识!