一、受控组件
受控组件:input框自己的状态被React组件状态控制
// 类组件引入React
import React from 'react'
class InputComponent extends React.Component{
state = {
message: 'zm66666'
}
changeHandler = (e) => {
this.setState({
message: e.target.value
})
}
render () {
// 使用状态
return (
<div>
{/* 绑定value 绑定事件 */}
<input type='text' value={this.state.message} onChange={this.changeHandler} />
</div>
)
}
}
function App () {
return (
<div className="App">
<InputComponent/>
</div>
)
}
export default App
// 受控组件:input框自己的状态被React组件状态控制
// 1. 在组件的state中声明一个组件的状态数据
// 2. 将状态数据设置为input标签元素的value属性的值
// 3. 为input添加change事件,在事件处理程序中,通过事件对象e获取到当前文本框的值(即用户当前输入的值)
// 4. 调用setState方法,将文本框的值作为state状态的最新值
// 受控组件
import React, { FC, useState, ChangeEvent } from 'react'
// import type { ChangeEvent } from 'react'
const FormDemo: FC = () => {
// input
const [text, setText] = useState<string>('input')
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setText(event.target.value)
}
// textarea
const [text2, setText2] = useState<string>('textarea')
const handleChange2 = (event: ChangeEvent<HTMLTextAreaElement>) => {
setText2(event.target.value)
}
const getHtml = () => {
return { __html: text2.replaceAll('\n', '<br>') }
}
// radio
const [gender, setGender] = useState<string>('male')
const handleChange3 = (event: ChangeEvent<HTMLInputElement>) => {
setGender(event.target.value)
}
// checkbox
// const [checked, setChecked] = useState(false)
// const handleChange4 = (event: ChangeEvent<HTMLInputElement>) => {
// setChecked(!checked)
// }
// checkbox组
const [selectedFruitList, setselectedFruitList] = useState<string[]>([])
const handleChange5 = (event: ChangeEvent<HTMLInputElement>) => {
const fruit = event.target.value
if (selectedFruitList.includes(fruit)) {
setselectedFruitList(selectedFruitList.filter(f => {
if (f === fruit) return false
return true
}))
} else {
setselectedFruitList(selectedFruitList.concat(fruit))
}
}
// select
const [lang, setLang] = useState<string>('js')
const handleChange6 = (event: ChangeEvent<HTMLSelectElement>) => {
setLang(event.target.value)
}
return (
<>
<div>
FormDemo:
<div>
<span>input:</span>
<input type="text" value={text} onChange={handleChange}/>
<button onClick={() => console.log(text)}>打印</button>
<button onClick={() => setText('66666666')}>set</button>
</div>
<div>
<span>textarea:</span>
<textarea value={text2} onChange={handleChange2}/>
<p dangerouslySetInnerHTML={getHtml()}></p>
</div>
<div>
<span>radio:</span>
<label htmlFor="radio1">男</label>
<input type="radio" value='male' name='gender' id='radio1' onChange={handleChange3} checked={gender === 'male'}/>
<label htmlFor="radio2">女</label>
<input type="radio" value='female' name='gender' id='radio2' onChange={handleChange3} checked={gender === 'female'}/>
<button onClick={() => console.log(gender)}>打印{gender}</button>
</div>
{/* <div>
<span>checkbox:</span>
<label htmlFor="checkbox1">选中</label>
<input type="checkbox" id='checkbox' checked={checked} onChange={handleChange4}/>{checked.toString()}
</div> */}
<div>
<span>checkbox组:</span>
<label htmlFor="checkbox1">苹果</label>
<input type="checkbox" id='checkbox1' value='apple' checked={selectedFruitList.includes('apple')} onChange={handleChange5}/>
<label htmlFor="checkbox2">橙子</label>
<input type="checkbox" id='checkbox2' value='orange' checked={selectedFruitList.includes('orange')} onChange={handleChange5}/>
<label htmlFor="checkbox3">香蕉</label>
<input type="checkbox" id='checkbox3' value='banana' checked={selectedFruitList.includes('banana')} onChange={handleChange5}/>
{JSON.stringify(selectedFruitList)}
</div>
<div>
<span>select:</span>
<select value={lang} onChange={handleChange6}>
<option value='java'>java</option>
<option value='js'>js</option>
<option value='php'>php</option>
</select>
</div>
</div>
</>
)
}
export default FormDemo
// 受控组件 vs 非受控组件
// 受控组件: 值同步到state, 使用value属性
// 非受控组件: 值不同步state, 使用defaultValue属性
// react推荐使用受控组件, 看似麻烦,但是 更加可控
二、非受控组件
// 类组件引入React createRef
import React, { createRef } from 'react'
class InputComponent extends React.Component{
// 使用createRef产生一个存放dom的对象容器
msgRef = createRef()
changeHandler = () => {
console.log(this.msgRef.current)
console.log(this.msgRef.current.value)
}
render () {
// 使用状态
return (
<div>
{/* ref绑定 获取真实dom */}
<input ref={this.msgRef} />
<button onClick={this.changeHandler}>click</button>
</div>
)
}
}
function App () {
return (
<div className="App">
<InputComponent/>
</div>
)
}
export default App
// 非受控组件:
// 通过手动操作dom的方式获取文本框的值
// 文本框的状态不受react组件的state中的状态控制
// 直接通过原生dom获取输入框的值
// 1.导入createRef 函数
// 2.调用createRef函数,创建一个ref对象,存储到名为msgRef的实例属性中
// 3.为input添加ref属性,值为msgRef
// 4.在按钮的事件处理程序中,通过msgRef.current即可拿到input对应的dom元素,
// 而其中msgRef.current.value拿到的就是文本框的值
import React from 'react'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
name: '双越',
flag: true,
}
this.nameInputRef = React.createRef() // 创建 ref
this.fileInputRef = React.createRef()
}
render() {
// // input defaultValue
// return <div>
// {/* 使用 defaultValue 而不是 value ,使用 ref */}
// <input defaultValue={this.state.name} ref={this.nameInputRef}/>
// {/* state 并不会随着改变 */}
// <span>state.name: {this.state.name}</span>
// <br/>
// <button onClick={this.alertName}>alert name</button>
// </div>
// // checkbox defaultChecked
// return <div>
// <input
// type="checkbox"
// defaultChecked={this.state.flag}
// />
// </div>
// file
return <div>
<input type="file" ref={this.fileInputRef}/> // 获取上传问卷 要使用非受控组件!!!!!!!!
<button onClick={this.alertFile}>alert file</button>
</div>
}
alertName = () => {
const elem = this.nameInputRef.current // 通过 ref 获取 DOM 节点
alert(elem.value) // 不是 this.state.name
}
alertFile = () => {
const elem = this.fileInputRef.current // 通过 ref 获取 DOM 节点
alert(elem.files[0].name)
}
}
export default App
三、总结