上节课我们学习了关于react
的事件处理,说了关于ref
是否可以省略。这节课我们将开始进入下一课的学习,非受控组件。
回顾
在学习非受控组件之前,我们来对上节课内容来进行简单的回顾。
- 不要过度使用
ref
- 事件监听要严格注意大小写
- 通过
event.target
获取到事件发生的DOM
元素
以上便是上节课的内容,接下来我们开始进入新课程的学习。
收集表单数据
可能有朋友要问了,我们的大标题叫非受控组件,怎么扯到表单数据收集了呢?其实我们将通过表单数据的收集来介绍受控组件和非受控组件。
可能有人要问这个受控是啥意思?其实就是字面意思,收到控制,受到谁的控制?先不纠结咱们在学习中慢慢探讨。
案例需求
我们先来看一下我们的案例需求是什么?
- 定义一个包含表单的组件
- 输入用户名和密码点击登录之后提示相关信息
案例实现
我们这个需求其实很简单,就是最基本的用户登录操作,只不过我们把登录那一步去掉了,换成了展示信息。
实现页面基本结构
那我们先不要那么着急,一步一步来,先把基本页面实现了:
class Login extends React.Component { render() { return ( <form action="#"> Username: <input type="text" /> Password: <input type="password" /> <button>Submit</button> </form> ); } } ReactDOM.render(<Login />, document.getElementById("test"));
我们来看一下这段代码,很简单的几个步骤:
- 创建组件
- 编写
render
方法 - 返回一个
form
表单 - 编写页面基本元素
- 渲染组件
我们来看一下结果:
这样页面的基本结构算是完成了也可以输入用户名和密码,而且密码也是密文。
点击按钮触发结果
大家想一想现在submit
按钮起作用吗?我们还没有加点击事件。但是我们先不考虑按钮的点击事件,我们就先思考一下如果我们点击了会怎么样呢?
大家注意看一下我们的form
标签。form
标签里面是不是有一个action
属性?这个属性是干什么的大家应该都清楚,就是点击提交按钮之后我们表单往那提交呢,其实就是往我们action
属性的链接里面提交。那我们把action
属性设定成了#
看一下点击前和点击后的效果:
所以大家看见了,这其实是页面跳转了。即便我没有给submit
按钮添加onClick
事件,但是点击按钮还是出现了页面出现跳转的情况。可能大家看着还是不够直观。我们把action
属性改一下<form action="https://www.baidu.com">
我们把链接改成了百度,那么这次点击是不是就会跳转到百度呢?
我们来看,点击按钮之后确实跳转到了百度,但是url
后面是不是还有一个问号啊?这个问号是什么意思呢?
form
表单信息
我们之前说过表单信息是要提交给action
属性中的链接的,如果我们没有指定请求方式,那么我们form
表单发出的是不是GET
请求?GET
请求的参数会体现在url
上,并通过问号来将参数列表和url
链接进行隔开。而form
表单发出GET
请求带的参数是query
参数。但是呢我们从url
上面来看,只有一个问号,问号后面的参数呢?
我们再回头看代码,我们的input
标签是不是只有type
标签?而且我们也知道form
表单提交出去的参数肯定就是这里input
栏输入的数据,但是form
表单知道这两个input
中输入的值分别都是什么吗?不知道啊,所以说input
标签我们需要给他们加上name
属性,这样form
表单才知道这两个input
栏输入的参数名称分别是什么,那我们改一下代码再看看效果
class Login extends React.Component { render() { return ( <form action="https://www.baidu.com"> Username: <input type="text" name="username" /> Password: <input type="password" name="password" /> <button>Submit</button> </form> ); } }
看看这次的效果是什么样子:
这次跳转到了百度,而且参数也带上了。
但是我们要做的是跳转到百度吗?当然不是,我们是想弹窗提示用户登录成功啊。那我们怎么办?可能有朋友要说,那我给按钮绑定一个onClick
事件,然后通过refs
来做不就得了。当然这种做法 OK 的,没毛病,天王老子来了都不能说你这个做法是错的。但是那样做的话,我们还写表单干什么啊?
form
表单事件
那么如果我们不用这种方法还有什么方法可以用呢?我们来回想一下form
标签是不是有一个原生的onsubmit
属性?那么在react
中的话呢?回忆一下之前说过的是不是就有一个对应的onSubmit
?那么是不是就简单很多了?给一个回调呗:
class Login extends React.Component { notify = () => {} render() {return <form action="https://www.baidu.com" onSubmit={this.notify}>...</form>} }
那么好,我们来分析一下上面这段代码,我们给表单加了onSubmit
事件绑定,要求表单在提交时直接执行我们给的回调。那么这个回调函数我们得定义啊。赋值语句加箭头函数来定义这个回调函数。好,这个回调函数这么写?
分析一下:
- 我们是不是要展示
input
栏输入的信息? onSubmit
是不是加给form
标签的?
那么这样的话我们能用event.target
来获取吗?肯定不能啊,那么我们就得给这两个input
标签添加ref
了啊,那我们再来改一下代码:
class Login extends React.Component { notify = () => { const {username, password} = this; alert(`{username.value}: {password.value}`); } render() { return ( <form action="https://www.baidu.com" onSubmit={this.notify}> Username: <input ref={c => this.username = c} type="text" name="username" /> Password: <input ref={c => this.password = c} type="password" name="password" /> <button>Submit</button> </form> ); } }
现在我们来看:我们用回调函数的形式给两个input
标签都加上了ref
,那么notify
回调函数是不是就好写了?你看我们这两个ref
分别在this
上加了username
和password
属性,而且这两个属性还分别就是这两个input
标签的DOM
节点,但是我们想要展示值,那么是不是该取value
属性?所以说notify
方法中第一步先结构赋值,然后展示这两个节点的value
。那么我们来看一下啊结果:
这下我们可以成功展示出form
表单中的信息了,但是这个弹窗提醒我们点了确定之后就有问题了:
又跳转到百度了。可能有朋友要说,这有啥问题啊?表单提交嘛,本来就是往这提交的啊。但是我们的需求是什么啊?我们就想提示信息,我们并不想真正地提交,不想让页面跳转出去,我们不想让页面刷新。或许有朋友要说,那你不写action
属性不就行了嘛。那我们来试试。
大家觉得什么叫做页面没有刷新?是不是没有触发刷新按钮?而且url
也没有任何变化,这种才是页面没有刷新?这两个条件缺一不可。那么我们看一下图里。url
变了,如果我这边是个视频的话,大家会看见刷新按钮是被触发过一次的。所以说不给action
属性其实没有用。
但是表单提交是表单默认动作,我们怎么禁止这种动作呢?其实表单是有原生的阻止默认事件的方法的。那么我们再来修改一下:
class Login extends React.Component { notify = e => { e.preventDefault(); ... } render() {...} }
我们在notify
用e
参数接收event
,然后调用event
的preventDefault
方法就可以完成默认事件的禁用。我们再看一下效果:
点击了确定之后,什么变化都没有。但是这个禁用掉了,我们怎么提交呢?这里就要提到我们曾经学到过得ajax
了,当然有关ajax
不是我们目前需要重点讨论的。只是先提一下。
非受控组件
其实我们至此我们就已经完成了一个非受控组件。但是这是什么意思呢?
我们来思考几个问题:
- 页面里面是不是有表单,而且表单中有两个输入项?
- 是不是我们点击
Submit
按钮的时候才获取到两个输入项的值?
那么好,我们有这样一个结论,上面页面表单中的所有输入类DOM
的值,现取现用的话就是非受控组件,可能大家要说,啥叫现取现用?我们看我们上面的写法:是不是我们在notify
方法中才要用到我们输入类的DOM
的值?那么这个值是在什么时候获取取的?是不是在notify
方法中在使用前才去通过this
来获取?也就是说这种只有在需要使用输入类的DOM
的值的时候才去获取的话,那么这个组件就是非受控组件。
总结
form
表单可以用onSubmit
事件来代替给提交按钮加onClick
事件form
表单的onSubmit
事件的回调方法中可以通过event
来禁用默认提交事件- 禁用了
form
表单的默认提交事件后可以通过ajax
来完成与后台的交互 - 现用现取则是非受控
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/uncontroled_component/