自用
React是一个用于构建用户界面的JavaScript库,主要用于构建UI。React强调的是面向数据编程。
React起源于Facebook的内部项目,起初是因为该公司对所有JavaScript MVC(Model View Controller 模型-视图-控制器)框架都不满意,所以决定自己写一套来架设Instagram网站,后来觉得这套框架很好用,就在2013年五月进行开源推出。其带来了一种全新的函数式编程风格,React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑非常简单,是目前最流行的前端框架。
React 是一个全新思路的前端 UI 框架,它完全接管了 UI 开发中最为复杂的局部更新部分,擅长在在复杂场景下保证高性能;同时,它引入了基于组件的开发思想,从另一个角度来重新审视 UI 的构成。通过这种方法,不仅能够提高开发效率,而且可以让代码更容易理解,维护和测试。
React特点
library(库):小而巧。船小好调头,可以很方便的从一个库切换到另外的库,但是代码几乎不会变。
Framework(框架):大而全。框架提供了一整套的解决方案,如果在项目中,想切换到另外的框架,会比较困难。
Vue的API设计非常简洁,但是其实现方式却让人感觉是“魔法”,开发者虽然能马上上手,但是为什么能实现功能却很难说清楚。
相比之下React的设计哲学非常简单,虽然经常有需要自己处理各种细节问题,但是却让人感觉它非常“真实”,能清楚地感觉到自己仍然是在写js。
React与Vue中心思想相同:一切都是组件,组件实例之间可以嵌套。
组件化方面
数据流方面
开发团队方面
React是由FaceBook前端官方团队进行维护和更新的; 因此,React的维护开发团队,技术实力比较雄厚;
Vue:第一版,主要是有作者尤雨溪专门进行维护的,当Vue更新到2.x版本后,也有了一个以尤雨溪为主
导的开源小团队,进行相关的开发和维护;
社区方面
移动APP开发体验方面
JSX, 一种 JavaScript 的语法扩展,其格式比较像是模版语言,但事实上完全是在JavaScript内部实现的,它允许 HTML 与 JavaScript 的混写。通常在 React 中使用 JSX 来描述用户界面。 元素是构成 React 应用的最小单位,JSX 就是用来声明 React 当中的元素。
React不一定要使用 JSX,但它有以下优点:
JSX 看起来类似 HTML:
ReactDOM.render(
Hello, world!
,
document.getElementById('example')
);
React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合,比如,在 UI 中需要绑定处理事件、在某些时刻状态发生变化时需要通知到 UI,以及需要在 UI 中展示准备好的数据。
React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。
React 不强制要求使用 JSX,但是大多数人发现,在 JavaScript 代码中将 JSX 和 UI 放在一起时,会在视觉上有辅助作用。它还可以使 React 显示更多有用的错误和警告消息。
React.JS是基于组件化的开发,React框架允许我们将代码封装成组件,然后像插入普通的HTML
标签一样,在网页中插入这个组件。
//index.js
//引入 React 库
import React from 'react';
import ReactDOM from 'react-dom';
// 引入App组件,以大写字母开头
import App from './App';
//App.js
import React from 'react';
//定义一个React组件
function App() {
return (
<div className="App">
Hello World!
</div>
);
}
export default App;
在JS中通过React将App组件渲染到页面上
React 认为一个组件应该具有如下特征:
(1)可组合(Composeable):一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件拥有(own)它创建的子组件,通过这个特性,一个复杂的 UI 可以拆分成多个简单的 UI 组件;
(2)可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个 UI 场景;
(3)可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护;
(4)可测试(Testable):因为每个组件都是独立的,那么对于各个组件分别测试显然要比对于整个 UI 进行测试容易的多。
文档对象模型(Document Object Model,简称DOM)
1.什么是Virtual DOM
虚拟DOM概念随着react的诞生而诞生,由facebook提出,其卓越的性能很快得到广大开发者的认可。
Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。
2.为什么要用Virtual DOM
在浏览器里一遍又一遍的渲染DOM是非常非常消耗性能的,常常会出现页面卡死的情况;所以尽量减少对DOM的操作成为了优化前端性能的必要手段,Virtual DOM就是将DOM的对比放在了js层,通过对比不同之处来选择新渲染DOM节点,从而提高渲染效率。
在传统的 Web 应用中,我们往往会把数据的变化实时地更新到用户界面中,于是每次数据的微小变动都会引起 DOM 树的重新渲染。
虚拟DOM的目的是将所有操作累加起来,统计计算出所有的变化后,统一更新一次DOM,最终实现页面元素的高效更新。
<body>
<div id="app">
<ρ class="item">节点1p>
div>
<script>
createElement(){
return {
tag: 'div',
data: {
id:app},
children: [
{
tag:'p',
data: {
class: item
},
children: ['节点1']
}
]
}
}
script>
body>
Diff算法的作用是用来计算出 Virtual DOM 中被改变的部分,然后针对该部分进行原生DOM操作,而不用重新渲染整个页面。
Diff算法在React中处于主导地位,是React Virtual DOM和渲染的性能保证,这也是React最有魅力、最吸引人的地方。
React 将 Virtual DOM 树转换为 actual DOM 树的最小操作的过程称为调和, diff 算法便是调和的结果,React 通过制定大胆的策略,将 O(n3)的时间复杂度转换成 O(n)。
下面是 React diff 算法的 3 个策略:
基于以上三个策略,React 分别对 tree diff、component diff 以及 element diff 进行算法优化。
React 的组件可以定义为 class 或函数的形式。class 组件目前提供了更多的功能。如需定义 class 组件,需要继承 React.Component
:
class Welcome extends React.Component {
render() {
return <h1>Hello, {
this.props.name}</h1>;
}
}
在 React.Component
的子类中有个必须定义的 render()
函数。
ReactDOM.render()
方法是React
框架中最基础的方法,这个方法的作用是将模板转化为HTML
的语法,然后插入到指定的DOM
节点中。其目的就是将虚拟DOM渲染成真实的DOM。
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
上面的代码将一个插入到
root
的节点中,其中document.getElementById('root')
指定被插入的节点。
同理,这是一个动态渲染的例子
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {
new Date().toLocaleTimeString()}.</h2>
//toLocaleTimeString() 方法可根据本地时间把 Date 对象的时间部分转换为字符串,并返回结果。
</div>
);
ReactDOM.render(
element,
document.getElementById( 'root' )
);
}
//setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
setInterval( tick, 1000 );
通过React框架,完成TodoList功能
// 构造函数
constructor(props) {
super(props);
this.state = {
list: ["learn react", "learn English"],
inputValue: ""
};
}
// 将数据渲染到页面
render() {
return (
<div>
<div>
<input value={
this.state.inputValue} onChange={
this.handleInputChange.bind(this)}/>
{
/* bind(this) 可将 handleBtnClick()中的this与外部this绑定*/}
<button onClick={
this.handleBtnClick.bind(this)}>add</button>
</div>
<ul>
{
/* map()函数用于对数组做循环
每一个key值都是不同的,没有key值会报警告,可将数组中对应的下标当做key值*/}
{
this.state.list.map((item, index) => {
return <li key={
index} onClick={
this.handleItemClick.bind(this,index)}>{
item}</li>;
})}
</ul>
</div>
);
}
效果图:
add
按钮添加绑定事件,获取输入框数据,点击按钮后将输入框内容添加到列表中 // 添加按钮函数
handleBtnClick() {
// 点击按钮时改变state中list的数据
this.setState({
// '...':展开运算符,等价于list中原本包含的内容
list: [...this.state.list, this.state.inputValue],
inputValue: ""
});
}
// 获取输入框数据函数
handleInputChange(e) {
this.setState({
inputValue: e.target.value
});
}
效果图:
// 删除列表项目
handleItemClick(index){
const list = [...this.state.list];
// splice()从数组中添加/删除对应下标项目
list.splice(index,1);
this.setState({
//等价于this.setState({list})
list: list
})
}
效果图:
目前,页面时一整个TodoList组件,不利于后期的维护与运行效率,所以需要把其拆分成更小的组件,将代办事项抽离出来变成子组件,可以使得整体结构更清晰,便于理解。
TodoItem.js:
// 子组件
// 子组件通过props的形式接收父组件传递来的参数
// 子组件向父组件传值,要调用父组件传递过来的方法
import React from 'react';
export default class TodoItem extends React.Component{
constructor(props){
super(props);
this.handleDelete = this.handleDelete.bind(this)
}
// 删除代办事项 | 子组件向父组件传值
handleDelete(index){
this.props.delete(this.props.index)
}
render() {
const {
content} = this.props;
return(
<li onClick={
this.handleDelete}>{
content}</li>
)
}
}
TodoList.js:
import TodoItem from './TodoItem';
handleDelete(index){
console.log(index)
const list = [...this.state.list];
// splice()从数组中添加/删除对应下标项目
list.splice(index,1);
this.setState({
//等价于this.setState({list})
list: list
})
}
...
return <TodoItem />
TodoList.js完整代码
// 父组件
// 父组件通过属性的方式向子组件传递参数(eg:content)
// 进行代码优化
import React from "react";
import TodoItem from './TodoItem';
export default class Todolist extends React.Component {
// 构造函数
constructor(props) {
super(props);
this.state = {
list: ["learn react", "learn English"],
inputValue: ""
};
//提前声明this指向
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleDelete = this.handleDelete.bind(this);
}
// 添加按钮函数
handleBtnClick() {
// 点击按钮时改变state中list的数据
this.setState({
// '...':展开运算符,等价于list中原本包含的内容
list: [...this.state.list, this.state.inputValue],
inputValue: ""
});
}
// 获取输入框数据函数
handleInputChange(e) {
this.setState({
inputValue: e.target.value
});
}
// 同上
handleDelete(index){
console.log(index)
const list = [...this.state.list];
// splice()从数组中添加/删除对应下标项目
list.splice(index,1);
this.setState({
//等价于this.setState({list})
list: list
})
}
//
getTodoItems(){
return(
// map()函数用于对list数组中的item做循环
// 每一个key值都是不同的,没有key值会报警告,可将数组中对应的下标当做key值
this.state.list.map((item, index) => {
return (
<TodoItem
delete={
this.handleDelete}
key={
index}
content={
item}
index={
index} />
)
{
/* return {item} ; */}
})
)
}
// 将数据渲染到页面
render() {
//定义组件的类里面要有一个render的函数
// jsx语法
return ( //return出去的语句,决定了此组件在页面显示的内容
// 组件要放在一个大的闭合标签内,下面的this指向该组件
<div>
<div>
<input value={
this.state.inputValue} onChange={
this.handleInputChange}/>
{
/* bind(this) 可将 handleBtnClick()中的this与外部this绑定*/}
<button onClick={
this.handleBtnClick}>add</button>
</div>
<ul>
{
this.getTodoItems()}
</ul>
</div>
);
}
}
效果图:
React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,支持iOS和安卓两大平台。RN使用Javascript语言,类似于HTML的JSX,以及CSS来开发移动应用,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。
React Native主要特性如下:
异步执行
JavaScript应用代码和原生平台之间所有的操作都采用异步执行模式,原生模块使用额外线程,开发者可以解码主线程图像、后台保存至磁盘、无须顾忌UI等诸多因素直接度量文本设计布局。
触摸处理
React Native引入了一个类似于iOS上Responder Chain响应链事件处理机制的响应体系,并基于此为开发者提供了诸如TouchableHighlight等更高级的组件。
React VS React Native:
React VR旨在允许Web开发人员使用React的声明方法(特别是React Native)来创作虚拟现实(VR)应用程序。
React VR使用Three.js 来支持较低级别的WebVR 和 WebGL API. WebVR是用于访问Web上VR设备的API。 WebGL(Web图形库)是一种无需使用插件即可用于在任何兼容的Web浏览器中渲染3D图形的API。
React VR类似于React Native,因为它使用View
,Image
和Text
作为核心组件,并且支持Flexbox布局。 此外,React VR还将Pano
,Mesh
和PointLight
等VR组件添加相关库中。
可以创建一个简单的项目来查看VR效果,下面是命令行代码
效果图:
React 16 之后的版本,v对底层核心算法进行了改良。官方的一句话解释是“React Fiber是对核心算法的一次重新实现”。
在现有React中,更新过程是同步的,这可能会导致性能问题。当组件树过于庞大时,又同时进行很多事情,将造成界面卡顿,形成很不好的用户体验。
React Fiber把更新过程碎片化,执行过程如下面的图所示,每执行完一段更新过程,就把控制权交还给React负责任务协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有紧急任务,那就去做紧急任务。维护每一个分片的数据结构,就是Fiber,其最大的使命是解决大型React项目的性能问题。
通过一个星期对React的学习,我知道了什么是React,React用来做什么,React被开发出来的意义,以及通过简单上手使用React框架,完成基础的demo——TodoList。我认为,在学习React框架时,最重要的是理解它的核心概念,React的本质是用JS对象来模拟DOM即创建虚拟DOM,通过虚拟DOM与真实DOM进行对比,实现页面的按需更新。区别于传统数据渲染(提交整个页面的DOM元素,全部刷新),通过React我们可以将结构变化的部分更新到真实DOM中,进行局部更新,极大的提高了效率。React的核心思想是组件化,HTML、CSS、JS合为一体。一切皆是Component,所有页面都可以拆分成组件,结构清晰直观。React是一个UI库,描述页面标签如何展示,它可以与已知的库或框架很好地配合,这也提现了它独特的灵活性。它还有很多优点,需要继续去挖掘。
协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有紧急任务,那就去做紧急任务。维护每一个分片的数据结构,就是Fiber,其最大的使命是解决大型React项目的性能问题。