REACT-受控组件和非受控组件
概述
React中的组件根据是否受React控制可分为受控的和非受控的。
React 中的受控组件和非受控组件都是针对于表单数据而言的。React 推荐使用受控组件来处理表单数据。
受控组件
在一个受控组件中,表单数据是由 React 组件来管理的。
import React, { Component} from 'react'
import ReactDOM from "react-dom";
export default class App extends Component {
state = {
value:'初始值'
}
render() {
return (
<div>
<input type="text" value={this.state.value} onChange={(evt)=>{
this.setState({value:evt.target.value})
}}/>
<button onClick={()=>{
console.log(this.state.value)
}}>登录</button>
<button onClick={()=>{
this.setState({value:""})
}}>重置</button>
<Child value={this.state.value}></Child>
</div>
)
}
}
class Child extends Component {
render() {
return (
<div>
{this.props.value}
</div>
)
}
}
ReactDOM.render(
// <React.StrictMode>
<App />
// </React.StrictMode>
,document.getElementById('root'))
非受控组件
在非受控组件中,表单数据交由 DOM 节点处理,可以使用 ref 来从 DOM 中获取表单数据
import React, { Component} from 'react'
import ReactDOM from "react-dom";
export default class App extends Component {
myref = createRef();
// state = {
// value:'初始值'
// }
render() {
return (
<div>
{/* 想React 能赋予组件一个初始值,但是不去控制后续的更新 可以指定defaultValue*/}
{/* 同样, <input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked , <select>和 <textarea> 支持 defaultValue 。*/}
<input type="text" ref={this.myref} defaultValue="初始值" onChange={(evt)=>{
this.setState({value:evt.target.value})
}}/>
<button onClick={()=>{
console.log(this.myref.current.value)
}}>登录</button>
<button onClick={()=>{
this.myref.current.value = "";
}}>重置</button>
{/* 非受控组件中,dom元素数据(this.myref.current.value)不能进行外部的分享,可以使用状态中的数据进行传递 */}
{/* <Child value={this.myref.current.value}></Child> */}
{/* <Child value={this.state.value}></Child> */}
</div>
)
}
}
class Child extends Component {
render() {
return (
<div>
{this.props.value}
</div>
)
}
}
ReactDOM.render(
// <React.StrictMode>
<App />
// </React.StrictMode>
,document.getElementById('root'))
受控组件应用ToDoList
import React, { Component} from 'react'
import ReactDOM from "react-dom";
export default class ToDoList extends Component {
constructor(){//构造器
//子类必须调用super()
super();//super 调用了父类(Component)的构造函数来去实例化子类本身,可以向父级传参
//必须加this
this.state = {
todoList:[
{
id:1,
text:'eat',
isChecked:false
},
{
id:2,
text:'sleep',
isChecked:true
},
{
id:3,
text:'run',
isChecked:true
},
],
value:'',
}
}
//外部变量可以直接写
// state = {
// todoList:[11,22,33]
// }
render() {
return (
<div>
<input value={this.state.value} onChange={(evt)=>{
this.setState({value:evt.target.value})
}}></input>
<button onClick={()=> this.add()}>添加</button>
<ul>
{this.state.todoList.map((item,index) => {
return (
<li key={item.id} >{/*数据需要进行删除和添加的话,key最好是使用唯一辨识值id*/ }
{/*dangerouslySetInnerHTML的作用相当于VUE中的v-html*/}
<input type="checkbox" checked={item.isChecked} onChange={()=>this.handleChecked(index)}/>
<span dangerouslySetInnerHTML={{__html:item.text}} style={{textDecoration:item.isChecked?'line-through':''}}></span>
<button onClick={()=>this.del(index)}>del</button>
</li>
)
})}
</ul>
{this.state.todoList.length === 0 && <div>暂无待办事项2</div>}{/*第一个条件为真才会执行后面的条件,否则不执行 */}
{/* {this.state.todoList.length === 0?<div>暂无待办事项1</div>:null}
<div>{this.state.todoList.length === 0 && '暂无待办事项3'}</div> */}
</div>
)
}
add(){
let newList = [...this.state.todoList];//尽量不要直接更改原对象
newList.push({id:this.state.todoList.length+1,text:this.state.value,isChecked:false});
this.setState({todoList:newList,value:''});
}
del(index){
//浅克隆
// let newList = this.state.todoList.concat();
let newList = this.state.todoList.slice();
newList.splice(index,1);
this.setState({todoList:newList});
}
handleChecked(index){
let newList = this.state.todoList.slice();
newList[index].isChecked = !newList[index].isChecked;
this.setState({todoList:newList});
}
}
ReactDOM.render(
// <React.StrictMode>
<ToDoList />
// </React.StrictMode>
,document.getElementById('root'))