43.B站 非受控组件、受控组件、高阶函数、函数柯里化 - yiqunkeke/react-jianshu-shangguigu-zty GitHub Wiki

<!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>hello_react</title>
    <!-- 引入react,为了使用 React对象  -->
    <script src="js/react.development.js"></script>
    <!-- 引入 react-dom, 为了使用 ReactDOM 对象 -->
    <script src="js/react-dom.development.js"></script>
    <!-- 引入 babel, 为了 解析 JSX -->
    <script src="js/babel.min.js"></script>
    <!-- 引入prop-types,为了对 props属性的类型、必要性、默认值进行限制,全局多了一个 PropTypes对象 -->
    <script src="js/prop-types.js"></script>
</head>
<body>
   <div id="test"></div>

   <!-- 1. 非受控组件 -->
   <!-- <script type="text/babel">
        class Login extends React.Component {

            handleSubmit = (event) => {
                event.preventDefault() // event是事件对象。调用事件对象的preventDefault。可以阻止默认事件。因为提交是表单的默认事件。
                const {username, password} = this
                alert(`你输入的用户名是:${username.value},你输入的密码是${password.value}`)

                // 表单提交默认引发页面的跳转。
                // 为了更好的用户体验,我们希望能够页面不刷新发送ajax请求。所以需要阻止表单跳转。
                // 1.删除表单的action属性,并不能解决问题。页面依然进行了刷新,且表单中填写的数据消失了。
                // 2.利用原生的阻止默认事件---可以阻止表单提交
            }

            render() {
                return (
                    // <form action="http://atguigu.com" onSubmit={this.handleSubmit}>
                    <form 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>
                )
            }

            // 非受控组件:表单中输入类DOM的值,比如input,checkbox,radio等,现用现取-----非受控。
        }

        ReactDOM.render(<Login/>, document.getElementById('test'))
    </script> -->

    <!-- 2. 受控组件 -->
   <!-- <script type="text/babel">
    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()
            const {username, password} = this.state 
            alert(`你输入的用户名是:${username},你输入的密码是${password}`)
        }

        render() {
            return (
                <form onSubmit={this.handleSubmit}>
                    用户名:<input onChange={this.saveUsername} type="text" name="username"/>
                    密码:<input onChange={this.savePassword} type="password" name="password"/>
                    <button>登录</button>
                </form>
            )
        }

        // 受控组件:页面中所有输入类的DOM,比如input,radio等,随着你的输入能够把输入的东西维护到状态中去。
        //          等需要用的时候,直接从状态中取出来。-----受控组件。
        // 类似于 vue 中双向绑定。

        // 建议大家写:受控组件。因为受控组件中一个ref都没有用。react明确提出,勿过度使用ref。
    }

    ReactDOM.render(<Login/>, document.getElementById('test'))
    </script> -->

    <!-- 3. 高阶函数 -->
    <!-- <script type="text/babel">
        class Login extends React.Component {
    
            state = {
                username: '',
                password: ''
            }

            // 保存表单数据到状态中
            saveFormData = (dataType) => {
                // saveFormData函数的返回值,不再是undefined,而是另一个函数。这个函数才是onChange真正的回调函数。
                return (event) => { // 这里的event是react在调用onChange回调时,传入的事件对象。
                    this.setState({
                        [dataType]: event.target.value  // 对象中所有的属性名都是字符串。 读变量的方式: [变量]
                    })
                }
            }
            /* 概念: saveFormData就是一个高阶函数。
                高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数
                            1. 若A函数,接收的参数是一个函数,则A函数就可以称为高阶函数
                            2. 若A函数,调用的返回值依然是一个函数,则A函数就是高阶函数 
                saveFormData 的返回值是一个函数,所以它是高阶函数。    
                
                常见的高阶函数有: Promise、 setTimeout(() => {}, 1000)、  arr.map(() => {})

                函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数,最后统一处理的函数编码形式。
            */

            // 表单提交的回调
            handleSubmit = (event) => {
                event.preventDefault()
                const {username, password} = this.state 
                alert(`你输入的用户名是:${username},你输入的密码是${password}`)
            }

    
            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        {/*一再强调:回调函数后面不要写小括号。---否则会直接调用这个回调函数。

                           且 onChange={this.saveFormData('username')} 代码的含义是:
                                将saveFormData函数的返回值给了onChange作为回调。
                                不是将saveFormData交给onChange作为回调。
                                而saveFormData的返回值是 undefined。
                           
                           onChange={this.saveFormData} 含义是:把saveFormData函数交给onChange作为回调。当input框输入值发生改变时,react会自动帮你调用saveFormData。   
                           
                           所以,不加小括号是真的把一个函数交给onChange作为回调,而加小括号是把一个函数的返回值交给onChange作为回调。特别不巧saveFormData的返回值偏偏也undefined。
                           解决办法:让saveFormData的返回值不是undefined,而是一个函数。

                           原则:必须把一个函数交给onChange作为回调。
                        */}
                        用户名:<input onChange={this.saveFormData('username')} type="text" name="username"/>
                        密码:<input onChange={this.saveFormData('password')} type="password" name="password"/>
                        <button>登录</button>
                    </form>
                )
            }
    
        }
    
        ReactDOM.render(<Login/>, document.getElementById('test'))
    </script> -->

    <!-- 4.对象相关的知识 -->
    <!-- <script type="text/javascript">
        let a = "name"
        let obj = {}
        obj[a] = "tom"
        console.log(obj)  // {name: "tome"}
    </script> -->

    <!-- 5.函数的柯里化 -->
    <!-- <script type="text/javascript">

        // 1. 函数没有使用柯里化
        // function sum(a, b, c) {
        //     return a+b+c
        // }
        // const result = sum(1,2,3)
        // console.log(result)

        // 2.函数的柯里化
        function sum(a) {
            return (b) => {
                return (c) => {
                    return a + b +c
                }
            }
        }
        const result = sum(1)(2)(3)
        console.log(result)

    </script> -->

    <!-- 6.不用柯里化的实现:同时接收dataType参数与event事件对象 -->
    <script type="text/babel">
        class Login extends React.Component {
    
            state = {
                username: '',
                password: ''
            }

            saveFormData = (dataType, event) => {
                this.setState({
                    [dataType]: event.target.value 
                })
            }
            
            handleSubmit = (event) => {
                event.preventDefault()
                const {username, password} = this.state 
                alert(`你输入的用户名是:${username},你输入的密码是${password}`)
            }

            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        {/*注意:在onChange的回调函数中,去调用saveFormData函数,并给saveFormData传两个参数。
                           onChange的回调函数是:匿名的箭头函数。在react中,这个匿名的箭头函数可以接收到event事件对象。这个event事件对象是react传递进去的。
                           我们的做法是:在这个匿名的箭头函数中,通过 this.saveFormData()形式调用 saveFormData函数并传递参数。
                           而匿名的箭头函数中的 saveFormData此时就可以接收到 event对象。所以我们可以通过这种形式,传递event对象的同时,给自定义函数传递其他参数。
                         */}
                        用户名:<input onChange={ event => this.saveFormData('username', event)} type="text" name="username"/>
                        密码:<input onChange={ event => this.saveFormData('password', event)} type="password" name="password"/>
                        <button>登录</button>
                    </form>
                )
            }
    
        }
    
        ReactDOM.render(<Login/>, document.getElementById('test'))
    </script>
    
</body>
</html>
⚠️ **GitHub.com Fallback** ⚠️