ReactReact全家桶React 概述+虚拟DOM的创建与渲染+JSX
Posted 前端More
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReactReact全家桶React 概述+虚拟DOM的创建与渲染+JSX相关的知识,希望对你有一定的参考价值。
文章目录
参考链接:
1 React 概述
1.1 React 简介与特点
React
用于动态构建用户界面的 JS 库(只关注于视图)
- 是一个将数据渲染为 html 视图的开源 JS 库
- 它遵循基于组件的方法,有助于构建可重用的 UI 组件
- 它用于开发复杂的交互式的 web 和移动 UI
原生JS的缺点
- 原生JS操作DOM繁琐,效率低,直接操作DOM,浏览器会进行大量的重绘重排
- 原生JS没有组件化编码方案,代码复用率很低
React的特点
- 使用
虚拟DOM和Diff算法
,尽量复用DOM节点,减少与真实DOM的交互 - 使用
JSX
,代码的可读性更好 组件化模式
,提高代码复用率、且让代码更好维护声明式编程
, 让编码人员无需直接操作DOM,提高开发效率- 在 React Native中可以使用React语法进行移动端开发
1.2 相关补充:命令式与声明式编程、重绘与重排、模块化与组件化、虚拟DOM
命令式编程与声明式编程
命令式编程
:用详细的命令机器怎么去处理一件事情以达到你想要的结果.
例如你想通过点击改变页面中某一个元素,首先要获取按钮,再给按钮添加点击事件,获取要改变的元素,执行点击函数,改变元素达到自己的目的,这是一步一步的步骤操作,就如同给计算机发布命令,一步一步执行,这就是命令式编程声明式编程
:你只需要告诉计算机,你要得到什么样的结果,计算机则会完成你想要的结果,以React为例,在页面中通过 显示一个变量,你只需要改变这个变量,页面就会跟着刷新,这就是你只需要结果,React 内部去处理过程,这就是声明式编程
重绘与重排
重绘(repaint)
:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程重排(reflow)
:当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置的过程
模块化与组件化
业务逻辑
: 举个例子比如淘宝双12举办活动,那些活动页面的逻辑,什么时候显示,在某些情况下显示什么,在另外一些情况下又该显示什么 ,这就是业务逻辑
传统开发模式的主要问题
:命名冲突、文件依赖, 通过模块化
可解决上述问题
-
模块
: 一个JS文件
就是一个模块,模块内部定义的变量和函数默认情况下在外部无法得到 -
模块化
:从业务逻辑角度或功能需要角度划分的,按照项目功能需求划分成不同类型的业务框架(例如:注册、登录、外卖、直播…) ,目的: 隔离、分装 -
把单独的一个功能封装到一个模块(js文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员,也可以依赖别的模块
-
优点
: 方便代码的重用,从而提升开发效率,并且方便后期的维护
传统方式编写应用的问题
:依赖关系混乱、代码复用率不高, 通过组件化
可解决上述问题
组件
: 可复用的 Vue/React 实例组件化
: 从UI界面角度或复用的角度划分的,页面上每个独立的区域都可以看做是一个组件,目的:复用、解耦- 一个界面的功能很复杂,将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得容易了,当应用是以多组件的方式实现, 这个应用就是一个组件化的应用。
最大区别
:划分角度不同,都是便于项目的维护和开发。
模块化是对功能的拆分,模块化并没有要求一定组件化,就是说进行模块化拆分时你可以完全不考虑代码重用,只是把同一业务的代码做内聚整合成不同的模块
虚拟DOM
虚拟DOM
是JS按DOM(真实DOM)的结构来创建的虚拟树型结构对象,是对DOM的抽象,比DOM更加轻量型(属性更少),本质还是Object类型的对象,虚拟DOM最终会被React转化为真实DOM,呈现在页面上。
2 初识React
2.1 引入相关库
-
react.js
:React核心库。 -
react-dom.js
:提供操作DOM的React扩展库。 -
babel.min.js
:解析JSX语法代码转为JS代码的库。- 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
- 只要用了JSX,都要加上
type="text/babel"
, 声明需要babel来处理
2.2 虚拟DOM的创建与渲染
JS 创建虚拟 DOM(一般不用)
<script type="text/JS" >
//1.创建虚拟DOM,创建嵌套格式的dom
const VDOM=React.createElement('h1',id:'title',React.createElement('span',,'hello,React'))
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.querySelector('.test'))
</script>
JSX 创建虚拟DOM
//1.创建虚拟DOM
script type="text/babel" > /* 此处一定要写babel */
const VDOM = ( /* 此处一定不要写引号,因为不是字符串 */
<h1 id="title">
<span>Hello,React</span>
</h1>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.querySelector('.test'))
</script>
虚拟DOM的渲染
语法
:
//virtualDOM为虚拟dom containerDOM用来包裹虚拟DOM的真实dom对象
ReactDOM.render(virtualDOM, containerDOM)
作用
: 将虚拟DOM渲染为真实DOM,然后在页面中显示
代码总览
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello_react</title>
</head>
<body>
<!-- 真实DOM对象 根节点-->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/JS" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/JS" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/JS" src="../js/babel.min.js"></script>
<script type="text/babel"> /* 此处一定要写babel */
//1.创建虚拟DOM
const VDOM = <h1>Hello,React</h1> /* 此处一定不要写引号,因为不是字符串 */
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
3 JSX
3.1 JSX简介
JSX(JS XML)
是一种类似于XML的JS扩展语法,用来简化创建虚拟DOM, 在React中可以方便地用来描述UI(用户界面) 。 JSX为我们提供了创建React元素方法(React.createElement(component, props, ...children)
)的语法糖
(简写形式)
写法:
import React from 'react';
//JSX不是字符串, 也不是HTML/XML标签,最终产生的就是一个JS对象
var ele = <h1>Hello, JSX!</h1>
// 等价于
var element = React.createElement(
"h1",
null,
"Hello, world!"
);
注:
-
定义虚拟DOM时,不要写引号。只有一个根标签且每个标签必须闭合
-
JSX 语法有时需要
小括号( )
包裹,避免遇到js自动插入分号的陷阱 -
内联样式
,要用style= key:value
的形式去写。 React 提倡的是组件思想,万物皆是 JS 控制(用 JS 来写 HTML 和 CSS)。以组件为维度,把 HTML、CSS、JS 混合在一起。React 会自动添加 ”px” 后缀到内联样式为数字的属性后。如需使用 ”px” 以外的单位,请将此值设为数字与所需单位组成的字符串style= marginBottom: 40,//或'40px' 有px需要加' ' width: 590, height: 590, display: 'flex', float: 'left', justifyContent: 'flex-end'
3.2 JSX的基本用法
3.2.1 JSX代表JS对象(Object)
JSX本身也是一个表达式
,在编译后,JSX表达式会变成普通的JS对象(Object)。
你可以在if语句或for循环中使用JSX,你可以将它赋值给变量,你可以将它作为参数接收,你也可以在函数中返回JSX。
function getGreeting(user)
if (user)
return <h1>Hello, formatName(user)!</h1>;
return <h1>Hello, Stranger.</h1>;
//上面的代码在if语句中使用JSX,并将JSX作为函数返回值。实际上,这些JSX经过编译后都会变成JS对象。经过babel会变成下面的js代码:
function test(user)
if (user)
return React.createElement(
"h1",
null,
"Hello, ",
formatStr(user),
"!"
);
return React.createElement(
"h1",
null,
"Hello, Stranger."
);
3.2.2 在JSX中使用JS表达式
在 JSX 语法中,你可以在
内放置任何有效的JS表达式
, 例如,2 + 2
,user.firstName
或 formatName(user)
都是有效的 JS 表达式。
function formatName(user)
return user.firstName + ' ' + user.lastName;
const user =
firstName: 'Harper',
lastName: 'Perez'
;
const element = (
<h1>
Hello, formatName(user)!
</h1>
);
ReactDOM.render(
element,
document.getElementById('root')
);
但if语句以及for循环不是JS表达式
,不能直接作为表达式写在 中,可以先将其赋值给一个变量(变量是一个JS表达式):
function NumberDescriber(props)
let description;
if (props.number % 2 == 0)
description = <strong>even</strong>;
else
description = <i>odd</i>;
return <div>props.number is an description number</div>;
JSX还可自动防范注入攻击,在JSX中嵌入接收到的内容是安全的,在默认情况下,React DOM会将所有嵌入JSX的值进行编码。这样可以有效避免xss攻击。比如:
const danger = response.potentialDanger;
cosnt ele = <h1>title</h1>
相关补充 :js表达式与js语句
js表达式
:一个表达式会产生一个值,可以放在任何一个需要值的地方
判断方法
:在它们左边定义一个变量 const x =xxx 若有返回值就是表达式
下面这些都是表达式:
- a
- a+b
- demo(1) ( 函数调用表达式)
- arr.map( )
- x === y ? ‘a’ : ‘b’
- function test ( )
js语句
: 语句可以理解为一个行为,循环语句和判断语句就是典型的语句。下面这些都是语句:
- if( )
- for( )
- switch( )case:xxxx
3.2.3 JSX属性值
可以使用引号
将字符串字面量
指定为属性值或者可以将一个JS表达式
嵌在一个大括号
中作为属性值:
//”0”是一个字符串字面量
const element = <div tabIndex="0"></div>
const element = <img src=user.avatarUrl></img>;
//这里用到的是JS属性访问表达式,上面的代码将编译为:
const element = React.createElement("img", src: user.avatarUrl );
3.2.4 JSX的Children
一个标签里面没有内容,你可以使用 />
来闭合标签 , JSX 标签里能够包含很多子元素 Children
const element = (
<div>
<h1>Hello!</h1>
<img src=user.avatarUrl />
</div>
);
标签属性名使用驼峰命名法camelCase
, class== > className;,for== >Htmlfor , tabindex== >tabIndex
const element = <div className='demo'></div>
3.2.5 JSX中的props
每个组件都是一个对象,props是对象的一个属性,组件对象可以通过props传递
指定JSX中的props有以下几种方式:
-
使用JS表达式
,任何有效的JS表达式
都可以作为props的值
,使用的时候将该表达式放在一对大括号
中即可<MyComponent foo=1 + 2 + 3 + 4 /> <YourComponent clickTodo=(id) => this.props.handleClick(id) />
-
字符串字面量可以作为prop值
<MyComponent message="hello world" /> // 等价于 <MyComponent message='hello world' />
-
使用扩展运算符
, 你想将一个prop对象传入JSX,你可以使用扩展运算符...
直接将整个prop对象传入function App1() return <Greeting firstName="Ben" lastName="Hector" />; // 等价于 function App2() const props = firstName: 'Ben', lastName: 'Hector'; return <Greeting ...props />;
3.2.6 JSX标签体内容props.children
React组件中有一个特殊的prop–props.children
。它指代了JSX表达式中标签体内容。
指定 JSX中的props.children 有以下几种方式:
-
使用字符串字面量
, 在JSX标签体中写入字符串字面量,组件得到的props.children就是该字符串值//MyComponent的props.chilren获得”Hello World!”字符串 <MyComponent>Hello world!</MyComponent>
-
JSX元素作为children
, 我们同样可以使用JSX元素作为JSX的children,由此生成嵌套组件 , 也可以混合使用字符串字面量和JSX作为children :<MyContainer> Here is a list: <MyFirstComponent /> <MySecondComponent /> </MyContainer>
-
JS表达式
, 和props一样,你也可以将任何有效的JS表达式作为children传入,将它放在 中就可以了。<MyComponent>a+b</MyComponent>
-
函数children
, 传入自定义组件的children并没有严格的限制,只要在React需要render的时候能将它们转换成可以render的东西就行了function ListOfTenThings() return ( <Repeat numTimes=10> //作为一个prop传入 (index) => <div key=index>This is item index in the list</div> </Repeat> );
-
布尔值、Null以及Undefined
, 布尔值,Null以及Undefined可以作为有效的children,但他们不会被render<div> // <Header />只有在showHeader为true时才会render showHeader && <Header /> <Content /> </div>
3.2.7 自定义组件与元素标签
遇到 <
开头的代码, 观察标签首字母:
- 若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
- 若大写字母开头,React就去渲染对应的组件,若组件没有定义,则报错。
- 自定义组件首字母要大写,一定引入后在使用,元素标签名不能使用表达式
以上是关于ReactReact全家桶React 概述+虚拟DOM的创建与渲染+JSX的主要内容,如果未能解决你的问题,请参考以下文章
ReactReact全家桶React 生命周期+虚拟DOM+Diff算法