上次给大家介绍了由尤雨溪推出的Vue框架,今天给大家简要介绍我正在学习的React框架。不想说太多废话,也不想贴太多代码,下面列出的内容都是React框架的核心内容(学过react的可以复习一下,没学过的可以简单了解一下react的核心特性),为了方便理解React的特性,部分内容与Vue进行了对比。
如果你看不懂,我送你一句话(来自Vue官网):你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
1、React简介
React是由Facebook推出的前端开发框架,于2013年5月开源,目前React已经演化成一套成熟的Web应用解决方案,其衍生出的React Native用写Web App的方式去写Native App,实现同一组人只需要写一次UI, 在理论上就能同时运行在PC端的浏览器和手机端APP上。
React特点:
- 声明式设计 − React采用声明范式,可以轻松描述应用。
- 高效 − React通过对DOM的模拟,最大限度地减少与DOM的交互。
- 灵活 − React可以与已知的库或框架很好地配合。
- JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
- 组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
- 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
2、React核心原理
React的核心原理主要是两点:虚拟DOM和Diff算法。当然Vue里面也有虚拟DOM和Diff算法这两个概念,在面试找工作的过程中这也是经常被问到的问题,后续有机会我会再深入了解一下。
虚拟DOM(Virtual DOM):传统的 web 应用,操作 DOM 一般是直接更新操作的,DOM 更新通常是比较昂贵的。而 React 为了尽可能减少对 DOM 的操作,提供了一种不同的而又强大的方式来更新 DOM,代替直接的 DOM 操作。就是实现了一个轻量级的虚拟DOM。虚拟DOM是React抽象出来的一个对象,描述 DOM 应该什么样子的,应该如何呈现。通过这个 Virtual DOM 去更新真实的 DOM,由这个 Virtual DOM来管理真实 DOM 的更新。
Diff算法: 更新Virtual DOM并不保证马上影响真实的 DOM,React 会等到事件循环结束,然后利用这个 diff 算法,通过当前新的 dom 表述与之前的作比较,计算出最小的步骤更新真实的 DOM。
注意:以上只是对React核心原理的简单介绍, 实际上这两者背后的原理有更进一步深入学习的必要, 这留给以后再看。
3、通过create-react-app工具创建React项目
在工程项目中,往往都是使用现成的脚手架去构建项目, create-react-app就是专门用来构建React项目的脚手架, 相当于Vue的vue-cli。
使用方法:
- 安装Node环境
- 全局安装create-react-app: npm install -g create-react-app
- 创建react项目: create-react-app demo-app
- 进入项目目录: cd demo-app
- 安装相关包: npm install
- 运行react项目: npm start
4、React JSX语法
在Vue中模板文件是类似HTML的文件, 其学起来难度比较低, 而React理解需要通过JSX来定义HTML, 然后使用render函数进行渲染(注意render里面的return中只能有一个元素存在)。
JSX是React用来描述DOM结构的一种语法,它非常类似于原始的html写法,但是又有一些自己的规则。TypeScript语言原生支持JSX,两者配合可以让TS覆盖到界面部分类型检查,开发体验非常棒,JSX让我们可以完全使用JS来开发界面部分(HTML)和逻辑部分(JS),可以充分利用JS的灵活性。
插值
插值简单理解就是将数据的值插入页面,在Vue中通过{{}}
实现插值, 而在React的JSX语法中通过{}
实现插值。示例如下:
render() {
let name = 'React'
return <div>Hello {name}</div>
}
当然也可以在{}
中放一些表达式或者调用函数, 这里不做演示。
添加属性
添加属性与插值的写法类似,如:
render() {
return (
<div tabIndex="0">
<img src={user.avatarUrl} />
</div>
)
}
注意:JSX语法上更接近JavaScript,并非和HTML完全对应,所以React DOM使用 camelCase
(小写驼峰命名)来定义属性的名称,而不使用HTML属性名称的约定。比如最常见的,JSX里面的 class
变成了 className
render() {
return <div className="message">Hello</div>
}
事件处理
React元素的事件处理和DOM元素很类似,但是语法上有一些不同:
- React事件的命名采用小驼峰模式(camelCase),而不是纯小写,比如onClick、onChange等
- 使用JSX语法时你需要传入一个函数作为事件处理函数,而不是一个字符串
Vue中采用v-on
监听DOM事件,其中v-on
可以简写为@
传统HTML的事件处理
<button onclick="onclick()">Click</button>
React的事件处理
onBtnClick() {
console.log('button clicked!')
}
render() {
return <button onClick={this.onBtnClick.bind(this)}></button>
}
注意: 在React里面我们不需要使用addEventListener
给元素添加事件监听
5、React组件化开发
在 react 中,一切皆组件,根据划分不同组件,可以使代码复用,减少代码编写。组件分可以分为Class组件和函数组件。
Class组件
Class组件又叫有状态组件,定义Class组件需要继承React.Component,实现render函数,返回一个元素。基本示例如下:
class ClassComponent extends React.Component{
render(){
return <div>这是一个Class组件</div>;
}
}
函数组件
函数组件又叫无状态组件。基本示例如下:
const FunctionComponent = () => <div>是一个Function组件</div>;
Class组件和函数组件的区别
- 实现原理不同: 函数组件是一个纯函数,它接收一个props对象返回一个react元素;而类组件需要去继承React.Component并且创建render函数返回react元素。
- 生命周期和属性不同: 函数组件没有生命周期、state和ref,而类组件有。两者都有props。
但是React16.8提供的hooks特性, 提供了useState、useEffect、useRef等钩子方法, 让函数组件也可以实现生命周期、state和ref, 目前react hooks已经在开发中得到广泛的使用,以后再详细看一下。
6、React三大属性
props
类似vue中的props, 可通过父子组件进行数据传递和交互。具体而言, props可实现以下三种组件通信:
- 父传子
- 子传父
- 兄弟组件通讯
porps可在类组件和函数组件中直接使用。
state
在react组件中可以通过state保存当前所操作数据的状态
为什么React需要state:因为React不同于Vue, Vue是数据双向绑定, 而React是数据的单向绑定, 所以需要通过setState方法对state进行更新, 以后有时间再深入了解。
state可在类组件中直接使用,在函数组件中要用useState实现。
ref
在React中可以通过ref获取React元素或DOM元素。在日常写React代码的时候,一般情况是用不到Ref这个东西,因为一般来说并不直接操作底层DOM元素,而是在render函数里去编写我们的页面结构,由React来组织DOM元素的更新。凡事总有例外,总会有一些很奇葩的时候需要直接去操作页面的真实DOM,这就要求React具有直接访问真实DOM的能力,而Ref就是提供了这样的能力。
React.createRef: React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点。
ref的使用方法如下:
class RefDemo extends React.Component{
constructor() {
super()
this.myRef = React.createRef()
}
componentDidMount() {
// 输出当前绑定的DOM元素
console.log(this.myRef.current)
}
render() {
return <div ref={this.myRef} />
}
}
也可以通过绑定字符串(String类型的refs)来获取ref:
class StringRef extends React.Component {
componentDidMount() {
console.log(this.refs.container.innerHTML) //获取绑定的节点
}
render() {
return (
<div ref='container'>怎知向何处</div>
)
}
}
注意: 不能在函数组件上使用 ref 属性,因为他们没有实例。函数组件可以使用useRef(),它所返回的对象在组件的整个生命周期内不变。
7、React的生命周期
React中常用的生命周期:
- componentDidMount:会在组件挂在后(插入DOM树中)立即调用。对应Vue的created和mounted。
- componentDidUpdate: 会在更新后会被立即调用。首次渲染不会执行此方法。对应Vue的updated。
- componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作。对应Vue的destroyed。
注意: 不能在函数组件使用上述生命周期, 在函数组件中可通过useEffect模拟上述生命周期。
Vue中常用的生命周期:
- created:页面初始化,在模板渲染成html前调用
- mounted: 挂载(DOM挂载到页面上),在模板渲染成html后调用,用来进行发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
- updated:更新(DOM更新)
- destroyed:销毁,一般在beforeDestroy中清除定时器、解绑自定义事件、取消订阅消息等(收尾工作)
这部分内容没有贴代码,后续有机会再详细介绍一下React的生命周期。