目录
1.组件form
受控组件及其特点
非受控组件及其特点
模拟:简单受控组件表单
input两个方向绑定数据:
模拟:复杂(真实)受控组件表单(form里面有多种数据输入)
注意:handleChange1~5 中代码重复率高。
降低代码重复写法降低代码重复写法
模拟:非受控组件
受控组件形式自动时钟
非受控组件形式自动时钟
2.ref-函数类型实现
3.createRef实现
createRef实现自动化时钟
2.业务场景(登录)=>ref模拟form表单收集
三种非受控表单解决方式
方式一:ref="key" 原理:this.refs={} => this.refs={key:真实DOM}
方式二:ref={e=>this.key=e} =>直接赋值this.key=真实DOM
方式三:直接调用react提供的方法createRef();this.key=React.createRef()
事件绑定受控表单方式
3.业务衍生场景=>按钮触发事件
4.业务衍生场景=>表单自动获取焦点
组件受状态和属性变化控制,称为受控组件。
特点:数据驱动,组件不直接操作DOM,而是由ReactDOM自动同步
组件不受状态和属性变化控制,称为非受控组件。
特点:可以直接操作DOM,类似于传统的html表单操作,通过ref获取真实DOM。
(数据传递) =>数据源state+属性绑定value+事件监听onChange
class App extends React.Component{
state = {name:"",age:18}
handleClick = () ={
console.log("form data:",this.state)
}
handleChange = (e) ={
console.log(e.target.value) //获取到input输入内容
this.setState({
name:e.target.value
})
}
input两个方向绑定数据:
1.通过value,同步state=>input (属性绑定)
2.通过onChange,同步input输入输入内容=>state (事件绑定)
render(){
return(
)
}
}
ReactDOM.render(
,document.getElementById("app"))
class App extends React.Component{
state = {
name:"user",
age:18,
single:false,
desc:"intoduction",
hobby:"playing"
}
handleSubmit=()={
//获取收集表单数据
console.log("form data:",this.state)
//提交数据
//阻止默认行为
e.preventDefault()
}
handleChange1 = (e) ={
this.setState({
name:e.target.value
})
}
handleChange2 = (e) ={
this.setState({
age:e.target.value
})
}
handleChange3 = (e) ={
console.log(e.target.checked) //点击,在true和false之间来回切换
//将表单中内容同步到数据中
this.setState({
single:e.target.checked
})
}
handleChange4 = (e) ={
this.setState({
desc.target.value
})
}
handleChange5 = (e) ={
this.setState({
hobby:e.target.value
})
}
render(){
return(
)
}
}
ReactDOM.render(
,document.getElementById("app"))
this.setState({key:value}),key动态,value:r.target.value,注意:e.target.checked不同
class App extends React.Component{
state = {
name:"user",
age:18,
single:false,
desc:"intoduction",
hobby:"playing"
}
handleSubmit=()={
//获取收集表单数据
console.log("form data:",this.state)
//提交数据
//阻止默认行为
e.preventDefault()
}
handleChange = (e) ={
console.dir(e.target)
let target = e.target
let key = target.name
//注意:checkedbox情况不同value = target.checked,追加判断
let type = target.type
let value = type==checkedbox?target.checked:target.value
this.setState({
[key]:value //动态追加key
})
}
render(){
return(
)
}
}
ReactDOM.render(
,document.getElementById("app"))
class Clock extends React.Components{
state = {time:new Date().toLocalTimeString()}
render(){
return(
{this.state.time}
)
}
componentDidMount(){ //第一次挂载完毕生命周期的钩子函数自动执行
setInterval(()=>{
this.setState({
time:new Date().toLocalTimeString()
})
},1000)
}
}
ReactDOM.render(
,document.getElementById("app"))
1.真实DOM容器ref-string类型实现
组件实例属性:this.ref = {},这个对象容器用来存储真实DOM的引用
class Clock extends React.Component{
render(){
return(
2.将真实DOM放在this.ref容器中
通过creatElement创建虚拟DOM,新增ref属性
通过ReactDOM.render同步渲染虚拟DOM=>真实DOM=>判断是否有ref属性
==>有ref:将ref属性对应的虚拟DOM转化成真实DOM=>放在this.ref={}容器中
[ 将ref属性对应的值作为key,将真实DOM作为value ]
ref="timeRef">{new Date().toLocalTimeString()}
//ref容器中存放:{timeRef:真实DOM
}
)
}
componentDidMount(){ //已经渲染完毕,可以拿到真实DOM
setInterval(()=>{
3.this.ref中获取操作真实DOM=>给
重新赋值
this.refs.timeRef.innerHTML = new Date().toLocaleTimeString()
},1000)
}
}
ReactDOM.render(
,document.getElementById("app"))
组件实例.refs = {key:真实DOM} ; key是ref属性对应的值
组件实例直接挂载key,组件实例.key=真实DOM => 自动化时钟
class Clock extends React.Component{
render(){
return(
2.将真实DOM放在this.ref容器中
通过creatElement创建虚拟DOM,新增ref属性
通过ReactDOM.render同步渲染虚拟DOM=>真实DOM=>判断是否有ref属性
==>有ref:ref属性对应的值是否是一个函数
==>是函数,直接执行这个函数,并将真实DOM作为参数传递。[组件实例.key=真实DOM]
this.timeRef=e}>{new Dare().oLocaleTimeString()}
{this.timeRef2=element}}>
{new Date().toLocalTimeString()}
)
}
//组建挂载完毕:组件第一次渲染完毕执行=>虚拟DOM已经完全转化为真实DOM
compomentDidMount(){
console.loh(this)//组件实例
console.loh(this.ref)//组件ref容器
setInterval(()=>{
//this.key = 真实DOM{对应此处的
标签}
this.refs.timeRef.innerHTML = new Date().toLoacleTimeString();
this.refs.timeRef.innerHTML = new Date().toLoacleTimeString();
})
}
}
ReactDOM.render(
,document.getElementById("app"))
React中creatRef源码:
//a immutable object(不可改变的对象) with single mutable value
function creatRef(){
var refObject={
current:null;
};
{
Object.seal(refObject );
//seal封装,对参数对象进行封闭,不能添加新的属性,只能有一个属性
}
return refObject;
}
注意:
执行React.creatRef()=>返回{ current:null }对象容器,但是这个返回值源码没有挂载到组件实例上.
所以我们需要进行手动挂载this.key = React.createRef()上。
class Clock extends React.Component{
constructor(props){
super(props)
this.timeRef=React.createRef() //{current:null}
}
render(){
return(
通过createElement创建虚拟DOM,新增ref属性,
ReactDOM.render把虚拟DOM同步渲染成真实DOM=>判断是否有ref存在
如果有ref,会把ref对应的值,即{current:null}容器,将真实DOM
赋值给容器current属性
和2的区别:
不需要给引用容器提供key
}>{new Date().toLocalTimeString()}
)
}
componentDidMount(){
console.log(this)
console.log(this.ref)
setInterval(()=>{
//this.key.current=真实DOM
this.timeRef,current.innerHTML = new Date().toLocalTimeString()
},1000)
}
}
方式一:ref="key" 原理:this.refs={} => this.refs={key:真实DOM}
方式二:ref={e=>this.key=e} =>直接赋值this.key=真实DOM
方式三:直接调用react提供的方法createRef();this.key=React.createRef():{current:nulll}=>{current:真实DOM}
class Form extends React.Component{
console.log(this)
console.log(this.refs.inputRef) //真实DOM
console.log(this.refs.inputRef.value)
render(){
return(
)
}
}
class Form extends React.Component{
console.log(this.inputRef2) //真实DOM
console.log(this.inputRef2.value) //获取input输入内容
render(){
return(
this.inputRefs2=e}/>
)
}
}
class Form extends React.Component{
console.log(this.inputRef3) //非真实DOM,是个对象容器
console.log(this.inputRef3.current) //真实DOM
console.log(this.inputRef3.current.value) //获取input输入内容
constructor(){
super()
this.inputRef3=React.createRef()
}
render(){
return(
)
}
}
class Form extends React.Component{
handleChange=>(e)=>{
console.log("onChange") //input输入框中每输入一个触发一次onChange
console.log(e.targrt.value)
}
render(){
return(
)
}
}
class Form extends React.Component{
constructor(){
super();
this.inputRef = React.createRef()
}
handleClick=()=>{
alert( this.inputRef.current.value)
}
handleBlur=(e)={
console.log(e.target) //真实DOM
console.log(e.target.value) //输入框内容
alert(e.target.value);
}
render(){
return(
handleBlur}/>
inputRef}/>
)
}
}
ReactDOM.render(
,document.getElementById("app"))
class Form extends React.Component{
constructor(){
super();
this.inputRef = React.createRef()
}
handleClick=()=>{
this.inputRef.current.focus()
}
render(){
return(
inputRef}/>
)
}
//已经渲染完毕,可以直接直接使用真实DOM
componentDidMount(){
this.inputRef.current.focus()
}
}
ReactDOM.render(
,document.getElementById("app"))