• React学习(二)----- 面向组件编程


    1、React开发工具安装

    步骤:谷歌浏览器右上角三个点 ----- 更多工具 ----- 扩展程序 ----- 打开右上角的开发者模式 ----- 页面左上角的首页图标 ----- 下方打开Chrome网上应用店 ----- 搜索React,找到 facebook 出版的开发工具添加

    但是浏览器一般无法打开Chrome应用商店,下方提供百度云链接,阅读者下载直接导入即可,导入方式:

    步骤:谷歌浏览器右上角三个点 ----- 更多工具 ----- 扩展程序 ----- 打开右上角的开发者模式 ----- 点击加载已解压的扩展程序 ----- 选择下载好的文件夹导入即可 ----- 点击浏览器右上角的图标 ----- 将 React 插件右方的钉子点亮(编写 React 程序时将自动亮起)

    地址:链接:https://pan.baidu.com/s/1FGfk2LNNusAYewHsZwlO4w   提取码:hmi1

    2、创建组件的两种形式

    • 函数式组件
      <!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="box"></div>
      
        <!-- 引入核心库 -->
        <script src="../js/react.development.js"></script>
        <script src="../js/react-dom.development.js"></script>
        <script src="../js/babel.min.js"></script>
      
        <script type="text/babel">
          // 创建函数式组件
          // 注意:1>调用者:react   2>this指向:undefined,因为script脚本需要babel翻译,翻译后使用了严格模式,而严格
          // 模式不允许自定义函数中的this指向window
          function Demo(){
            console.log(this)//undefined
            return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
          }
          // 将组件渲染到页面上
          ReactDOM.render(<Demo />,document.getElementById("box"))
        </script>
      </body>
      </html>
      View Code

      /*
      执行完ReactDOM.render(<Demo />,document.getElementById("box"))之后发生了什么???
      1、React解析组件标签,找到Demo组件;
      2、发现组件是使用函数定义的,随后调用该函数,将返回的虚拟Dom转换成真实的Dom,随后呈现在页面中;
      */

               注意:函数式组件玩儿不了state和refs,只能玩儿一下props

    <!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>Document</title>
    </head>
    <body>
      <!-- 容器 -->
      <div id="box"></div>
    
      <!-- 引入核心库 -->
      <script src="../js/react.development.js"></script>
      <script src="../js/react-dom.development.js"></script>
      <script src="../js/babel.min.js"></script>
      <!-- 引入prop-types,用于对组件的标签属性进行限制 ,引入全局对象PropTypes-->
      <script src="../js/prop-types.js"></script>
    
      <script type="text/babel">
        // 1、创建组件
        function Demo(props){
          console.log(props)
          const {name,age,sex} = props 
          return (
              <ul>
                <li>姓名:{name}</li>
                <li>性别:{sex}</li>
                <li>年龄:{age + 1}</li>
              </ul>
            )
        }
        Demo.propTypes = {
          name:PropTypes.string.isRequired,
          age:PropTypes.number.isRequired,
          sex:PropTypes.string
        }
        Demo.defaultProps = {
          sex:'人...'
        }
        // 2、将组件渲染到页面上
        const obj = {name:"jerry", age:22}
        ReactDOM.render(<Demo {...obj}/>,document.getElementById("box"))
      </script>
    </body>
    </html>
    View Code
    • 类式组件
      • class基础知识

    1、构造器 constructor() 不是必须写的,要对实例做一些初始化的操作,如添加指定属性时才写,其中的this是指类的实例对象,constructor()  从创建到销毁,只执行一次

    2、如果A类继承了B类时,且A类中写了构造器,那A类的构造器中super函数必须放在第一行调用;

    3、类中定义的方法都是放在了类的原型对象上,供实例去使用;

      • 例子:
        <!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>Document</title>
        </head>
        <body>
          <!-- 容器 -->
          <div id="box"></div>
        
          <!-- 引入核心库 -->
          <script src="../js/react.development.js"></script>
          <script src="../js/react-dom.development.js"></script>
          <script src="../js/babel.min.js"></script>
        
          <script type="text/babel">
            // 1、创建类式组件
            class MyComponent extends React.Component{
              render(){
                return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
              }
            } 
            console.log(new MyComponent())
            // 2、将组件渲染到页面上
            ReactDOM.render(<MyComponent />,document.getElementById("box"))
          </script>
        </body>
        </html>
        View Code

        render:必须要有一个返回值,返回值是jsx语法,其实也是一个虚拟dom;

        1、render 是放在哪里的???----- 类的原型对象上,供实例使用
        2、实例是谁创建的???----- React内部会创建组件实例对象,调用render()得到虚拟DOM, 并解析为真实DOM
        3、render 函数中的this是谁??? ----- MyComponent类(组件)的实例对象
        4、render 函数调用几次???----- 1+n(1是初始化的那次,n是状态更新的次数)
            /*
              执行完ReactDOM.render(<MyComponent />,document.getElementById("box"))之后发生了什么???
              1、React解析组件标签,找到MyComponent组件;
              2、发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法,
                 将返回的虚拟Dom转换成真实的Dom,随后呈现在页面中;
              */
    • 复杂组件(有状态)和简单组件(无状态)的区分??? 
      • 组件三大核心属性一:state
        • 示例
          <script type="text/babel">
              // 1、创建一个类式组件
              class Weather extends React.Component{
                // 定义初始状态
                constructor(props){
                  super(props);
                  // state初始值为null,低版本为一个空对象{}
                  this.state = {
                    isHot : true
                  }
                }
                // 定义虚拟dom
                render(){
                  const {isHot} = this.state
                  return (
                    <h2>今天天气很{isHot ? '炎热' : '寒冷'}</h2>
                  )
                }
              }
          
              // 2、将组件渲染到页面上
              ReactDOM.render(<Weather />,document.getElementById("box"))
            </script>
          View Code
        • 事件绑定修改state
          • 类中定义方法中的this
            class Person {
                  constructor(name){
                    this.name = 'wxh'
                  }
                  speak(){
                    /*
                      speak放在哪里??? 在类Person的原型上,供实例使用
                      当 Person 的实例调用 speak 时,speak 里面的this是指 Person 实例
                     */
                    console.log(this)
                    console.log(`My name is ${this.name}`)
                  }
                }
                const p1 = new Person();
                p1.speak()//Person {name: "wxh"}  My name is wxh
                const x = p1.speak;
                /*
                  this 为什么是undefined,而不是window???----- 因为 class 中定义的方法,内部自动开启了严格模式 'use strict'
                 */
                console.log(x())//报错: Cannot read property 'name' of undefined
          • 示例:
            <script type="text/babel">
                // 1、创建一个类式组件
                class Weather extends React.Component{
                  // 定义初始状态
                  constructor(props){
                    super(props);
                    // state初始值为null,低版本为一个空对象{}
                    this.state = {
                      isHot : true
                    }
                  }
                  // 定义虚拟dom
                  render(){
                    const {isHot} = this.state
                    return (
                      /*
                         事件处理:
                         1、React 事件的命名采用小驼峰式(camelCase),而不是纯小写
                       */
                      <h2 onClick={this.handlerClick}>今天天气很{isHot ? '炎热' : '寒冷'}</h2>
                    )
                  }
                  handlerClick(){
                    /*
                      1、handlerClick放在哪里??? 在类Weather的原型上,供实例使用
                      2、当 Weather 的实例调用 handlerClick 时,handlerClick 的this是指 Weather 实例
                      3、this为什么是undefined???-----由于 handlerClick 是作为 onClick 的回调,所以不是通过实例调用的,
                        是直接调用,且类中方法默认开启了局部的严格模式,所以是 undefined
                     */
                    console.log(this)
                  }
                }
            
                // 2、将组件渲染到页面上
                ReactDOM.render(<Weather />,document.getElementById("box"))
              </script>

            现象:this为undefined,如何解决???

            /*
                 1、强制绑定this: 通过函数对象的bind()返回一个this为实例对象的新函数
                 所以点击事件执行时,先到实例自身的属性上去查找,若查找不到,再去类的原型对象上去查找
             */
              this.handlerClick = this.handlerClick.bind(this);

            二、自定义方法 ----- 赋值语句的形式+箭头函数(是定义在实例对象上)

            handlerClick= ()=>{this.setState({
                  isHot:!this.state.isHot
               })
            }
          • 事件中state修改
            /*
               严重注意:
            1、状态 state 不可直接修改,要借助一个内置的 API:setState("对象(需要修改的值)","回调函数") 来进行更新,且更新是一种合并,不是替换;
            2、回调函数的作用:1>查看数据是否修改成功 2>在当前函数当中获取到最新的DOM结构,相当于nextTick
            3、这个函数是个异步的 同步先执行,在执行异步
            */ this.setState({ isHot:!this.state.isHot })
          • state的简写方式
            class Weather extends React.Component{
                  // 初始化状态,直接定义在实例对象上
                  state = {
                    isHot : true
                  }
                  // 定义虚拟dom
                  render(){
                    const {isHot} = this.state
                    return (
                      <h2 onClick={this.handlerClick}>今天天气很{isHot ? '炎热' : '寒冷'}</h2>
                    )
                  }
                }
      • 组件三大核心属性二:props
        • 示例(
          1. 每个组件对象都会有 props(properties的简写) 属性,默认为一个空对象{}
          2. 组件标签的所有属性都保存在props中
          3. props是只读的,不允许在组件内部修改,即this.props.name = 'xxx'

          <!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>Document</title>
          </head>
          <body>
            <!-- 容器 -->
            <div id="box"></div>
            <div id="box1"></div>
            <!-- 引入核心库 -->
            <script src="../js/react.development.js"></script>
            <script src="../js/react-dom.development.js"></script>
            <script src="../js/babel.min.js"></script>
          
            <script type="text/babel">
              // 1、创建组件
              class Dad extends React.Component{
                render(){
                  console.log(this)
                  const {name,age,sex} = this.props
                  return (
                    <ul>
                      <li>姓名:{name}</li>
                      <li>性别:{sex}</li>
                      <li>年龄:{age}</li>
                    </ul>
                  )
                }
              }
              // 2、将组件渲染到页面上
              ReactDOM.render(<Dad name="wxh" age="18" sex="女"/>,document.getElementById("box"))
              ReactDOM.render(<Dad name="jerry" age="22" sex="男"/>,document.getElementById("box1"))
            </script>
          </body>
          </html>
          View Code
        • 批量传递props
          • 扩展运算符
            <!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>Document</title>
            </head>
            <body>
              <!-- 容器 -->
              <div id="box"></div>
              <div id="box1"></div>
              <!-- 引入核心库 -->
              <script src="../js/react.development.js"></script>
              <script src="../js/react-dom.development.js"></script>
              <script src="../js/babel.min.js"></script>
            
              <script type="text/babel">
                // 1、创建组件
                class Dad extends React.Component{
                  render(){
                    console.log(this)
                    const {name,age,sex} = this.props
                    return (
                      <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age}</li>
                      </ul>
                    )
                  }
                }
                // 2、将组件渲染到页面上
                ReactDOM.render(<Dad name="wxh" age="18" sex="女"/>,document.getElementById("box"))
                const obj = {name:"jerry", age:"22", sex:"男"}
                ReactDOM.render(<Dad {...obj}/>,document.getElementById("box1"))
                // ReactDOM.render(<Dad name="jerry" age="22" sex="男"/>,document.getElementById("box1"))
              </script>
            </body>
            </html>
            View Code

            注意:

            let arr = [1,3,5,7,9]
            console.log(arr,...arr)//展开一个数组

             let arr1 = [1,3,5,7,9]
             let arr2 = [2,4,6,8,10]
             // 连接数组,相当于arr1展开 +一个逗号 + arr2展开
             console.log(...arr1)
             console.log([...arr1])
             console.log([...arr1,...arr2])

            // 在函数中使用:接收不定个数的形参
            function sum(...args){
               console.log(args)//[1,2,3,4]
               console.log(...args)//1 2 3 4
               return args.reduce((pre,cur)=>{
                 return pre + cur
               })
            }
            console.log(sum(1,2,3,4))

            const obj = {name:"jerry", age:"22", sex:"男"}
            console.log(...obj)//报错,展开运算符不能展开一个对象

            const obj = {name:"jerry", age:"22", sex:"男",children:{school:'hhh'}}
            // console.log(...obj)//报错,展开运算符不能展开一个对象
            //新语法:字面量的方式复制一个对象,类似于object.assign(),一维属性为深拷贝,二维及以上为浅拷贝
            let cloneObj = {...obj}
            obj.name='wxh'
            obj.children.school='高一'
            console.log(obj,cloneObj)

            const obj = {name:"jerry", age:"22", sex:"男",children:{school:'hhh'}}
            console.log({...obj,name:'wxh',address:'地球'})//更新或者合并属性

            注意!!!原生JS中{...obj}是一种语法,而React中使用{...obj}和原生JS并不一样,是在差值表达式中使用了...obj,虽然这种写法在原生JS中是不允许的,但是在React+babel的共同处理下,支持这种语法!!!!! 

        • 对props进行限制
          console.log('@@@',...obj);//不允许随便使用,只允许在标签中使用,打印为空
          ReactDOM.render(<Dad {...obj}/>,document.getElementById("box1"))
          • 组件内部读取某个值:
             const {name,age,sex} = this.props
          • 对props中的属性值进行类型限制和必要性限制
            <!-- 引入prop-types,用于对组件的标签属性进行限制 ,引入全局对象PropTypes  v15.5以上-->
            <script src="../js/prop-types.js"></script>
            
            Dad.propTypes = {
              name:PropTypes.string.isRequired
            }
          • 默认属性值
            Dad.defaultProps = {
              sex:'人...'
            }
        • props的简写方式,赋值语句是给实例自身添加属性,而static+赋值语句是给类本身添加属性
          <!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>Document</title>
          </head>
          <body>
            <!-- 容器 -->
            <div id="box"></div>
            <div id="box1"></div>
            <!-- 引入核心库 -->
            <script src="../js/react.development.js"></script>
            <script src="../js/react-dom.development.js"></script>
            <script src="../js/babel.min.js"></script>
            <!-- 引入prop-types,用于对组件的标签属性进行限制 ,引入全局对象PropTypes-->
            <script src="../js/prop-types.js"></script>
          
            <script type="text/babel">
              // 1、创建组件
              class Dad extends React.Component{
                static propTypes = {
                  name:PropTypes.string.isRequired,
                  age:PropTypes.number.isRequired,
                  sex:PropTypes.string
                }
                static defaultProps = {
                  sex:'人...'
                }
                render(){
                  const {name,age,sex} = this.props
                  return (
                    <ul>
                      <li>姓名:{name}</li>
                      <li>性别:{sex}</li>
                      <li>年龄:{age + 1}</li>
                    </ul>
                  )
                }
               
              }
              console.log(PropTypes)
              // 2、将组件渲染到页面上
              const obj = {name:"jerry", age:22, sex:"男"}
              ReactDOM.render(<Dad {...obj}/>,document.getElementById("box"))
              ReactDOM.render(<Dad name="wxh" age={18} />,document.getElementById("box1"))
            </script>
          </body>
          </html>
          View Code
      • 组件三大核心属性三:refs(

        组件内的标签可以定义ref属性来标识自己

        • 字符串形式的ref(不建议使用) ----- 存在一些问题:https://github.com/facebook/react/pull/8333#issuecomment-271648615  官网也没有给出一个明确的解释,只是说会存在一些效率方面的问题,而且它已过时并可能会在未来的版本中被移除
          <!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>Document</title>
          </head>
          <body>
              <!-- 容器 -->
              <div id="box"></div>
          
              <!-- 引入React的核心库 -->
              <script src="../js/react.development.js"></script>
              <!-- 引入React的扩展库,用来渲染虚拟DOM -->
              <script src="../js/react-dom.development.js"></script>
              <!-- 引入babel,用来将jsx转换为浏览器可以识别的文件 -->
              <script src="../js/babel.min.js"></script>
              <!-- 引入propTypes,对标签属性的类型、必要性以及默认值进行控制 -->
              <script src="../js/prop-types.js"></script>
          
              <script type="text/babel">
                  // 1、创建组件
                  class MyComponent extends React.Component{
                      // 对标签属性的类型、必要性进行控制
                      static propTypes = {
          
                      }
                      // 对标签属性的默认值进行控制
                      static defaultProps = {
          
                      }
                      // 初始化数据
                      state = {
          
                      }
                      render(){
                          return(
                              <div>
                                  <input type="text" placeholder="点击按钮提示数据" ref="leftInput"/>&nbsp;
                                  <button id="btn" onClick={this.handlerClick}>点我提示左侧的数据</button>&nbsp;
                                  <input type="text" placeholder="失去焦点提取数据" onBlur={this.handlerBlur} ref="rightInput"/>
                              </div>
                          )
                      }
                      // 展示左侧输入框的数据  字符串形式
                      handlerClick = ()=>{
                          console.log(this.refs.leftInput)
                          let TDOM = this.refs.leftInput;
                          console.log(TDOM.value)
                      }
                      // 失去焦点显示数据  字符串形式
                      handlerBlur = ()=>{
                          const {rightInput} = this.refs;
                          console.log(rightInput.value)
                      }
                  }
                  // 2、将组件渲染到页面上
                  ReactDOM.render(<MyComponent />,document.getElementById("box"))
              </script>
          </body>
          </html>
          View Code
        • 回调形式的ref
          <!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>Document</title>
          </head>
          <body>
              <!-- 容器 -->
              <div id="box"></div>
          
              <!-- 引入React的核心库 -->
              <script src="../js/react.development.js"></script>
              <!-- 引入React的扩展库,用来渲染虚拟DOM -->
              <script src="../js/react-dom.development.js"></script>
              <!-- 引入babel,用来将jsx转换为浏览器可以识别的文件 -->
              <script src="../js/babel.min.js"></script>
              <!-- 引入propTypes,对标签属性的类型、必要性以及默认值进行控制 -->
              <script src="../js/prop-types.js"></script>
          
              <script type="text/babel">
                  // 1、创建组件
                  class MyComponent extends React.Component{
                      // 对标签属性的类型、必要性进行控制
                      static propTypes = {
          
                      }
                      // 对标签属性的默认值进行控制
                      static defaultProps = {
          
                      }
                      // 初始化数据
                      state = {
                        
                      }
                      render(){
                          return(
                              <div>
                              <input type="text" placeholder="点击按钮提示数据" ref={(currentNode)=>{this.leftInput = currentNode; console.log('@',currentNode)}}/>&nbsp; 
                              <br /><br />
                                  <button id="btn" onClick={this.handlerClick}>点我提示左侧的数据</button>&nbsp;
                                  <br /><br />
                                  <input type="text" placeholder="失去焦点提取数据" onBlur={this.handlerBlur} ref={currentNode => this.rightInput = currentNode} />
                              </div>
                          )
                      }
                      // 展示左侧输入框的数据  字符串形式
                      handlerClick = ()=>{
                          const {leftInput} = this
                          console.log(leftInput.value)
                      }
                      // 失去焦点显示数据  字符串形式
                      handlerBlur = ()=>{
                          const {rightInput} = this;
                          console.log(rightInput.value)
                      }
                  }
                  // 2、将组件渲染到页面上
                  ReactDOM.render(<MyComponent />,document.getElementById("box"))
              </script>
          </body>
          </html>
          View Code

          解决方式:

          <!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>Document</title>
          </head>
          <body>
              <!-- 容器 -->
              <div id="box"></div>
          
              <!-- 引入React的核心库 -->
              <script src="../js/react.development.js"></script>
              <!-- 引入React的扩展库,用来渲染虚拟DOM -->
              <script src="../js/react-dom.development.js"></script>
              <!-- 引入babel,用来将jsx转换为浏览器可以识别的文件 -->
              <script src="../js/babel.min.js"></script>
              <!-- 引入propTypes,对标签属性的类型、必要性以及默认值进行控制 -->
              <script src="../js/prop-types.js"></script>
          
              <script type="text/babel">
                  // 1、创建组件
                  class MyComponent extends React.Component{
                      // 对标签属性的类型、必要性进行控制
                      static propTypes = {
          
                      }
                      // 对标签属性的默认值进行控制
                      static defaultProps = {
          
                      }
                      // 初始化数据
                      state = {
                          isHot : true
                      }
                      render(){
                          const {isHot} = this.state
                          return(
                              <div>
                                  <h2 onClick = {this.changeState}>今天天气好{isHot ? '晴朗' : '凉爽'}</h2>
                              {/*<input type="text" placeholder="点击按钮提示数据" ref={(currentNode)=>{this.leftInput = currentNode; console.log('@',currentNode)}}/>&nbsp;*/}
                              <input type="text" placeholder="点击按钮提示数据" ref={this.saveInputRef}/>&nbsp;    
                              <br /><br />
                                  <button id="btn" onClick={this.handlerClick}>点我提示左侧的数据</button>&nbsp;
                                  <br /><br />
                                  <input type="text" placeholder="失去焦点提取数据" onBlur={this.handlerBlur} ref={currentNode => this.rightInput = currentNode} />
                              </div>
                          )
                      }
                      // 解决更新时执行两次的问题
                      saveInputRef = (currentNode)=>{
                          this.leftInput = currentNode; 
                          console.log('@',currentNode)
                      }
                      // 修改标识
                      changeState = () =>{
                          this.setState({
                              isHot : !this.state.isHot
                          })
                      }
                      // 展示左侧输入框的数据  字符串形式
                      handlerClick = ()=>{
                          const {leftInput} = this
                          console.log(leftInput.value)
                      }
                      // 失去焦点显示数据  字符串形式
                      handlerBlur = ()=>{
                          const {rightInput} = this;
                          console.log(rightInput.value)
                      }
                  }
                  // 2、将组件渲染到页面上
                  ReactDOM.render(<MyComponent />,document.getElementById("box"))
              </script>
          </body>
          </html>
          View Code
          注意:回调 ref 中调用次数的问题??? ----- 调用者:React 
          
          如果 ref 回调函数是以内联函数的方式定义的,在更新(render调用)过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,
          所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
        •  createRef创建ref容器(推荐使用)
          <!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>Document</title>
          </head>
          <body>
              <!-- 容器 -->
              <div id="box"></div>
          
              <!-- 引入React的核心库 -->
              <script src="../js/react.development.js"></script>
              <!-- 引入React的扩展库,用来渲染虚拟DOM -->
              <script src="../js/react-dom.development.js"></script>
              <!-- 引入babel,用来将jsx转换为浏览器可以识别的文件 -->
              <script src="../js/babel.min.js"></script>
              <!-- 引入propTypes,对标签属性的类型、必要性以及默认值进行控制 -->
              <script src="../js/prop-types.js"></script>
          
              <script type="text/babel">
                  // 1、创建组件
                  class MyComponent extends React.Component{
                      // 对标签属性的类型、必要性进行控制
                      static propTypes = {
          
                      }
                      // 对标签属性的默认值进行控制
                      static defaultProps = {
          
                      }
                      // 初始化数据
                      state = {
          
                      }
                      /*
                        React.createRef 调用后可以返回一个容器,该容器可以存储被 ref 所标识的节点,该容器是“专人专用”,只能存一个
                       */
                      myRef = React.createRef() 
                      render(){
                          console.log(this)
                          return(
                              <div>
                                  <input type="text" ref={this.myRef} placeholder="失去焦点提取数据" onBlur={this.handlerBlur}/>
                              </div>
                          )
                      }
                      // 失去焦点显示数据  字符串形式
                      handlerBlur = ()=>{
                          const {current} = this.myRef;
                          console.log(current.value)
                      }
                  }
                  // 2、将组件渲染到页面上
                  ReactDOM.render(<MyComponent />,document.getElementById("box"))
              </script>
          </body>
          </html>
          View Code

          注意:

          React.createRef 调用后可以返回一个容器,该容器可以存储被 ref 所标识的节点,该容器是“专人专用”,只能存一个

    3、React中的事件处理

    •  示例
             render(){
                      return(
                          <div>
                              <input type="text" placeholder="失去焦点提取数据" onBlur={this.handlerBlur} ref={currentNode => this.rightInput = currentNode} />
                          </div>
                      )
                  }
                  /*
                    1.通过onXxx属性指定事件处理函数(注意大小写)
                      1)React使用的是自定义(合成)事件, 而不是使用的原生DOM事件    -----    为了更好的兼容性
                      2)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)    -----    为了更高效
                    2.通过event.target得到发生事件的DOM元素对象    -----    不要过度使用ref
                  */
                  // 失去焦点显示数据  字符串形式
                  handlerBlur = (e)=>{
                      console.log(e.target)
                      console.log(e.target.value)
                  }
      View Code
      /*
        1.通过onXxx属性指定事件处理函数(注意大小写)
           1)React使用的是自定义(合成)事件, 而不是使用的原生DOM事件    -----    为了更好的兼容性
           2)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)    -----    为了更高效
        2.通过event.target得到发生事件的DOM元素对象    -----    不要过度使用ref
      */

    4、收集表单数据(包含表单的组件分类)

    • 非受控组件:表单中所有输入类 DOM 的值,现用现取,即点击按钮的时候才收集
      • Ref的形式
        <!--
         * @Descripttion: 
         * @version: 
         * @Author: 北栀女孩儿
         * @Date: 2021-08-30 09:28:15
         * @LastEditTime: 2021-08-30 09:52:22
        -->
        <!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>Document</title>
        </head>
        <body>
          <!-- 容器 -->
            <div id="box"></div>
        
            <!-- 引入React的核心库 -->
            <script src="../js/react.development.js"></script>
            <!-- 引入React的扩展库,用来渲染虚拟DOM -->
            <script src="../js/react-dom.development.js"></script>
            <!-- 引入babel,用来将jsx转换为浏览器可以识别的文件 -->
            <script src="../js/babel.min.js"></script>
            <!-- 引入propTypes,对标签属性的类型、必要性以及默认值进行控制 -->
            <script src="../js/prop-types.js"></script>
        
            <script type="text/babel">
                // 1、创建组件
                class MyComponent extends React.Component{
                    // 对标签属性的类型、必要性进行控制
                    static propTypes = {
        
                    }
                    // 对标签属性的默认值进行控制
                    static defaultProps = {
        
                    }
                    // 初始化数据action="http://www.atguigu.com"
                    state = {
                        
                    }
                    render(){
                        return(
                            <div>
                                <form  method="post" onSubmit={this.handlerSubmit}>
                                  <label htmlFor="userName">用户名:</label> 
                                  <input type="text" id="userName" name="userName" ref={currentNode => this.userName = currentNode}/>
                                  <br />
                                  <br />
                                  <label htmlFor="password">密码:</label> 
                                  <input type="password" id="password" name="password" ref={currentNode => this.password = currentNode}/> 
                                  <br />
                                  <br />
                                  <button>提交</button>
                                </form>
                            </div>
                        )
                    }
                    // 处理提交的按钮
                    handlerSubmit = (e) =>{
                      // 阻止表单提交
                      e.preventDefault()
                      const {userName,password} = this;
                      alert(`你输入的用户名是:${userName.value},密码是${password.value}`)
                    }
                }
                // 2、将组件渲染到页面上
                ReactDOM.render(<MyComponent />,document.getElementById("box"))
            </script>
        </body>
        </html>
        View Code
    • 受控组件(推荐使用):表单中所有输入类 DOM 的值,随着输入将值维护到状态state中,即vue中的数据双向数据绑定
      <!--
       * @Descripttion: 
       * @version: 
       * @Author: 北栀女孩儿
       * @Date: 2021-08-30 09:28:15
       * @LastEditTime: 2021-08-30 10:09:48
      -->
      <!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>Document</title>
      </head>
      <body>
        <!-- 容器 -->
          <div id="box"></div>
      
          <!-- 引入React的核心库 -->
          <script src="../js/react.development.js"></script>
          <!-- 引入React的扩展库,用来渲染虚拟DOM -->
          <script src="../js/react-dom.development.js"></script>
          <!-- 引入babel,用来将jsx转换为浏览器可以识别的文件 -->
          <script src="../js/babel.min.js"></script>
          <!-- 引入propTypes,对标签属性的类型、必要性以及默认值进行控制 -->
          <script src="../js/prop-types.js"></script>
      
          <script type="text/babel">
              // 1、创建组件
              class MyComponent extends React.Component{
                  // 对标签属性的类型、必要性进行控制
                  static propTypes = {
      
                  }
                  // 对标签属性的默认值进行控制
                  static defaultProps = {
      
                  }
                  // 初始化数据
                  state = {
                      userName :'',
                      password : ''
                  }
                  render(){
                      return(
                          <div>
                              <form action="" method="get">
                                <label htmlFor="userName">用户名:</label> 
                                <input type="text" id="userName" name="userName" onChange={this.handlerUserName}/>
                                <br />
                                <br />
                                <label htmlFor="password">密码:</label> 
                                <input type="password" id="password" name="password" onChange={this.handlerPassword}/> 
                                <br />
                                <br />
                                <button onClick={this.handlerSubmit}>提交</button>
                              </form>
                          </div>
                      )
                  }
                  // 监听 input 的输入事件 ,保存输入值到状态中
                  handlerUserName = (e) => {
                    console.log(e.target.value)
                    this.setState({
                      userName : e.target.value
                    })
                  }
                  handlerPassword = (e) =>{
                    console.log(e.target.value)
                    this.setState({
                      password : e.target.value
                    })
                  }
                  // 处理提交的按钮
                  handlerSubmit = (e) =>{
                    e.preventDefault()
                    const {userName,password} = this.state
                    alert(`你输入的用户名是:${userName},密码是${password}`)
                  }
              }
              // 2、将组件渲染到页面上
              ReactDOM.render(<MyComponent />,document.getElementById("box"))
          </script>
      </body>
      </html>
      View Code
    • 扩展:高阶函数和函数的柯里化
      • 传参:错误的方式
        <label htmlFor="userName">用户名:</label> 
        // 这么写的含义是将  this.saveFormData函数的返回值  作为onChange事件的回调函数,即把 undefined 作为回调,input 输入值发生变化时不在执行!!!
        // 而不是将  this.saveFormData函数  作为回调
        <input type="text" id="userName" name="userName" onChange={this.saveFormData('userName')}/>
        
        
        // 监听 input 的输入事件 ,保存输入值到状态中
        saveFormData = (e) => {
          console.log(e.target.value)
        }
      • 正确的方式:高阶函数的方式
        <label htmlFor="userName">用户名:</label> 
        <input type="text" id="userName" name="userName" onChange={this.saveFormData('userName')}/>
        
        
        // 监听 input 的输入事件 ,保存输入值到状态中
        saveFormData = (dataType) => {
           // 返回的函数将是真正的 onChange 事件的回调函数
           return (event) => {
               console.log(dataType,event.target.value)
               this.setState({
                  [dataType] : event.target.value
               })
               // 错误的方式:dataType这个时候是一个字符串,相当于'dataType',属性为dataType,而不是变量
               // this.setState({
               //   dataType : event.target.value
               // })
           }
        }

         高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数

               1)若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数;

               2)若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数;

                常见的高阶函数:Promise、定时器、一些数组方法(map、filter)等

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

    function sum(a){
      return (b) => {
        return (c) => {
          return a+b+c
        }
      }
    }
    console.log(sum(
    1)(2)(3))//6
      • 正确的方式:非高阶函数的方式
        <label htmlFor="userName">用户名:</label> 
        <input type="text" id="userName" name="userName" onChange={(event)=>{this.saveFormData('userName',event.target.value)}}/>
        
         // 监听 input 的输入事件 ,保存输入值到状态中
         saveFormData = (dataType, value) => {
             console.log(dataType, value)
             this.setState({
                 [dataType] : value
             })
         }

    5、遇到的问题

           后续补充                                             

    北栀女孩儿
  • 相关阅读:
    图解SQL的Join(转)
    MySQ数据表设计
    关于数据库DML、DDL、DCL区别
    SQL多表连接查询
    Xcode报错Expected selector for Objective-C and Expected method body
    Mac上安装使用MYSQL以及Navicat数据库管理和PHP服务器配置
    更换app开发者账号
    Mac 下的 C++ 开发环境
    spring-retry 重试机制
    Ribbon的主要组件与工作流程
  • 原文地址:https://www.cnblogs.com/wxh0929/p/15179290.html
Copyright © 2020-2023  润新知