组件的组合使用
步骤:
1)拆分组件: 拆分界面,抽取组件
2)实现静态组件: 使用组件实现静态页面效果
3)实现动态组件
① 动态显示初始化数据
② 交互功能(从绑定事件监听开始)
问题:数据保存在哪个组件内?
看数据是某个组件需要(给它),还是某些组件需要(给共同的父组件)
问题:子组件需要改变父组件的状态?
子组件不能直接改变父组件的状态,状态在哪个组件,更新状态的行为就在哪个组件
组件收集表单数据
理解
- 问题: 在react应用中, 如何收集表单输入数据
- 包含表单的组件分类
a. 受控组件: 表单项输入数据能自动收集成状态
b. 非受控组件: 需要时才手动读取表单输入框中的数据
<script type="text/babel">
/*
1. 问题: 在react应用中, 如何收集表单输入数据
2. 包含表单的组件分类
受控组件
非受控组件
*/
/*
需求: 自定义包含表单的组件
1. 界面如下所示
2. 输入用户名密码后, 点击登陆提示输入信息
3. 不提交表单
*/
class LoginForm extends React.Component{
constructor(props){
super(props)
this.state = {
password:''
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(event){
const userName = this.nameInput.value
const password = this.state.password
alert(`准备提交的用户名:${userName},密码:${password}`)
//阻止默认行为
event.preventDefault()
}
handleChange(event){
this.setState({password:event.target.value})
}
render(){
return (
<form onSubmit={this.handleSubmit}>
<label>用户名:</label>
<input type="text" ref={input => this.nameInput=input}/>
<br/>
<label>密码:</label>
<input type="text" value={this.state.password} onChange={this.handleChange}/>
<br/>
<input type="submit" value="登录"/>
</form>
)
}
}
ReactDOM.render(
<div>
<LoginForm/>
</div>,
document.getElementById('root')
);
</script>
组件生命周期
理解
- 组件对象从创建到死亡它会经历特定的生命周期阶段
- React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调
- 我们在定义组件时, 可以重写特定的生命周期回调函数, 做特定的工作
生命周期详述
- 组件的三个生命周期状态:
- Mount:插入真实 DOM
- Update:被重新渲染
- Unmount:被移出真实 DOM
- React 为每个状态都提供了勾子(hook)函数
- componentWillMount()
- componentDidMount()
- componentWillUpdate()
- componentDidUpdate()
- componentWillUnmount()
- 生命周期流程:
a. 第一次初始化渲染显示: ReactDOM.render()
- constructor(): 创建对象初始化state
- componentWillMount() : 将要插入回调
- render() : 用于插入虚拟DOM回调
- componentDidMount() : 已经插入回调
b. 每次更新state: this.setSate() - componentWillUpdate() : 将要更新回调
- render() : 更新(重新渲染)
- componentDidUpdate() : 已经更新回调
c. 移除组件: ReactDOM.unmountComponentAtNode(containerDom) - componentWillUnmount() : 组件将要被移除回调
重要的勾子
- render(): 初始化渲染或更新渲染调用
- componentDidMount(): 开启监听, 发送ajax请求
- componentWillUnmount(): 做一些收尾工作, 如: 清理定时器
- componentWillReceiveProps(): 该方法当props发生变化时执行
/*
需求: 自定义组件
1. 让指定的文本做显示/隐藏的动画
2. 切换时间为2S
3. 点击按钮从界面中移除组件界面
*/
class Life extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state={
opacity: 1
}
this.distroyComponent = this.distroyComponent.bind(this)
}
distroyComponent(){
ReactDOM.unmountComponentAtNode(document.getElementById('example'))
}
componentDidMount(){// 在此方法中启动定时器/绑定监听/发送ajax请求
//循环定时器
this.intervalId = setInterval(function(){ //setInterval的this 是windows
console.log('定时器执行。。。')
let {opacity} = this.state
opacity -= 0.1
if(opacity<=0){
opacity=1
}
this.setState({opacity})
}.bind(this),200)
}
componentWillUnmount(){// 清除定时器/解除监听
console.log('componentWillUnmount(): 将要被移除')
clearInterval(this.intervalId)
}
render(){
const {opacity} = this.state
return (
<div>
<h2 style={{opacity}}>{this.props.msg}</h2>
<button onClick={this.distroyComponent}>不活了</button>
</div>
)
}
}
组件间通信
5.1.1. 方式一: 通过props传递
-
共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
-
通过props可以传递一般数据和函数数据, 只能一层一层传递
-
一般数据-->父组件传递数据给子组件-->子组件读取数据
-
函数数据-->子组件传递数据给父组件-->子组件调用函数
5.1.2. 方式二: 使用消息订阅(subscribe)-发布(publish)机制
-
工具库: PubSubJS
-
下载: npm install pubsub-js --save
-
使用: import PubSub from 'pubsub-js' //引入 PubSub.subscribe('delete', function(data){ }); //订阅 PubSub.publish('delete', data) //发布消息
5.1.3. 方式三: redux
参考文章