需求:定义一个包含表单的组件
输入用户名密码后,点击登录 提示输入信息
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="test"></div>
</body>
<!-- react 核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!-- react-dom ,用于支持 react 操作 DOM -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 将 jsx 转化成 js -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
//1、创建组件
class Login extends React.Component{
handleSubmit=(event)=>{
event.preventDefault();
const {username,password} = this;
alert(`你数据的用户名是:${username.value},你输入的密码是:${password.value}`)
}
render(){
return (
<form action='http://www.learning.com' onSubmit={this.handleSubmit}>
用户名: <input ref={c=>this.username=c} type='text' name='username'>
密码: <input ref={c=>this.password=c} type='password' name='password'>
<button>按钮</button>
</form>
)
}
}
//form 表单默认是 get 请求,parameter 传参。
//2、渲染虚拟DOM到页面
ReactDOM.render(<Login/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
</html>
包含表单的组件分类:
页面中所有输入类的dom,比如说 input 框,这种输入类的dom ,随着你的输入,就能把输入的东西 维护到状态里面,需要使用的时候直接从状态里面取出来,这种组件就属于 受控组件。相当于 vue 中的双向数据绑定。
优势在于 :能够减少 ref 的使用。
受控组件代码示例:
<script type="text/babel">
//1、创建组件
class Login extends React.Component{
//初始化状态
state ={
username:"",//用户名
password:""//密码
}
handleSubmit=(event)=>{
event.preventDefault(); //阻止表单的提交
const {username,password} = this.state;
alert(`你数据的用户名是:${username},你输入的密码是:${password}`)
}
saveUsername = (event)=>{
this.setState({username:event.target.value})//用户名维护到 状态里
}
savePassword = (event)=>{
this.setState({password:event.target.value})//密码维护到 状态里
}
render(){
return (
<form action='http://www.learning.com' onSubmit={this.handleSubmit}>
用户名: <input onChange={this.saveUsername} ref={c=>this.username=c} type='text' name='username'>
密码: <input onChange={this.savePassword } ref={c=>this.password=c} type='password' name='password'>
<button>按钮</button>
</form>
)
}
}
//form 表单默认是 get 请求,parameter 传参。
//2、渲染虚拟DOM到页面
ReactDOM.render(<Login/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
现用现取。等到使用的时候才会去拿 ref 中的值。 不建议使用,尽量少用 ref,会引起性能问题。
代码示例:
<script type="text/babel">
//1、创建组件
class Login extends React.Component{
handleSubmit=(event)=>{
event.preventDefault();
const {username,password} = this;
alert(`你数据的用户名是:${username.value},你输入的密码是:${password.value}`)
}
render(){
return (
<form action='http://www.learning.com' onSubmit={this.handleSubmit}>
用户名: <input ref={c=>this.username=c} type='text' name='username'>
密码: <input ref={c=>this.password=c} type='password' name='password'>
<button>按钮</button>
</form>
)
}
}
//form 表单默认是 get 请求,parameter 传参。
//2、渲染虚拟DOM到页面
ReactDOM.render(<Login/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
定义:如果一个函数符合 下面 2个规范中的任何一个,那该函数就是 高阶函数:
1)若 A 函数,接收的参数是一个 函数,那么A 函数就可以称之为高阶函数;
2)若 A 函数,调用的返回值依然是一个函数,那么A 函数就可以称之为高阶函数;(saveFormData函数符合该条件)
常见的高阶函数:
Promise 、数组的 filter 方法、setTimeout(接收函数参数)、arr.map() 等等;
<script type="text/babel">
//1、创建组件
class Login extends React.Component{
//初始化状态
state ={
username:"",//用户名
password:""//密码
}
handleSubmit=(event)=>{
event.preventDefault(); //阻止表单的提交
const {username,password} = this.state;
alert(`你数据的用户名是:${username},你输入的密码是:${password}`)
}
// saveFormData 的返回值是一个 函数。 对象中的所有的对象名都是一个 字符串。
saveFormData= (dataType)=>{
return (event)=>{ // 必须把 一个函数作为函数的回调交给 react 。这个就是 高阶函数。event 是 react 帮忙维护的事件
this.setState({[dataType]:event.target.value})
}
}
render(){
return (
<form action='http://www.learning.com' onSubmit={this.handleSubmit}>
用户名: <input onChange={this.saveFormData('username')} ref={c=>this.username=c} type='text' name='username'>
密码: <input onChange={this.saveFormData('password')} ref={c=>this.password=c} type='password' name='password'>
<button>按钮</button>
</form>
)
}
}
//form 表单默认是 get 请求,parameter 传参。
//2、渲染虚拟DOM到页面
ReactDOM.render(<Login/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
上面代码不使用高阶函数实现示例:
<script type="text/babel">
//1、创建组件
class Login extends React.Component{
//初始化状态
state ={
username:"",//用户名
password:""//密码
}
handleSubmit=(event)=>{
event.preventDefault(); //阻止表单的提交
const {username,password} = this.state;
alert(`你数据的用户名是:${username},你输入的密码是:${password}`)
}
// saveFormData 的返回值是一个 函数。 对象中的所有的对象名都是一个 字符串。
saveFormData= (dataType,value)=>{
this.setState({[dataType]:value})
}
render(){
return (
<form action='http://www.learning.com' onSubmit={this.handleSubmit}>
用户名: <input onChange={event=>{this.saveFormData('username',event.target.value)}} ref={c=>this.username=c} type='text' name='username'>
密码: <input onChange={event=>{this.saveFormData('password',event.target.value)}} ref={c=>this.password=c} type='password' name='password'>
<button>按钮</button>
</form>
)
}
}
//form 表单默认是 get 请求,parameter 传参。
//2、渲染虚拟DOM到页面
ReactDOM.render(<Login/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
补充:对象相关的知识
<scritp>
let a = "name"
let obj = {} //{name:Tom}
obj[a] = "Tom"
console.log(obj)
</scritp>
定义:通过函数连续调用返回函数的方式,实现多次接收参数,最后统一处理的函数编码形式。
代码示例:
<scritp>
//需求:求三个数的和。
/*
//常规写法
function sum(a,b,c){
return a+b+c;
}
*/
//函数柯里化的方式
function sum(a,b,c){
return (b)=>{
return (c)=>{
return a+b+c;
}
}
}
</scritp>
需求:定义组件实现以下功能:
1、让指定的问你本做 显示/隐藏 的渐变动画
2、从完全可知,到彻底消失,耗时2s
3、点击“不活了” 按钮从界面中卸载组件。
生命周期回调函数《》生命周期钩子函数 《》
状态中的数据可以驱动视图的变化。
代码示例:
<script type="text/babel">
//1、创建组件
class Life extends React.Component{
state={
opacity:1
}
componentDidMount(){ //render 的兄弟,只调用一次。组件挂载完毕
this.timer = setInterval(()=>{
let {opacity} = this.state;
opacity -= 0.1 //设置透明度
if(opacity <= 0){
opacity = 1;
}
this.setState({opacity})
},200)
}
//组件将要被卸载的时候调用
componentWillUnmount(){
//清除定时器
clearInterval(this.timer);
}
death = ()=>{
//卸载组件。 ReactDOM.unmountComponentAtNode();
ReactDOM.unmountComponentAtNode(document.getElementById("test));
}
render(){//render 调用次数 1(初始化)+n (state中的数据变化)
return {
<div>
<h2 style={{opacity:this.state.opacity}}>React 学不会,怎么办?</h2>
<button onClick={this.death}>不活了</button>
</div>
}
}
}
//form 表单默认是 get 请求,parameter 传参。
//2、渲染虚拟DOM到页面
ReactDOM.render(<Life />, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
挂载:mount
卸载:unmount
1)组件从创建到死亡会经历的一些特定的阶段;
2)React 组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用;
3)我们在定义组件时,会在特定的生命周期函数中,做特定的工作。
<script type="text/babel">
//1、创建组件
class Count extends React.Component{
//构造器 ---- 初始化
constructor(props){
console.log("Count --- constructor); //第 1 步打印
super(props);
//初始化状态
this.state={ count:0 };
}
add=()=>{
let {count} = this.state;//获取原状态
this.setState({count:count+1})
}
//组件将要挂载的 钩子
componentWillMount(){
console.log("Count --- componentWillMount") //第 2 步打印
}
//组件挂载完毕的钩子
componentDidMount(){
console.log("Count --- componentDidMount") //第 4 步打印
}
render(){//render 调用次数 1(初始化)+n (state中的数据变化)
console.log("Count---render") //第 3 步打印
let {count} = this.state;
return {
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
}
}
}
//2、渲染虚拟DOM到页面
ReactDOM.render(<Count/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
<script type="text/babel">
//1、创建组件
class Count extends React.Component{
//构造器 ---- 初始化
constructor(props){
console.log("Count --- constructor); //第 1 步打印
super(props);
//初始化状态
this.state={ count:0 };
}
add=()=>{
let {count} = this.state;//获取原状态
this.setState({count:count+1})
}
//卸载组件按钮的回调
death=()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"));
}
//组件将要卸载
componentWillUnmount(){
console.log("Count --- componentWillUnmount") //按钮点击卸载打印
}
//组件将要挂载的 钩子
componentWillMount(){
console.log("Count --- componentWillMount") //第 2 步打印
}
//组件挂载完毕的钩子
componentDidMount(){
console.log("Count --- componentDidMount") //第 4 步打印
}
//控制组件更新的"阀门",返回为 true 则继续往下,返回 false 则不更新页面。后续流程暂停
//调用了 setState 方法后就会到这个钩子,是否更新组件。不写钩子函数,底层会自动添加一个,并且具有一个默认返回值:true。
//写了这个钩子函数,就必须要写返回值,否则默认为 undefined,会报警告或者报错。
shouldComponentUpdate(){
console.log("Count --- shouldComponentUpdate");
return true;
}
//组件将要更新的钩子
componentWillUpdate(){
console.log("Count --- componentWillUpdate");
}
//组件更新完毕的钩子
componentDidUpdate(){
console.log("Count --- componentDidUpdate");
}
render(){//render 调用次数 1(初始化)+n (state中的数据变化)
console.log("Count---render") //第 3 步打印
let {count} = this.state;
return {
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
}
}
}
//2、渲染虚拟DOM到页面
ReactDOM.render(<Count/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
<script type="text/babel">
//1、创建组件
class Count extends React.Component{
//构造器 ---- 初始化
constructor(props){
console.log("Count --- constructor); //第 1 步打印
super(props);
//初始化状态
this.state={ count:0 };
}
add=()=>{
let {count} = this.state;//获取原状态
this.setState({count:count+1})
}
//卸载组件按钮的回调
death=()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"));
}
//强制更新按钮的回调
force= () => {
this.forceUpdate();
}
//组件将要卸载
componentWillUnmount(){
console.log("Count --- componentWillUnmount") //按钮点击卸载打印
}
//组件将要挂载的 钩子
componentWillMount(){
console.log("Count --- componentWillMount") //第 2 步打印
}
//组件挂载完毕的钩子
componentDidMount(){
console.log("Count --- componentDidMount") //第 4 步打印
}
//控制组件更新的"阀门",返回为 true 则继续往下,返回 false 则不更新页面。后续流程暂停
//调用了 setState 方法后就会到这个钩子,是否更新组件。不写钩子函数,底层会自动添加一个,并且具有一个默认返回值:true。
//写了这个钩子函数,就必须要写返回值,否则默认为 undefined,会报警告或者报错。
shouldComponentUpdate(){
console.log("Count --- shouldComponentUpdate");
return true;
}
//组件将要更新的钩子
componentWillUpdate(){
console.log("Count --- componentWillUpdate");
}
//组件更新完毕的钩子
componentDidUpdate(){
console.log("Count --- componentDidUpdate");
}
render(){//render 调用次数 1(初始化)+n (state中的数据变化)
console.log("Count---render") //第 3 步打印
let {count} = this.state;
return {
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
}
}
}
//2、渲染虚拟DOM到页面
ReactDOM.render(<Count/>, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
<script type="text/babel">
//1、创建组件
class Count extends React.Component{
//构造器 ---- 初始化
constructor(props){
console.log("Count --- constructor); //第 1 步打印
super(props);
//初始化状态
this.state={ count:0 };
}
add=()=>{
let {count} = this.state;//获取原状态
this.setState({count:count+1})
}
//卸载组件按钮的回调
death=()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"));
}
//强制更新按钮的回调
force= () => {
this.forceUpdate();
}
//组件将要卸载
componentWillUnmount(){
console.log("Count --- componentWillUnmount") //按钮点击卸载打印
}
//组件将要挂载的 钩子
componentWillMount(){
console.log("Count --- componentWillMount") //第 2 步打印
}
//组件挂载完毕的钩子
componentDidMount(){
console.log("Count --- componentDidMount") //第 4 步打印
}
//控制组件更新的"阀门",返回为 true 则继续往下,返回 false 则不更新页面。后续流程暂停
//调用了 setState 方法后就会到这个钩子,是否更新组件。不写钩子函数,底层会自动添加一个,并且具有一个默认返回值:true。
//写了这个钩子函数,就必须要写返回值,否则默认为 undefined,会报警告或者报错。
shouldComponentUpdate(){
console.log("Count --- shouldComponentUpdate");
return true;
}
//组件将要更新的钩子
componentWillUpdate(){
console.log("Count --- componentWillUpdate");
}
//组件更新完毕的钩子
componentDidUpdate(){
console.log("Count --- componentDidUpdate");
}
render(){//render 调用次数 1(初始化)+n (state中的数据变化)
console.log("Count---render") //第 3 步打印
let {count} = this.state;
return {
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
}
}
}
class ADom extends React.Component{
//初始化状态
state={carName:"奔驰"}
changeCar = () => {
this.setState({carName:"奥拓"})
}
render(){
return {
<div>
<h2>我是父组件,想要BDom 组件展示信息</h2>
<button onClick={this.changeCar}>换车</button>
<BDom carName={this.state.carName} />
</div>
}
}
}
class BDom extends React.Component{
//组件将要接收新的 props 的钩子函数
//第一次传入的参数不算,第一次以后传的参数才算 props。
componentWillReceiveProps(props){
console.log("BDom --- componentWillReceiveProps", props)
}
//控制组件更新的"阀门"
shouldComponentUpdate(){
console.log("BDom --- shouldComponentUpdate");
return true;
}
//组件将要更新的钩子
componentWillUpdate(){
console.log("BDom --- componentWillUpdate");
}
//组件更新完毕的钩子
componentDidUpdate(){
console.log("BDom --- componentDidUpdate");
}
render(){
console.log("BDom --- render");
return {
<div>
<h2>我是子组件,接收到的车名是:{this.props.carName}</h2>
</div>
}
}
}
//2、渲染虚拟DOM到页面
ReactDOM.render(<ADom />, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>
1)constructor()
2)componentWillMount()
3)render()
4)componentDidMount() ====>常用,一般在这个钩子中做一些初始化的事情,例如:开启定时器、发送网络请求、订阅消息
1)shouldComponentUpdate()
2)componentWillUpdate()
3)render() ====>常用
4)componentDidUpdate()
1)componentWillUnmount() ====>常用,一般在这个钩子中做一些收尾的事情,例如:关闭定时器、取消订阅消息。
<script type="text/babel">
//1、创建组件
class Count extends React.Component{
//构造器 ---- 初始化
constructor(props){
console.log("Count --- constructor); //第 1 步打印
super(props);
//初始化状态
this.state={ count:0 };
}
add=()=>{
let {count} = this.state;//获取原状态
this.setState({count:count+1})
}
//卸载组件按钮的回调
death=()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"));
}
//强制更新按钮的回调
force= () => {
this.forceUpdate();
}
//必须要有返回值。返回 null 或者 状态对象(状态中的东西)
// 利用返回值能够指定状态。影响状态的更新。
// 接收到一个 props ,得到一个 对象,这种就是派生.
//state 的值在任何时候都取决于 props
// 如果 state 的值在任何时候都取决于 props,那么可以使用 getDerivedStateFromProps
static getDerivedStateFromProps(props){
console.log("getDerivedStateFromProps",props);
return null;
//return props;
}
// 在更新之前获取快照
// 传递快照值,快照值可以是任何类型,比如字符串、数字等
getSnapshotBeforeUpdate(){
console.log("getSnapshotBeforeUpdate");
return null;
}
//组件将要卸载
componentWillUnmount(){
console.log("Count --- componentWillUnmount") //按钮点击卸载打印
}
//组件将要挂载的 钩子
componentWillMount(){
console.log("Count --- componentWillMount") //第 2 步打印
}
//组件挂载完毕的钩子
componentDidMount(){
console.log("Count --- componentDidMount") //第 4 步打印
}
//控制组件更新的"阀门",返回为 true 则继续往下,返回 false 则不更新页面。后续流程暂停
//调用了 setState 方法后就会到这个钩子,是否更新组件。不写钩子函数,底层会自动添加一个,并且具有一个默认返回值:true。
//写了这个钩子函数,就必须要写返回值,否则默认为 undefined,会报警告或者报错。
shouldComponentUpdate(){
console.log("Count --- shouldComponentUpdate");
return true;
}
//组件更新完毕的钩子
componentDidUpdate(preProps,preState,snapShotValue){
console.log("Count --- componentDidUpdate",preProps,preState,snapShotValue);
}
render(){//render 调用次数 1(初始化)+n (state中的数据变化)
console.log("Count---render") //第 3 步打印
let {count} = this.state;
return {
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
}
}
}
//2、渲染虚拟DOM到页面
ReactDOM.render(<Count count={200} />, document.getElementById('test'));//第一个参数是 虚拟DOM,第二个参数是 容器。
</script>