React.js基础
ReactNative框架是基于React.js扩展而来,其编码基础和基本开发思想都是与React.js一致。
React.js是Facebook在2013年5月开源的一个JavaScript框架,主要用于构建UI页面。
目前Facebook及其旗下的前端都是用React.js进行构建,在之前,Facebook是用Angular.js框架进行开发,但是随着Facebook业务的增加,Angular.js框架自身的架构能力不足以支撑项目的继续继承。Facebook在内部首先开启了一个以组件化编程思想为基础的新框架,后期开源,命名为React.js,用来架设 Instagram 的网站。
React.js核心思想为组件化编程,通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
本章会对React.js基础知识进行讲解,为ReactNative做技术基础准备。
0,开发环境
本节内容无法在手机App中运行,因React.js是浏览器JavaScript框架,所以本章内容全部在浏览器中运行调试。
首先确保,Nodejs,chrome浏览器和Yarn已经安装。
通过npm安装React工程创建工具
npm install -g create-react-app
安装成功之后便可以通过该工具创建一个React项目
cd 指定目录
create-react-app myapp
创建成功之后,进入该项目的工程文件夹根目录,运行
npm start
或
yarn start
启动项目。
首先会启动一个本地调试服务器,通过该调试服务器可以预览项目。
初始项目为下图所示:
1,React元素
React元素对象是在页面上显示的基本单位,能够在页面上看到的东西,都是React元素对象。
创建React元素对象有两种方式:
- 使用HTML标签创建React元素对象
- 使用React组件创建React元素对象
使用React组件创建元素的内容,在我们后续讲完React组件在详细说明
首先我们需要引入react框架,
import React from 'react';
react框架在创建项目中自动被安装,同时自动安装的还有react-dom框架,react-dom框架下文中讲解。
通过react框架提供的createElement()
函数创建React元素对象。
React.createElement(
type,
props,
children1,
children2,
...
)
type:为HTML标签字符串或React组件类名
props:为元素属性,类型为一个对象,属性名为对象中的键名,属性值为相应键名对应的值
从第三个参数起,都为该元素的子元素,类似HTML中的节点的子节点。
例如,我们需要在屏幕上显示一个HelloWorld字符串,我们使用HTML中的p标签进行创建React元素,元素属性为空,子节点为一个字符串:HelloWorld。
const text = 'HelloWorld';
const textObject = React.createElement('p',null,text);
如果我们需要在屏幕上展示一个图片,创建React元素对象如下:
const url = 'https://facebook.github.io/react/img/logo_og.png';
const imageObject = React.createElement('img',{src:url,alt:'react-icon'})
在实际开发中,我们需要频繁的创建React元素对象,但此种创建方式十分不方便,所以,Facebook在ES6语法基础上,发布了JSX语法,使用JSX语法,可以更加方便的创建和管理React元素对象。
2,JSX语法
JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面,界面组件之间可以互相嵌套。可以理解为在JS中编写与XML类似的语言,一种定义带属性树结构(DOM结构)的语法,它的目的不是要在浏览器或者引擎中实现,它的目的是通过各种编译器将这些标记编译成标准的JS语言。
例如我们对比上文中提到的两个创建React元素对象的代码:
const text = 'HelloWorld';
//使用JavaScript语法
const textObject = React.createElement('p',null,text);
//使用JSX语法
const textObject = <p>{text}</p>
可以看出,JSX语法的本质就是使用标签语法代替React.createElement()
方法。
使用JSX语法,必须首先引入React框架,虽然使用JSX语法虽然没有显示调用React框架,但编译后的代码仍然包含React的调用。
且JSX语法的核心优势就是可以将变量写入标签中,这是之前HTML标签语法做不到的操作。有了变量,React框架的编程能力得到了极大的提升,可以处理更多动态的问题。
对于动态和静态,我在这里做一个基础定义
静态:在写代码的这个时刻,已知所要编写的内容。例如,我要输出一个HelloWorld字符串,这个字符串在编码的这个时刻是已知的,在编写这样的操作时,我们称之为静态问题。
动态:在编写代码这个时刻,对编写内容有部分未知的空间。例如,我要求两个书的和。到底这两个数是什么,在编写代码的时候不知道,这样的问题称之为动态问题,动态问题,必须使用变量来解决使用JSX语法创建对象和HTML标签语法很像,但和标签语法最大的区别就是在与语句中可以带变量,通过大括号对变量进行包裹。
创建一个显示图片的React元素对象
const url = 'https://facebook.github.io/react/img/logo_og.png';
//使用JavaScript语法
const imageObject = React.createElement('img',{src:url,alt:'react-icon'});
//使用JSX语法
const imageObject = <img src={url} alt={'react-icon'} />;
同样,React元素对象可以像HTML标签一样进行嵌套:
const text = 'HelloWorld';
const url = 'https://facebook.github.io/react/img/logo_og.png';
const divObject = (
<div>
<p>{text}</p>
<img src={url} alt={'react-icon'} />
</div>
);
JSX语法中,变量可以是值,也可以是另一个React元素对象:
const textObject = <p>{'HelloWorld'}</p>;
const divObject = (
<div>
{textObject}
</div>
)
//相当于
const divObject = (
<div>
<p>{'HelloWorld'}</p>
</div>
);
变量可以为数组,数组的每一个元素必须为React元素对象
const objectArray = [];
const textObject1 = <p>{'HelloWorld1'}</p>;
const textObject2 = <p>{'HelloWorld2'}</p>;
const textObject3 = <p>{'HelloWorld3'}</p>;
objectArray.push(textObject1);
objectArray.push(textObject2);
objectArray.push(textObject3);
const divObject = (
<div>
{objectArray}
</div>
)
//相当于
const divObject = (
<div>
<p>{'HelloWorld1'}</p>
<p>{'HelloWorld2'}</p>
<p>{'HelloWorld3'}</p>
</div>
);
3,ReactDOM
ReactDOM框架提供了将React元素对象渲染到屏幕上的方法。
使用ReactDOM框架首先需要引入
import ReactDOM from 'react-dom';
ReactDOM提供了一个render()方法,通过此方法可以将React元素对象渲染到指定的div标签中。
//通过document操作获取一个div节点
const div = document.getElementById('root');
//通过JSX语法创建一个React元素
const text = <p>{'HelloWorld'}</p> ;
//渲染组件到div中
ReactDOM.render(text,div);
4,React组件
组件化开发是React.js以及后续的ReactNative开发的核心思想。
通过对业务是视图进行封装,组件化开发可以最大化的简化开发过程,增强代码的可复用性和可维护性。
React组件是通过JavaScript类实现的。
通过继承react框架中提供的Component
基础类,构造一个React组件类。
import React , { Component } from 'react';
class MyComponent extends Component {
}
MyComponent
即为React组件,通过React组件也可以创建React元素,让组件显示在屏幕上。
const div = document.getElementById('root');
const myComponent = <MyComponent />;
ReactDOM.render(myComponent,div);
但是这样屏幕上没有任何现实,因为我们还没有实现React组件的内容,但此语法没有问题。
下面我们开始实现React组件
MyComponent通过react框架提供的Component基础类继承了以下方法:
- constructor()
- componentDidMount()
- render()
- componentWillUnmount()
import React , { Component } from 'react';
class MyComponent extends Component {
//组件构造方法,在此方法中对组件内数据进行初始化
//此方法传入参数为props固定不可变更,对于此参数后续介绍
constructor(props){
//此方法中固定在第一行调用super(props)对父类进行初始化
super(props);
}
//此方法为声明周期方法,在该组件显示在屏幕上时,该方法被自动调用
componentDidMount(){
}
//组件内渲染方法
//此方法返回一个React元素作为该组件的外观
render(){
return (
);
}
//此方法为声明周期方法,在该组件从屏幕上消失时,该方法被自动调用
//此方法不常用
componentWillUnmount(){
}
}
实现组件主要实现组件以下两个方面:
- 外观
- 逻辑
这也是React组件和html标签最本质的区别。React组件和外观和html标签很像但组件可以封装自己的业务逻辑,HTML仅仅是展示内容。
我们先实现一个最简单的组件,只显示一个HelloWorld
import React , { Component } from 'react';
class MyComponent extends Component {
render(){
return (
<p>{'HelloWorld'}</p>
);
}
}
此组件只有一个单纯的显示功能,只用到一个render方法。
实现更多负责的组件,需要学习一下两个章节。
5,Props
props是组件属性,通过组件创建元素时,可以为该元素传入属性,所传入的属性可以在组件内部通过this.props
字段访问。
例如我们声明一个显示文字的:
import React , { Component } from 'react';
class MyComponent extends Component {
render(){
return (
<p>{this.props.text}</p>
);
}
}
此组件可以动态显示内容,使用该组件是,只需要向其属性传入相应的值既可以。
const div = document.getElementById('root');
//为元素传入属性的语法在JSX中类似html
const myComponent = <MyComponent text={'HelloWorld'} />
ReactDOM.render(myComponent,div)
展开操作符
在组件属性字段较多时,赋值语句会使标签语法不方便阅读,此时,我们可以采用展开操作符,简化赋值语句
const params = {
name:'Tom',
age:10,
roomName:'101',
}
<MyComponent {...params} />
//相当于
<MyComponent
name={'Tom'}
age={10}
roomName={'101'}
/>
6,State
state是react框架提供了一个页面刷新的机制。它通过this.state
和this.setState()
来实现。
state是React组件通过继承Component获取的一个属性接口。
state是一个对象,在constructor方法中进行初始化,在render方法中使用。
state对象中的值不能直接修改,需要通过this.setState()
方法进行修改。
具体方法,我们通过一个计数器案例来进行讲解:
该技术实现了一个非常简单的计数功能。这个功能中,我们需要根据用户的点击事件来更新页面上的数字。
import React , { Component } from 'react';
export default App extends Component {
constructor(props){
super(props);
this.state = {
count:0,
}
}
render(){
return(
<div>
<h1>{'计数器'}<h1>
<p>{this.state.count}</p>
<p onClick={()=>{
this.setState({
count:this.state.count+1,
})
}}>{'增加'}</p>
<p onClick={()=>{
this.setState({
count:this.state.count-1,
})
}}>{'减少'}</p>
<p onClick={()=>{
this.setState({
count:0,
})
}}>{'归零'}</p>
</div>
)
}
}