前言
React是现在前端使用频率最高的三大框架之一,React率先提出虚拟DOM的思想和实现,使其保持有良好的性能。同时,掌握React语法不仅可以写Web应用的页面,还可以写IOS和安卓的页面,可以说是实用性很强的框架了。本篇文章将对
React
的入门使用进行讲解,同时针对组件化的思想进行概述,为接下来组件化开发的文章进行知识储备。
一、什么是React
用官网的话一语概括就是,React是用于构建用户页面的JavaScript库。
在前端页面开发过程中,一共需要经历3个步骤:(1)发送请求接收数据(2)对后台返回的数据进行处理(3)操作DOM呈现页面。而React主要就是专注于第三个步骤来进行优化的。
同时,我们也可以看到React本质上也是一个JS的函数库,我们不妨会想,关于JavaScript的函数库,我们已经知道了有
JQuery
。那么为什么还需要学React呢? 这里不得不提到传统前端开发存在的三个问题:
1.原生JavaScript操作DOM繁琐、效率低( DOM-API操作UI ) 。(比如document.getElementById()
)
2.使用JavaScript直接操作DOM,浏览器会进行大量的重绘重排。每次页面上重新请求数据,都会重新刷新当前的相关DOM元素,而原先的DOM节点无法复用。
3.原生JavaScript没有组件化编码方案,代码复用率低。虽然JS中有着模块化的思想,但是只是对JS文件根据模块进行了划分,封装程度还不够,对于css、html重复的代码并没有能够有效的进行提取和封装。
基于上述提到的三个问题,React的出现也自然提供了解决方案。我们可以来看一下React
都具备哪些特性:
1.采用组件化模式、声明式编码,提高开发效率及组件复用率。
2.在React Native中可以使用React语法进行移动端开发。
3.使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互。
二、React的快速入门
步骤一:在页面中引入对应的核心依赖包,
<!-- 引入babel.js依赖,用于将JSX语法代码转换为JS代码 --><script type="text/javascript" src="../js/babel.min.js"></script><!-- 引入 react 基础核心库 --><script type="text/javascript" src="../js/react.development.js"></script><!-- 引入 react-dom 扩展库 --><script type="text/javascript" src="../js/react-dom.development.js"></script>
三个核心依赖包的功能分别如下:
- react.js:React核心库。
- react-dom.js:提供操作DOM的react扩展库。
- babel.min.js:解析JSX语法代码转为JS代码的库。
需要注意的是,三个依赖包的加载顺序有一定的要求,由于react-dom.js
文件依赖了react.js
文件,所以前者需要放在后者之后才能正常的加载。
步骤二:在页面中定义一个<div>
标签,同时定义类型为text/babel
的<script>
标签块
<script type="text/babel"></script>
需要注意的是,type类型为text/babel
表示标签内写的不再是JS,而是JSX语法的代码,而babel
会充当转换器的角色,帮助我们把JSX语法的代码转换成JS。(这里稍微解释一下,JSX本质上就是JS,只是对其做了一些封装,多了一些语法规则而已,其目的是为了简化我们的JS开发)
步骤三:在创建的script
标签中创建虚拟DOM对象,并将其渲染到页面上
<script type="text/babel">// 创建一个虚拟DOMconst VDOM = <h1>hello,react</h1>// 将虚拟DOM渲染到页面上ReactDOM.render(VDOM,document.getElementById('test'));</script>
我们可以看到,对于虚拟DOM对象,我们可以直接在上面写标签。而后调用ReactDOM
对象的render
方法将虚拟DOM对象渲染到页面上。此时,我们可以在页面上看到对应的效果:
三、创建虚拟DOM的两种方式
(一)使用JSX方式创建虚拟DOM
我们在上一节中讲到,虚拟DOM
的创建可以直接在类型为babel
的script
标签中以JSX语法的代码直接书写。这种方式使用的前提是导入了我们之前提到的babel.min.js
函数库,写法较为简单。
<script type="text/babel">const VDOM = <h1 id="test2">Hello,React</h1>ReactDOM.render(VDOM,document.getElementById('test'));</script>
那我们是不是只能用JSX这种语法来创建虚拟DOM呢?或者说,JSX本质上还是JS,那我能不能用JS来创建虚拟DOM对象呢?答案当然是可以。
(二)使用JS方式创建虚拟DOM
我们可以看到,React
也提供了对应的API给我们去创建虚拟DOM对象,需要注意的是,此时我们script
标签中使用的类型就是我们熟悉的text/javascript
了
<script type="text/javascript">// 使用JS创建虚拟DOMconst VDOM = React.createElement('h1',{id:'test2'},'Hello,React'));ReactDOM.render(VDOM,document.getElementById('test'));</script>
为什么要使用JSX?
或许有人会有疑问?既然原生的JS也可以创建虚拟DOM对象,那么我们为什么还要学习JSX语法呢?直接使用更加熟悉的JS不是更香?
这种疑问自然是很合理的,原生的JS固然可以满足我们的简单需要,但实际上当场景一旦变得复杂,JSX的优势就体现了出来,我们不妨看下面这个例子:
实现在原<div>
标签中,加入id属性为test2
的span
标签,在span
标签中再嵌套一个<h1>
标签,文本内容为Hello,React。
使用JS实现代码如下:
<script type="text/javascript">// 使用JS创建虚拟DOMconst VDOM = React.createElement('span',{id:'test2'},React.createElement('h1',{},'Hello,React'));ReactDOM.render(VDOM,document.getElementById('test'));</script>
为了实现嵌套元素的效果,我们这里需要再次调用React.createElement
作为child
元素进行传入。
而使用JSX实现的代码如下:
<script type="text/babel">const VDOM = (<span id="test2"><h1>Hello,React</h1></span>)ReactDOM.render(VDOM,document.getElementById('test'));</script>
我们可以看到,使用JSX可以很清晰地将我们想要的虚拟DOM对象进行定义,虽然最终实现的效果和JS的一致(本质上是经过babel转换后,我们的JSX语句也会被转换成对应的JS语句),但可读性却要高很多,更加便于开发。可以想象一下,当我们要创建的虚拟DOM对象结构非常复杂时,用原生的JS代码进行开发是多么让人头疼的一件事情。
四、虚拟DOM和真实DOM节点的区别
<body><div id="test"></div><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/babel">const VDOM = (<h1>hi,React</h1>)var dom = document.getElementById('test');console.log('真实dom对象',dom)console.log('虚拟DOM对象',VDOM);debugger;// 由于console并不能真正看到真实的DOM对象,所以需要借助 Dubgger// 在debugger 窗口中我们可以看到,相对于虚拟DOM而言,真实的DOM对象会比较“重”(属性比较多和复杂)ReactDOM.render(VDOM,document.getElementById('test'));</script>
</body>
我们在浏览器中打开这个页面,同时打开控制台观察对应的对象
我们可以从截图中看到,相比于真实的DOM对象,React的虚拟DOM对象属性要简单得多,所以使用起来的代价也比较小。一般来说,我们也会认为虚拟DOM对象是要比真实的DOM对象要“轻”。
五、JSX的语法规则
(1)构建虚拟DOM的时候,不要使用单/双引号(下面是错误示范)
<script type="text/babel">const VDOM = ('<h1 id="test2">Hello,React~</h1>')ReactDOM.render(VDOM, document.getElementById('test'));</script>
(2)标签中混入JS表达式时要用{}
<script type="text/babel">const idAttr = 'test2';const text = 'Hello,React~';const VDOM = (<h1 id={idAttr}><span>{text}</span></h1>)ReactDOM.render(VDOM, document.getElementById('test'));</script>
(3)样式的类名指定不要用class,要用className
<head>...<style>.myClass {background-color: yellow;width: 200px}</style>
</head><body><div id="test"></div>
...<script type="text/babel">const idAttr = 'test2';const text = 'Hello,React~';const VDOM = (<h1 id={idAttr} className="myClass"><span>{text}</span></h1>)ReactDOM.render(VDOM, document.getElementById('test'));</script>
</body>
(4)内联样式,需要用{{key: 'value',...}}的格式去书写
<script type="text/babel">const idAttr = 'test2';const text = 'Hello,React~';const VDOM = (<h1 id={idAttr} className="myClass"><span style={{color:'white',fontSize: '30px'}}>{text}</span></h1>)ReactDOM.render(VDOM, document.getElementById('test'));</script>
需要注意的是,这里用了两对花括号,最外面的花括号意思是里面将使用JS表达式,而里面的花括号表达这是一个JS对象。同时如果style属性不是一个单词的话,需要用类似fontSize
这种小驼峰式命名才能生效。
(5)虚拟对象只有一个根标签
<script type="text/babel">const idAttr = 'test2';const text = 'Hello,React~';const VDOM = (<div><h1 id={idAttr} className="myClass"><span style={{ color: 'white', fontSize: '30px' }}>{text}</span></h1><h1 id={idAttr} className="myClass"><span style={{ color: 'white', fontSize: '30px' }}>{text}</span></h1></div>)ReactDOM.render(VDOM, document.getElementById('test'));</script>
(6)标签必须闭合(这点比较简单,就不再举例了)
(7)标签首字母
- 若首字母为小写时,则将该标签转为html同名元素,如果找不到,则报错
- 若首字母为大写时,react就会去渲染对应的组件,如果组件没有定义,就会报错
我们这里定义一个good
标签,然后查看一下结果
<script type="text/babel">const idAttr = 'test2';const text = 'Hello,React~';const VDOM = (<good>abc</good>)ReactDOM.render(VDOM, document.getElementById('test'));</script>
我们可以看到,虽然abc值正常显示了出来,但控制台实际上还是报了错,因为由于此时标签的首字母小写,所以会去找html的同名标签,good这种自动以标签自然是不存在的,所以也就报了错。
我们这里定义一个Good
标签,然后查看一下结果
我们可以看到,此时的控制台会直接报错说找不到这个名称的组件。
六、模块与组件理解
组件(化)是React
框架中十分重要的知识点,谈组件之前,我们先来聊聊什么是模块?
模块其实我们在开发很多语言的时候都有接触到这个概念,比如Java,我们会将一些重复性的代码进行抽取,封装成一个或者一组相关的类,再根据实际的业务对外提供服务。JS中的模块也是如此:向外提供特定功能的js程序, 一般就是一个js文件
那什么是组件呢?
组件可以看成是资源的进一步封装,和后台的代码不同,前端的资源除了js之外还有html、css和各种图片资源等,模块化只能让我们的js实现复用,但对于其他资源来说并不行。所以组件就是用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)。
在企业级开发中,组件的应用可以使得我们资源的可重用性得到提升,减少我们的开发成本,也是前端不断发展下的产物。
喜欢的朋友记得点赞、收藏、关注哦!!!