react redux组件传值(React 面向组件编程(下))
前言:
在React面向组件编程中 ,除了上一章节的组件实例的三大核心属性以外 ,还有很多重要的内容比如:React 的生命周期,受控组件与非受控组件 ,高阶函数和函数柯里化的理解等 ,在本文中会给大家继续讲解React 面向组件编程中剩余的内容 。
一 、受控组件与非受控组件
表单的组件分类:
受控组件 非受控组件多数情况下 ,推荐使用受控组件实现表单 。在受控组件中 ,表单数据由组件控制 。
另外一种是非受控组件 ,这种方式下表单组件由DOM自身控制 。1. 受控组件
受控组件通过 props 获取其当前值 ,并通过回调函数(比如 onChange )通知变化 表单状态发生变化时 ,都会通知 React ,将状态交给 React 进行处理 ,比如可以使用 useState 存储 受控组件中,组件渲染出的状态与它的 value 或 checked 属性相对应 受控组件会更新 state 的流程 class Login extends React.Component { // 初始化状态 state = { username:, // 用户名 password:, // 密码 } // 保存用户名到状态中 saveUsername=(event)=>{ this.setState({username:event.target.value}) } // 保存密码到状态中 savePassword=(event)=>{ this.setState({password:event.target.value}) } // 表单提交的回调 handleSubmit=(event)=>{ event.preventDefault(); // 阻止默认事件 let {username,password} = this.state alert(`你输入的用户名是${username},密码是${password}`) } render(){ return( <div> <form action="https://www.baidu.com/" onSubmit={this.handleSubmit}> 用户名:<input type="text" onChange={this.saveUsername} name="username" /> 密码:<input type="text" onChange={this.savePassword} name="password" /> <button type="submit">登录</button> </form> </div> ) } }2. 非受控组件
非受控组件将数据存储在 DOM 中 ,而不是组件内 ,这比较类似于传统的 HTML 表单元素 。
非受控组件的值不受组件自身的 state 和 props 控制 非受控组件使用 ref 从 DOM 中获取元素数据 class Login extends React.Component { handleSubmit=(event)=>{ // console.log(e>=event) event.preventDefault(); // 阻止默认事件 let {username,password} = this alert(`你输入的用户名是${username.value},密码是${password.value}`) } render(){ return( <div> <form action="https://www.baidu.com/" onSubmit={this.handleSubmit}> 用户名:<input type="text" ref={c=>this.username = c} name="username" /> 密码:<input type="text" ref={c=>this.password = c} name="password" /> <button type="submit">登录</button> </form> </div> ) } }3. 效果展示
4. 总结:
React 中的组件分为受控组件和非受控组件 受控组件的两个要点: 组件的 value 属性与 React 中的状态绑定 组件内声明了 onChange 事件处理 value 的变化 非受控组件更像是传统的 HTML 表单元素,数据存储在 DOM 中 ,而不是组件内部 ,获取数据的方式是通过 ref 引用 一些建议: 尽可能使用受控组件 受控组件是将状态交由 React 处理,可以是任何元素 ,不局限于表单元素 对于有大量表单元素的页面 ,使用受控组件会使程序变得繁琐难控 ,此时使用非受控组件更为明智 在受控组件中 ,数据流是单向的( state 是变化来源) ,因此在改变 state 时都应该使用 setState ,而不要强制赋值 Refs 不能用于函数式组件 ,因为函数式组件没有实例 在函数式组件内部 ,是可以使用 Refs 的二 、组件的生命周期
所谓的React生命周期 ,就是指组件从被创建出来,到被使用 ,最后被销毁的这么一个过程;
而在这个过程中 ,React提供了我们会自动执行的不同的钩子函数,我们称之为生命周期函数;组件的生命周期大致分为三个阶段:组件挂载阶段 ,组件更新阶段 ,组件销毁卸载阶段
react在版本16.3前后存在两套生命周期,16.3之前为旧版 ,之后则是新版 ,虽有新旧之分 ,但主体上大同小异 。
1. 对生命周期的理解
组件从创建到死亡它会经历一些特定的阶段 。 React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用 。 我们在定义组件时 ,会在特定的生命周期回调函数中 ,做特定的工作 。2. 生命周期的三个阶段(旧)
初始化阶段: 由ReactDOM.render()触发—初次渲染 constructor() componentWillMount() render() componentDidMount() 更新阶段: 由组件内部this.setSate()或父组件重新render触发 shouldComponentUpdate() componentWillUpdate() render() componentDidUpdate() 卸载组件: 由ReactDOM.unmountComponentAtNode()触发 componentWillUnmount() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>生命周期旧</title> </head> <body> <!-- 准备好一个容器 --> <div id="test"></div> <!-- 引入 React 核心库 --> <script src="../js/react.development.js"></script> <!-- 引入 react-dom 用于支持 react 操作 DOM --> <script src="../js/react-dom.development.js"></script> <!-- 引入babel: 1. ES6 ==> ES5 2. jsx ==> js --> <script src="../js/babel.min.js"></script> <script type="text/babel"> class Count extends React.Component { state = { count:0 } add = ()=>{ // 获取原状态 let {count} = this.state // 更新状态 this.setState({count:count+1}) } death = ()=>{ ReactDOM.unmountComponentAtNode(document.getElementById(test)) } force = ()=>{ this.forceUpdate() // 强制更新 } // 数据更新的 ‘阀门~’ shouldComponentUpdate() { console.log("Count --- shouldComponentUpdate"); return true // 这里必须有返回4值 ,其次返回值默认是true } // 组件将要更新的钩子 componentWillUpdate() { console.log("Count ---- componentWillUpdate"); } // 组件更新完成的钩子 componentDidUpdate() { console.log("Count ---- componentDidUpdate"); } render(){ console.log("render"); let {count} = this.state return( <div> <h2>当前求和为:{count}</h2> <button onClick={this.add}>点我+1</button> <button onClick={this.death}>卸载组件</button> <button onClick={this.force}>不更改任何状态中的数据 ,强制更新</button> </div> ) } } // 父组件 class A extends React.Component { state = {carName:小三轮} changeCar = ()=>{ this.setState({carName:"宾利"}) } render(){ console.log(A ---- render); return( <div> <div>我是A组件</div> <button onClick={this.changeCar}>换车</button> <B carName={this.state.carName}></B> </div> ) } } // 子组件 class B extends A { // 组件将要接收新的props的钩子 componentWillReceiveProps(){ console.log(B ---- componentWillReceiveProps); } // 数据更新的 ‘阀门~’ shouldComponentUpdate() { console.log("B --- shouldComponentUpdate"); return true // 这里必须有返回4值 ,其次返回值默认是true } // 组件将要更新的钩子 componentWillUpdate() { console.log("B ---- componentWillUpdate"); } // 组件更新完成的钩子 componentDidUpdate() { console.log("B ---- componentDidUpdate"); } render(){ console.log(B ---- render); return( <div> 我是B组件 ,接收到的车是:{this.props.carName} </div> ) } } ReactDOM.render(<A />,document.getElementById(test)) </script> </body> </html>3. 生命周期的三个阶段(新)
初始化阶段: 由ReactDOM.render()触发—初次渲染 constructor() getDerivedStateFromProps render() componentDidMount() 更新阶段: 由组件内部this.setSate()或父组件重新render触发 getDerivedStateFromProps shouldComponentUpdate() render() getSnapshotBeforeUpdate componentDidUpdate() 卸载组件: 由ReactDOM.unmountComponentAtNode()触发 componentWillUnmount() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>生命周期新</title> </head> <body> <!-- 准备好一个容器 --> <div id="test"></div> <!-- 引入 React 核心库 --> <script src="../js/17.0.1/react.development.js"></script> <!-- 引入 react-dom 用于支持 react 操作 DOM --> <script src="../js/17.0.1/react-dom.development.js"></script> <!-- 引入babel:1. ES6 ==> ES52. jsx ==> js --> <script src="../js/17.0.1/babel.min.js"></script> <script type="text/babel"> class Count extends React.Component { state = { count:0 } add = ()=>{ // 获取原状态 let {count} = this.state // 更新状态 this.setState({count:count+1}) } death = ()=>{ ReactDOM.unmountComponentAtNode(document.getElementById(test)) } force = ()=>{ this.forceUpdate() // 强制更新 } // 数据更新的 ‘阀门~’ shouldComponentUpdate() { console.log("Count --- shouldComponentUpdate"); return true // 这里必须有返回4值,其次返回值默认是true } // 组件将要更新的钩子 componentWillUpdate() { console.log("Count ---- componentWillUpdate"); } // 组件更新完成的钩子 componentDidUpdate() { console.log("Count ---- componentDidUpdate"); } render(){ console.log("render"); let {count} = this.state return( <div> <h2>当前求和为:{count}</h2> <button onClick={this.add}>点我+1</button> <button onClick={this.death}>卸载组件</button> <button onClick={this.force}>不更改任何状态中的数据 ,强制更新</button> </div> ) } } // 父组件 class A extends React.Component { state = {carName:小三轮} constructor(props) { state } changeCar = ()=>{ this.setState({carName:"宾利"}) } static getDerivedStateFromProps(props, state) { // 这里必须要一个返回值 ==> state or null // 这里的state会覆盖掉原本的状态 ,并且后续也无法修改 // 能将外部的接收的props 赋值给组件自身的 state // 如果你希望自身的state一直,全部依赖于外部的props ,那么可以使用这个生命周期函数 return {carName:"QQ"} } // 获取护具更新前的快照 ,能拿到旧的props和state // 必须有返回值 getSnapshotBeforeUpdate = (prevProps, prevState) => { } render(){ console.log(A ---- render); return( <div> <div>我是A组件</div> <button onClick={this.changeCar}>换车</button> <B carName={this.state.carName}></B> </div> ) } } // 子组件 class B extends A { // 组件将要接收新的props的钩子 UNSAFE_componentWillReceiveProps(){ console.log(B ---- componentWillReceiveProps); } // 数据更新的 ‘阀门~’ shouldComponentUpdate() { console.log("B --- shouldComponentUpdate"); return true // 这里必须有返回4值,其次返回值默认是true } // 将要挂载时 UNSAFE_componentWillMount() { console.log("Count --- componentWillUnMount"); } // 组件将要更新的钩子 UNSAFE_componentWillUpdate() { console.log("B ---- componentWillUpdate"); } // 组件更新完成的钩子 componentDidUpdate() { console.log("B ---- componentDidUpdate"); } render(){ console.log(B ---- render); return( <div> 我是B组件 ,接收到的车是:{this.props.carName} </div> ) } } ReactDOM.render(<A />,document.getElementById(test)) </script> </body> </html>4. 新旧生命周期的区别
新生命周期中去掉了三个 will 钩子 ,分别为 componentWillMount、componentWillReceiveProps 、componentWillUpdate; 新生命周期中新增了两个钩子 ,分别为 getDerivedStateFromProps(从 props 中得到衍生的 state )和 getSnapshotBeforeUpdate。5. 重要的勾子
render:初始化渲染或更新渲染调用 componentDidMount:开启监听, 发送ajax请求 componentWillUnmount:做一些收尾工作, 如: 清理定时器6. 即将废弃的勾子
componentWillMount componentWillReceiveProps componentWillUpdate警告:
现在使用会出现警告 ,下一个大版本需要加上 UNSAFE_ 前缀才能使用 ,以后可能会被彻底废弃 ,不建议使用 。
三 、高阶函数和函数柯里化的理解
1. 高阶函数
如果一个函数符合下面2个规范中的任何一个 ,那么它就属于一个高阶函数
若A函数 ,接收的参数是一个函数 ,那么A就可以称为高阶函数 若A函数,它的返回值依然是一个函数 ,那么A就可以称为高阶函数常见的高阶函数:Promise ,setTimeout,arr.map(数组方法)
2. 函数的柯里化
通过函数继续调用 ,返回值为函数的方式 ,实现多次接受参数,最后统一处理的函数编码形式
function sum(a){ return (b)=>{ return (c)=>{ return a + b + c } } } const result = sum(1)(2)(3) console.log(result);3. 使用函数柯里化代码示例
class Login extends React.Component { // 初始化状态 state = { username:, // 用户名 password:, // 密码 } // 保存表单数据到状态中 saveFormDate=(dataType,event)=>{ // 标识当前标签 this.setState({[dataType]:event.target.value}) } // 表单提交的回调 handleSubmit=(event)=>{ event.preventDefault(); // 阻止默认事件 let {username,password} = this.state alert(`你输入的用户名是${username},密码是${password}`) } render(){ return( <div> <form action="https://www.baidu.com/" onSubmit={this.handleSubmit}> 用户名:<input type="text" onChange={(event)=>this.saveFormDate(username,event)} name="username" /> 密码:<input type="text" onChange={(event)=>this.saveFormDate(password,event)} name="password" /> <button type="submit">登录</button> </form> </div> ) } }4. 不用函数柯里化代码示例
class Login extends React.Component { // 初始化状态 state = { username:, // 用户名 password:, // 密码 } // 保存表单数据到状态中 saveFormDate=(dataType)=>{ // 标识当前标签 return (event)=>{ // 这里的回调谁执行? input标签的 onChange事件 this.setState({[dataType]:event.target.value}) } } // 表单提交的回调 handleSubmit=(event)=>{ event.preventDefault(); // 阻止默认事件 let {username,password} = this.state alert(`你输入的用户名是${username},密码是${password}`) } render(){ return( <div> <form action="https://www.baidu.com/" onSubmit={this.handleSubmit}> 用户名:<input type="text" onChange={this.saveFormDate(username)} name="username" /> 密码:<input type="text" onChange={this.saveFormDate(password)} name="password" /> <button type="submit">登录</button> </form> </div> ) } }总结:
欢迎大家加入我的社区 ,在社区中会不定时发布一些精选内容:https://bbs.csdn.net/forums/db95ba6b828b43ababd4ee5e41e8d251?category=10003
以上就是 React 面向组件编程(下) ,不懂得也可以在评论区里问我或私聊我询问 ,以后会持续发布一些新的功能 ,敬请关注 。
我的其他文章:https://blog.csdn.net/weixin_62897746?type=blog创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!