前端技术:React详解
1.RN简介
React Native
(简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架React
在原生移动应用平台的衍生产物,目前支持iOS和安卓两大平台。RN使用Javascript
语言,类似于HTML
的JSX
,以及CSS
来开发移动应用,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。
React Native
看起来很像 React
,只不过其基础组件是原生组件而非 web 组件。要理解 React Native
应用的基本结构,首先需要了解一些基本的 React
的概念,比如 JSX
语法、组件、state
状态以及props
属性。
React Native开发特点:
- 一次学习,随处编写:使用React Native可以为iOS和Android操作系统开发应用程序,不同平台上的代码根据平台会有一些微小的区别。
- 混合开发:React Native代码开发的模块与原生代码开发的模块可以双向通信、无缝衔接;
- 高效的移动应用开发:
(1)独特的UI实现框架
(2)组件化开发
(3)跨平台移植代码迅速
(4)自动匹配不同屏幕大小的手机
- 高效的移动应用开发调试
- 高效的应用热更新
- 有效降低移动应用安装包体积
- 学习门槛低、开发难度低
使用React Native开发的代价
为了得到React Native开发的优点,使用React Native开发的APP也需要付出一定的代价。
- (1)内存消耗大
使用React Native开发的程序运行所需的内存比原生代码开发的程序略多。 - (2)运行速度
使用React Native开发的代码运行速度比原生代码略慢。
React 与 React Native 除了在编码表现层都使用 JSX 语法外,在 React 与 React Native 的底层都有 Virtual DOM 与 DOM 之间的映射与转换,以实现了页面组件高效更新的前端表现。
image.png
现在最新版本是0.59React Native中文网
React Native
与React
的关系及特点:React
是基础框架,是一套基础设计实现理念,开发者不能直接使用它来开发移动应用或网页。在React
之上发展出了React.js
框架用来开发网页,发展出来React Native
用来开发移动应用。底层原理是相同的,都是使用js实现虚拟dom树来驱动页面的渲染,react是驱动HTML dom的渲染,react native是驱动原生组件的渲染。
React.js
:目的 是为了使前端的V层更具组件化,能更好的复用,它能够使用简单的html标签创建更多的自定义组件标签,内部绑定事件,同时可以让你从操作dom中解脱出来,只需要操作数据就会改变相应的dom。
二者都是基于组件(component
)开发,然后组件和组件之间通过props
传递方法,每个组件都有一个状态(state)
,当某个方法改变了这个状态值时,整个组件就会重绘,从而达到刷新。另外,说到重绘就要提到虚拟dom
了,就是用js模拟dom
结构,等整个组件的dom
更新完毕,它会有一个diff
的过程,对比出哪些组件发生了变化,然后才渲染到页面,简单来说只更新了相比之前改变了的部分,而不是全部刷新,所以效率很高。
虚拟DOM(Virtual DOM)
的机制:在浏览器端用Javascript
实现了一套DOM API
。基于React
进行开发时所有的DOM
构造都是通过虚拟DOM
进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并。
2.React详解
生态介绍
Vue生态:Vue + Vue-Router + Vuex + Axios + Babel + Webpack
React生态:React + React-Router + Redux + Axios + Babel + Webpack
2.1.React 简介
React
React
是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。
React
特点
- 1.声明式设计 −
React
采用声明范式,可以轻松描述应用。 - 2.高效 −
React
通过对DOM的模拟,最大限度地减少与DOM的交互。 - 3.灵活 −
React
可以与已知的库或框架很好地配合。 - 4.JSX −
JSX
是JavaScript
语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。 - 5.组件 − 通过
React
构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。 - 6.单向响应的数据流 −
React
实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
2.2 React使用
1.React 环境配置安装
- 使用 React CDN 库
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 官方提供的CDN-->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
- 通过 npm 使用 React
- 使用 create-react-app 快速构建 React 开发环境
2.3React render 渲染
屏幕输出:Hello, React
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 使用cdn 上的React CDN库-->
<!-- react.min.js - React 的核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!-- react-dom.min.js - 提供与 DOM 相关的功能 -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- babel.min.js - Babel 可以将 ES6 代码转为 ES5 代码 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<!-- React render 渲染-->
<script type="text/babel">
ReactDOM.render(<h1>Hello, React </h1>,
document.getElementById('root')
);
</script>
</body>
</html>
3.React JSX
React 使用 JSX 来替代常规的 JavaScript。
1.React JSX简介
JSX:JavaScript XML,一种类似于XML的JS扩展语法。也可以理解成:符合 XML 规范的 JS 语法。
JSX语法的本质:以 React.createElement 的形式来实现的,并没有直接把 用户写的 HTML代码,渲染到页面上。使用babel转换工具将 JSX语法 转换为 JS语法。
我们不需要一定使用 JSX,但它有以下优点:
- JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
- 它是类型安全的,在编译过程中就能发现错误。
- 使用 JSX 编写模板更加简单快速。
const element = <h1>Hello, world!</h1>;
这种看起来可能有些奇怪的标签语法既不是字符串也不是 HTML。
它被称为 JSX, 一种 JavaScript 的语法扩展。 我们推荐在 React 中使用 JSX 来描述用户界面。
JSX 是在 JavaScript 内部实现的。
2.JSX的基本语法
(1)在 JSX内部 写 JS代码:如果要在 JSX 语法内部,书写 JS 代码,那么,所有的JS代码必须写到 {} 的内部。在{}内部,可以写任何符合JS规范的代码。
例如:
var myTitle = '这是使用变量定义的 tilte 值'
// 使用JSX语法 创建虚拟DOM对象
var vDom = (
<div>
Hello, React!
<h2 title={myTitle + 'vae'}>这是标题</h2>
</div>
);
(2)当编译引擎在编译JSX代码的时候,如果遇到了<,会把它当作 HTML代码 去编译;如果遇到了 {}, 会把方括号里面的代码当作 普通JS代码 去编译。
(3)在JSX中,如果要为元素添加class属性,则必须写成className,因为 class在ES6中是一个关键字;和class类似,label标签的 for 属性需要替换为 htmlFor。
代码举例:
// 使用JSX语法 创建虚拟DOM对象
var vDom = (
<div>
Hello, React!
<p className="qianguyihao">千古壹号</p>
<label htmlFor="" />
</div>
);
(4)在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹。
(5)如果要写注释,注释必须放到 {} 内部。例如:
// 使用JSX语法 创建虚拟DOM对象
var vDom = (
// 这一行是注释
<div>
Hello, React!
<p className="qianguyihao">千古壹号</p>
{/*这一行也是注释 */}
</div>
);
最后,再举个例子:
<!DOCTYPE html>
<html lang="">
<head>
<meta />
<meta />
<meta />
<title>Document</title>
</head>
<body>
<!-- 引入React相关的js库 -->
<script type="text/javascript" src="./libs/react.js"></script>
<script type="text/javascript" src="./libs/react-dom.js"></script>
<script type="text/javascript" src="./libs/babel.min.js"></script>
<div id="app"></div>
<!-- 注意,这一行的 type 是写 "text/babel",而不是 "text/javascript" -->
<script type="text/babel">
//页面中的真实容器元素
var containDiv = document.getElementById("app");
var arr = []
for (var i = 0; i < 6; i++) {
var p = <p className="myp" key={i}>这个是p标签</p> // 注意这个地方的写法: key = {i}
arr.push(p)
}
//1、使用JSX语法 创建虚拟DOM对象
var vDom = (
<div>
Hello, React!
{arr}
</div>
);
//2、渲染虚拟DOM对象
ReactDOM.render(vDom, containDiv); // 参数1:虚拟DOM对象;参数2:页面中的容器
</script>
</body>
</html>
4.React 组件 状态(State&props) 生命周期详解
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
- 创建组件的第一种方式:在React中,构造函数就是一个最基本的组件。如果想要把组件放到页面中,可以把构造函数的名称当作组件的名称,以 HTML标签形式引入页面中即可。
- 创建组件的第二种方式:使用 class 关键字
使用 function 创建的组件,叫做【无状态组件】;使用 class 创建的组件,叫做【有状态组件】。
本质区别:
有状态组件和无状态组件,最本质的区别,就是有无 state 属性。同时, class 创建的组件,有自己的生命周期函数,但是,function 创建的 组件,没有自己的生命周期函数。
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
组件API
设置状态:setState
替换状态:replaceState
设置属性:setProps
替换属性:replaceProps
强制更新:forceUpdate
获取DOM节点:findDOMNode
判断组件挂载状态:isMounted
组件的生命周期可分成三个状态:
在组件创建、到加载到页面上运行、以及组件被销毁的过程中,总是伴随着各种各样的事件,这些在组件特定时期,触发的事件统称为组件的生命周期。
- Mounting:已插入真实 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实 DOM
生命周期的方法有:
- componentWillMount 在渲染前调用,在客户端也在服务端。
- componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
- componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
- shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。 - componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
- componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
- componentWillUnmount在组件从 DOM 中移除之前立刻被调用。
1.组件创建阶段
组件创建阶段的生命周期函数,有一个显著的特点:创建阶段的生命周期函数,在组件的一辈子中,只执行一次。
- getDefaultProps
初始化 props 属性默认值。
- getInitialState
初始化组件的私有数据。因为 state 是定义在组件的 constructor 构造器当中的,只要new 了 class类,必然会调用 constructor构造器。
- componentWillMount()
组件将要被挂载。此时还没有开始渲染虚拟DOM。
在这个阶段,不能去操作DOM元素,但可以操作属性、状态、function。相当于 Vue 中的Create()函数。
- render()
第一次开始渲染真正的虚拟DOM。当render执行完,内存中就有了完整的虚拟DOM了。
意思是,此时,虚拟DOM在内存中创建好了,但是还没有挂在到页面上。
在这个函数内部,不能去操作DOM元素,因为还没return之前,虚拟DOM还没有创建;当return执行完毕后,虚拟DOM就创建好了,但是还没有挂在到页面上。
- componentDidMount()
当组件(虚拟DOM)挂载到页面之后,会进入这个生命周期函数。
只要进入到这个生命周期函数,则必然说明,页面上已经有可见的DOM元素了。此时,组件已经显示到了页面上,state上的数据、内存中的虚拟DOM、以及浏览器中的页面,已经完全保持一致了。
当这个方法执行完,组件就进入都了 运行中 的状态。所以说,componentDidMount 是创建阶段的最后一个函数。
在这个函数中,我们可以放心的去 操作 页面上你需要使用的 DOM 元素了。如果我们想操作DOM元素,最早只能在 componentDidMount 中进行。相当于 Vue 中的 mounted() 函数
2、组件运行阶段
有一个显著的特点,根据组件的state和props的改变,有选择性的触发0次或多次。
- componentWillReceiveProps()
组件将要接收新属性。只有当父组件中,通过某些事件,重新修改了 传递给 子组件的 props 数据之后,才会触发这个钩子函数。
- shouldComponentUpdate()
判断组件是否需要被更新。此时,组件尚未被更新,但是,state 和 props 肯定是最新的。
- componentWillUpdate()
组件将要被更新。此时,组件还没有被更新,在进入到这个生命周期函数的时候,内存中的虚拟DOM还是旧的,页面上的 DOM 元素也是旧的。(也就是说,此时操作的是旧的 DOM元素)
- render
此时,又要根据最新的 state 和 props,重新渲染一棵内存中的 虚拟DOM树。当 render 调用完毕,内存中的旧DOM树,已经被新DOM树替换了!此时,虚拟DOM树已经和组件的 state 保持一致了,都是最新的;但是页面还是旧的。
- componentDidUpdate
此时,组件完成更新,页面被重新渲染。此时,state、虚拟DOM 和 页面已经完全保持同步。
3、组件销毁阶段
一辈子只执行一次。
- componentWillUnmount: 组件将要被卸载。此时组件还可以正常使用。
生命周期对比:
vue生命周期React-Native生命周期
组件生命周期的执行顺序总结
1、Mounting:
-
constructor()
-
componentWillMount()
-
render()
-
componentDidMount()
2、Updating:
-
componentWillReceiveProps(nextProps):接收父组件传递过来的属性
-
shouldComponentUpdate(nextProps, nextState):一旦调用 setState,就会触发这个方法。方法默认 return true;如果 return false,后续的方法就不会走了。
-
componentWillUpdate(nextProps, nextState)
-
render()
-
componentDidUpdate(prevProps, prevState)
3、Unmounting:
- componentWillUnmount()
5.React 事件处理
React 元素的事件处理和 DOM 元素类似。但是有一点语法上的不同:
React 事件绑定属性的命名采用驼峰式写法,而不是小写。
如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
//HTML 通常写法是:
<button onclick="activateLasers()">
激活按钮
</button>
//React 中写法为:
<button onClick={activateLasers}>
激活按钮
</button>