“受控”与“非受控”两个概念,区别在于这个组件的状态是否可以被外部修改。
一个设计得当的组件应该同时支持“受控”与“非受控”两种形式,即当开发者不控制组件属性时,组件自己管理状态,而当开发者控制组件属性时,组件该由属性控制。
而开发一个复杂组件更需要注意这点,以避免只有部分属性受控,使其变成一个半受控组件。
state
,并随着用户的输入自己进行UI上的更新,这种行为是不被我们程序所管控的。而如果将React
里的state
属性和表单元素的值建立依赖关系,再通过onChange
事件与setState()
结合更新state属性
,就能达到控制用户输入过程中表单发生的操作。被React以这种方式控制取值的表单输入元素就叫做受控组件
。<script type="text/babel">
// 受控组件
class Login extends React.Component {
state = {
username: '',//用户名称
password: ''//用户密码
}
// 保存用户名在状态中
saveUsername = (e) => {
this.setState({ username: e.target.value })
}
// 保存密码在状态中
savePassword = (e) => {
console.log(e.target)
this.setState({ password: e.target.value })
}
btnSub = (e) => {
e.preventDefault()
console.log(e)
let { username, password } = this.state
alert(`你输入的用户名是${username},密码是${password}`)
}
render() {
return (
<div>
<form onSubmit={this.btnSub}>
账号:<input type="text" onChange={this.saveUsername} placeholder="输入数据" name='username' />
密码:<input type="text" onChange={this.savePassword} placeholder="输入密码" name='password' />
<button type="submit">点击登录</button>
</form>
</div>
)
}
}
// ReactDOM.render(虚拟dom,真实Dom)
ReactDOM.render(<Login />, document.getElementById('test'))
</script>
数据存储
在 DOM 中,而不是组件内
,这比较类似于传统的 HTML 表单元素。 非受控组件的值不受组件自身的 state
和 props
控制 非受控组件使用ref
从 DOM
中获取元素数据 <script type="text/babel">
// 非受控组件
class Login extends React.Component {
btnSub = (e) => {
e.preventDefault()
console.log(e)
let { username, password } = this
alert(`你输入的用户名是${username.value},密码是${password.value}`)
}
render() {
return (
<div>
<form action="https://kaifa.baidu.com/" onSubmit={this.btnSub}>
账号:<input type="text" ref={c => this.username = c} placeholder="输入数据" name='username' />
密码:<input type="text" ref={c => this.password = c} placeholder="输入密码" name='password' />
<button type="submit">点击登录</button>
</form>
</div>
)
}
}
// ReactDOM.render(虚拟dom,真实Dom)
ReactDOM.render(<Login />, document.getElementById('test'))
</script>
受控组件
React
处理,可以是任何元素
,不局限于
表单元素受控组件
会使程序变得繁琐难控,此时使用非受控组件
更为明智数据流是单向的
( state 是变化来源),因此在改变state
时都应该使用 setState
,而不要强制赋值
Refs
不能用于函数式组件
,因为函数式组件没有实例
组件内部
,是可以使用Refs
的某个阶段会自动执行的函数
。比如我们执行使用render函数,在prop或者state变化时,render函数自动执行,因此render也是React生命周期函数的一员组件挂载阶段
,组件更新阶段
,组件销毁卸载阶段
16.3前后
存在两套生命周期
,16.3之前为旧版
,之后则是新版
,虽有新旧之分,但主体上大同小异。 <script type="text/babel">
class Count extends React.Component {
state = {
count: 0
}
add = () => {
let { count } = this.state
this.setState({
count: count + 1
})
console.log(count)
}
death = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'));
}
force = () => {
this.forceUpdate()//强制更新
}
// 数据更新 '阀门~'
shouldComponentUpdate() {
console.log("shouldComponentUpdate")
return true;//这里必须要有返回值,其次返回值默认是true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log('componentWillUpdate')
}
// 组件更新完成的钩子
componentDidUpdate() {
console.log('componentDidMount')
}
render() {
console.log('render')
return (
<div>
<h1>当前求和为:{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新</button>
</div>
)
}
}
//父组件
class A extends React.Component {
state = {
carName: '红旗'
}
changeCar = () => {
this.setState({
carName: '黑骑士'
})
}
render() {
console.log('我是A')
return (
<div>
<div>我是A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName} />
</div>
)
}
}
//子组件
class B extends A {
// 数据更新 '阀门~'
shouldComponentUpdate() {
console.log("shouldComponentUpdate")
return true;//这里必须要有返回值,其次返回值默认是true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log('componentWillUpdate')
}
// 组件更新完成的钩子
componentDidUpdate() {
console.log('componentDidMount')
}
// 组件将要接受新的数据
componentWillReceiveProps() {
console.log('componentWillReceiveProps')
}
render() {
return (
<div>
<div>我是B组件接收的车是:{this.props.carName}</div>
</div>
)
}
}
ReactDOM.render(<A />, document.getElementById('test'))
</script>
<script type="text/babel">
class Count extends React.Component {
state = {
count: 0
}
add = () => {
let { count } = this.state
this.setState({
count: count + 1
})
console.log(count)
}
death = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'));
}
force = () => {
this.forceUpdate()//强制更新
}
// 数据更新 '阀门~'
shouldComponentUpdate() {
console.log("shouldComponentUpdate")
return true;//这里必须要有返回值,其次返回值默认是true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log('componentWillUpdate')
}
// 组件更新完成的钩子
componentDidUpdate() {
console.log('componentDidMount')
}
render() {
console.log('render')
return (
<div>
<h1>当前求和为:{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新</button>
</div>
)
}
}
class A extends React.Component {
state = {
carName: '红旗'
}
constructor(props){
state
}
changeCar = () => {
this.setState({
carName: '黑骑士'
})
}
static getDerivedStateFromProps(props, state) {
// 这里必须要一个返回值 ==> state or null
// 这里的state会覆盖掉原本的状态并且后续也无法修改
// 能将外部的接受的props复制给组件自身的state
// 如果你希望自身的state 一直,全部,依赖于外部的props,那么可以使用这个生命周期函数
return {
carName: '兰博基尼'
}
}
// 获取数据更新前的快照,能拿到就的props和state
getSnapshotBeforeUpdate(prevProp,prevState){
}
render() {
console.log('我是A')
return (
<div>
<div>我是A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName} />
</div>
)
}
}
class B extends A {
// 数据更新 '阀门~'
shouldComponentUpdate() {
console.log("shouldComponentUpdate")
return true;//这里必须要有返回值,其次返回值默认是true
}
// 组件将要挂载
UNSAFE_componentWillMount() {
console.log('componentWillMount')
}
// 组件将要更新的钩子
UNSAFE_componentWillUpdate() {
console.log('componentWillUpdate')
}
// 组件更新完成的钩子
componentDidUpdate() {
console.log('componentDidMount')
}
// 组件将要接受新的数据
UNSAFE_componentWillReceiveProps() {
console.log('componentWillReceiveProps')
}
render() {
return (
<div>
<div>我是B组件接收的车是:{this.props.carName}</div>
</div>
)
}
}
ReactDOM.render(<A />, document.getElementById('test'))
</script>
will 钩子
,分别为 componentWillMount
、componentWillReceiveProps
、componentWillUpdate
;getDerivedStateFromProps
(从 props
中得到衍生的 state
)和 getSnapshotBeforeUpdate
。render
:初始化渲染或更新渲染调用componentDidMount
:开启监听, 发送ajax请求componentWillUnmount
:做一些收尾工作, 如: 清理定时器function sum(a){
return (b)=>{
return (c)=>{
return a + b + c
}
}
}
const result = sum(1)(2)(3)
class Login extends React.Component {
// 初始化状态
state = {
username:'', // 用户名
password:'', // 密码
}
// 保存表单数据到状态中
saveFormDate=(dataType,event)=>{ // 标识当前标签
this.setState({[dataType]:event.target.value})
}
// 表单提交的回调
handleSubmit=(event)=>{
event.preventDefault(); // 阻止默认事件
let {username,password} = this.state
alert(`你输入的用户名是${username},密码是${password}`)
}
render(){
return(
<div>
<form action="https://www.baidu.com/" onSubmit={this.handleSubmit}>
用户名:<input type="text" onChange={(event)=>this.saveFormDate('username',event)} name="username" />
密码:<input type="text" onChange={(event)=>this.saveFormDate('password',event)} name="password" />
<button type="submit">登录</button>
</form>
</div>
)
}
}
class Login extends React.Component {
// 初始化状态
state = {
username:'', // 用户名
password:'', // 密码
}
// 保存表单数据到状态中
saveFormDate=(dataType)=>{ // 标识当前标签
return (event)=>{ // 这里的回调谁执行? input标签的 onChange事件
this.setState({[dataType]:event.target.value})
}
}
// 表单提交的回调
handleSubmit=(event)=>{
event.preventDefault(); // 阻止默认事件
let {username,password} = this.state
alert(`你输入的用户名是${username},密码是${password}`)
}
render(){
return(
<div>
<form action="https://www.baidu.com/" onSubmit={this.handleSubmit}>
用户名:<input type="text" onChange={this.saveFormDate('username')} name="username" />
密码:<input type="text" onChange={this.saveFormDate('password')} name="password" />
<button type="submit">登录</button>
</form>
</div>
)
}
}
以上就是React面向组件编程中剩下的一部分。希望本篇文章能够帮助到你,若有错误欢迎指出,不懂得可以评论区或者私信问我,我也会一 一解答。谢谢观看!
我的其他文章:https://blog.csdn.net/m0_60970928?type=blog