React组件
1. 概念
React应用都是构建在组件之上。是React的核心内容,是View的重要组成部分,每一个View页面都是由一个或者多个组件构成。
2. 组件的创建
2.1 函数组件
无状态函数式组件形式上表现为一个只带有一个render方法的组件类,通过函数形式或者ES6 箭头 function 的形式在创建,并且该组件是无state状态的。
用构造函数创建出来的组件,叫做“无状态组件”;
具体创建形式如下
1.引用react模块
2.声明函数
3.向外暴露
import React from 'react';//引用react模块
//定义一个React组件
function App() {
return (
<div>
hello React...
</div>
);
}
export default App;//向外暴露
2.2 class 组件
用class关键字创建出来的组件,叫做“有状态组件”;
React.Component创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则this不能获取当前组件实例对象。
1.引用react模块
2.声明类
3.重写渲染方法
4 向外暴露
//.引用react模块
import React from 'react';
//声明类
class App extends React.Component{
//重写渲染方法
render(){
return (
<div>
Hello,Reactjs!!
</div>
);
}
}
export default App;//向外暴露
在其他文件中引用组件
import React from 'react';
import ReactDOM from 'react-dom';
//App组件,组件要求大写字母开头
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
React.Component有三种手动绑定方法:可以在构造函数中完成绑定,也可以在调用时使用method.bind(this)来完成绑定,还可以使用arrow function来绑定。
//1. 构造函数中绑定
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
//2. 使用bind来绑定
<div onClick={this.handleClick.bind(this)}></div>
//3. 使用箭头函数绑定
<div onClick={()=>this.handleClick()}></div>
函数组件和class组件的区别用构造函数创建出来的组件,叫做“无状态组件”;
用class关键字创建出来的组件,叫做“有状态组件”;
有状态组件和无状态组件之间的本质区别是有无state属性。
注意:
使用class 关键字创建的组件,有自己的私有数据(this.state)和生命周期函数;
使用function创建的组件,只有props,没有自己的私有数据和生命周期函数;
函数组件和类组件当然是有区别的,而且函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件
3. 属性
3.1 props属性
props属性的特点:
-
每个组件对象都会有props(properties的简写)属性
-
组件标签的所有属性都保存在props中
-
内部读取某个属性值:this.props.propertyName
-
作用:通过标签属性从组件外 向组件内传递数据(只读 read only)
-
对props中的属性值进行类型限制和必要性限制(值不能被改变)
代码示例
使用函数组件:
import React from 'react';
import ReactDOM from 'react-dom';
//使用函数组件
function User(props){
//在组件中获取props属性值
return <div>{props.name},{props.age}</div>
}
//定义数据
const person ={
name:'张三',
age:20,
sex:'男'
}
ReactDOM.render(
<User {...person}></User>
, document.getElementById('root'));
使用类组件:
import React from 'react';
import ReactDOM from 'react-dom';
//使用class组件
class User extends React.Component{
render(){
return (
<div>{this.props.name}--{this.props.age}</div>
);
}
}
//数据
const person ={
name:'张三',
age:20,
sex:'男'
}
ReactDOM.render(
<User {...person}></User>
, document.getElementById('root'));
3.2、state 属性
只有类组件中有
声明state属性
this.state={
}
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
代码示例:
import React from 'react';
import ReactDOM from 'react-dom';
class Person extends React.Component{
//构造方法
constructor(){
super();
this.state = {
name: 'tom'
}
}
render(){
//state属性是可修改的
this.state.name = 'jack';
return (
<h1>{this.state.name}</h1>
);
}
}
ReactDOM.render(<Person />, document.getElementById('root'));
设置状态:setState
setState(object nextState[, function callback])
不能在组件内部通过this.state修改状态,因为该状态会在调用setState()后被替换。
setState()并不会立即改变this.state,而是创建一个即将处理的state。setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染。
setState()总是会触发一次组件重绘,除非在shouldComponentUpdate()中实现了一些条件渲染逻辑
3.3、props和state属性的区别
- props中的数据都是外界传递过来的;
- state中的数据都是组件私有的;(通过Ajax获取回来的数据,一般都是私有数据)
- props中的数据都是只读的,不能重新赋值;
- state中的数据,都是可读可写的;
- 子组件只能通过props传递数据;
4. 父子传值
4.1 父传子
父组件 --> 子组件 props属性 F.js 调用了 S.js , S.js中的数据是由 F.js决定的 通过标签(组件)的属性传值
F.js 引入 S.js class F{ <S 属性=值> } S.js {this.props.属性}
父组件代码示例如下:
//父组件里面写的函数
// 类组件
// 先引入模块
import React from 'react';
import User from './User';
// 声明类
class Person extends React.Component{
// 重写渲染方法
render(){
return(
<div className='div'>
<div>hello person</div>
<User str='1'></User>
</div>
);
};
};
// 向外暴露
export default Person;
子组件代码示例如下:
// 创建一个函数组件
// 首先引用react模块
import React from 'react';
// 声明函数
function User(props){
return(
<div><font>hello user</font>
<p>
{props.str}</p>
</div>
)
}
export default User;
4.2 子传父
子组件 --> 父组件
- 在父组件中声明一个函数,用于接收子组件的传值
- 通过组件属性的方法,把函数传递给子组件
- 在子组件中通过props属性调用父组件的函数,并通过参数传值
- 在父组件中的函数通过形参接收子组件的传值
父组件代码示例如下:
// 引用模块
import React from 'react';
import Son from './Son';
// 类函数
class Father extends React.Component{
// 写一个构造方法
message(msg){
console.log(msg)
}
// 重写渲染方法
render(){
return(
<React.Fragment>
<Son mess='hello ' msg={this.message}></Son>
</React.Fragment>
)
}
}
export default Father;
子组件代码示例如下:
import React from 'react';
class Son extends React.Component{
// 重新渲染页面
render(){
//返回值
return(
<React.Fragment>
<p>
{this.props.mess} ,
//传给父组件的值
{this.props.msg(123)}
</p>
</React.Fragment>
)
};
}
// 向外暴露
export default Son;
6. 兄弟传值
- 在父组件中声明一个函数,用于接收子组件的传值
- 通过组件属性的方法,把函数传递给子组件
- 在子组件中通过props属性调用父组件的函数,并通过参数传值
- 在父组件中的函数通过形参接收子组件的传值
- 父组件再传给另一个儿子 通过构造方法 this.state接收 再用父传子的方法就可以了
父组件代码示例如下:
import React from 'react';
import Son from './Son';
import Son2 from './Son2';
//父组件
class Father extends React.Component{
constructor(){
super();
this.state = {
message:''
}
}
//用于接收Son.js组件的数据函数
sonDatas(msg){
this.setState({
message:msg
});
console.log("在Father.js中展示Son.js生成的数据:"+msg);
}
render(){
return (
<React.Fragment>
<h1>在Father组件中显示:</h1>
<Son sondata={this.sonDatas.bind(this)}></Son>
<Son2 mess={this.state.message}></Son2>
</React.Fragment>
);
}
}
export default Father;
子组件1代码示例如下:
import React from 'react';
//子组件
class Son extends React.Component{
//按钮点击事件函数
sonClick(){
this.props.sondata('这是从Son.js中生成的数据。。。');
}
render(){
return (
<React.Fragment>
<button onClick={this.sonClick.bind(this)}>Son组件中的按钮获取数据</button>
</React.Fragment>
);
}
}
export default Son;
子组件2代码示例如下:
import React from 'react';
//子组件
class Son2 extends React.Component{
render(){
return (
<React.Fragment>
<h1>
在Son2.js中展示Son.js中生成的数据,这个是Father.js传过来的,数据是:
{this.props.mess}
</h1>
</React.Fragment>
);
}
}
export default Son2;