所有的demo源码:https://github.com/Ching-Lee/react-base
1.概念
组件就像JavaScript中的方法,他们接收一个参数props,表示属性,返回要显示在屏幕上的元素。
注意:自定义的组件首字母必须大写。如果是小写,React会认为这是DOM的标签。
2.定义组件
demo03:
<body>
<div id="firstComponent"></div>
<div id="secondComponent"></div>
<script type="text/babel">
//使用方法定义组件
function Welcome(props) {
return <h1>Hello,{props.name}</h1>
}
//使用类定义组件
class Wel extends React.Component{
render(){
return <h1>Hello,{this.props.name}</h1>
}
}
ReactDOM.render(<Welcome name="用function定义的Welcome组件"/>,document.getElementById("firstComponent"));
ReactDOM.render(<Wel name="用class定义的Wel组件"/>,document.getElementById("secondComponent"));
</script>
</body>
![](https://img.haomeiwen.com/i8521343/dfe7ad90e6bbcdca.png)
3.组件可以使用其他组件构成
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
4.组件的生命周期
组件的生命周期包括初始化、运行中、销毁三个阶段,每个阶段有相应的方法。
- 初始化阶段
![](https://img.haomeiwen.com/i8521343/578e15bbf8ffbef1.png)
- 运行中阶段
![](https://img.haomeiwen.com/i8521343/518eb32bb7532a7b.png)
- 销毁阶段
![](https://img.haomeiwen.com/i8521343/4ba0b56f1d033573.png)
示例:定时器
1)只使用render完成:demo04
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件的生命周期</title>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<script type="text/babel">
class Clock extends React.Component {
render() {
return (
<div>
<h1>定时器使用render完成</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
function tick() {
ReactDOM.render(<Clock date={new Date()}/>,document.body);
}
setInterval(tick,1000);
</script>
</body>
</html>
![](https://img.haomeiwen.com/i8521343/f515a408000cd523.png)
2)使用生命周期中相关函数完成
demo05
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>state和生命周期</title>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<script type="text/babel">
class Clock extends React.Component{
constructor(props){
super (props);
this.state={date:new Date()};
}
render(){
return(
<div>
<h1>生命周期和state</h1>
<h2>It is {this.state.date.toLocaleTimeString()}</h2>
</div>
);
}
tick(){
this.setState({date:new Date()});
}
//在初始阶段渲染完成后,设置state值,获取实时时间
componentDidMount(){
this.intervalId=setInterval(()=>this.tick(),1000);
}
//在销毁阶段
componentWillUnmount(){
clearInterval(this.intervalId);
}
}
ReactDOM.render(<Clock/>,document.body);
</script>
</body>
</html>
5. props和state 详解
5.1 属性
- 属性的含义
props=properties
组件的属性是只读的,不可以改变。 -
属性的使用
- props类型验证
官网:https://www.npmjs.com/package/prop-types
组件的props属性的值有类型限制
import PropTypes from 'prop-types';
组件名.propTypes={
//传递的userid属性值必须是number类型
userid:Proptypes.number,
//如果这个属性值是必须的,调用该组件的时候必须要传递这个值
userid:Proptypes.number.isRequired
};
组件中可以定义默认的属性值
组件名.defaultProps=自己定义的属性对象。
![](https://img.haomeiwen.com/i8521343/9b205689d762830d.png)
5.2 状态state
- 状态的含义
state:在组件中可以改变 - 状态的用法
getInitialState:初始化每个实例的特有状态
setState:更新组件状态
this.setState({comment: 'Hello'});
注意:props和state的更新是异步的,你不能依赖他们的值去计算下一个state。
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
//为了解决上述问题,使用如下形式的setState(),它接收的参数是函数,而不是对象,将之前的state作为第一个参数,属性作为第二个参数。
// Correct
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});
//使用箭头函数
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
![](https://img.haomeiwen.com/i8521343/da75d6b45b53c375.png)
setState发生之后会触发diff算法,diff算法会判断state变化之后的结果和目前页面上结果有什么区别,如果没有区别,则页面不需要更新。如果页面有区别,则找出不同的地方并更新特定的位置的DOM。
5.3 属性和状态的对比
- 相似点
1)都是纯Js对象
2)都会触发render更新
3)都具有确定性
![](https://img.haomeiwen.com/i8521343/feda3ad1f04a99ec.png)
5.4 属性和状态实战
实现一个评论框:demo06
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<script type="text/babel">
class Content extends React.Component {
constructor(props){
super(props);
}
render() {
return <p>{this.props.selectName}</p>;
}
}
class Comment extends React.Component {
constructor(props){
super(props);
this.state={names:["Tim","John","Hank"],selectName:''};
}
//当select发生改变时,设置state的selectName的值
handleSelect(event){
this.setState({selectName:event.target.value});
}
render() {
let options=[];
for(let option in this.state.names){
options.push(<option value={this.state.names[option]}>{this.state.names[option]}</option>);
}
//注意,这里必须使用箭头函数,需要将 handleSelect方法中的this作用域在定义时指定为组件(也就是类)
return (
<div>
<select onChange={(event)=>this.handleSelect(event)}>
{options}
</select>
<Content selectName={this.state.selectName}/>
</div>
);
}
}
ReactDOM.render(<Comment/>,document.body);
</script>
</body>
</html>
6.组件的refs
我们有的时候也需要获取原生的html元素结点
//方式1
let button=document.getElementById('submitButton');
ReactDOM.findDOMNode(button).style.color='red';
//方式2
可以给元素添加refs属性,直接获取
<button refs="submitButton">提交</button>
this.refs.submitButton.style.color='red';
![](https://img.haomeiwen.com/i8521343/03018478653198b4.png)
7.独立组件间共享Mixins
安装mixin的包
sudo npm install --save react-mixin
mixin.js
//定义了一个 MixinLog对象
const MixinLog={
log(){
console.log("abcdefg...")
}
};
export default MixinLog
其他js文件中调用
import ReactMixin from 'react-mixin'
import MixinLog from './mixins';
ReactMixin(类名.prototype,Mixinlog)
//可以直接使用Mixinlog对象
Mixinlog.log();
网友评论