react 从入门到实践之基础总结二

本文详细介绍了React中的组件化和模块化开发,包括构造函数和Class创建组件、状态(state)的管理和使用、props与state的差异和结合运用,以及ref的使用场景。通过实例展示了如何在React中创建无状态和有状态组件,如何处理组件间的交互,以及如何在多组件应用中删除和添加数据。同时,强调了在开发中遵循受控组件原则的重要性。
摘要由CSDN通过智能技术生成
一、React中的组件/模块、 组件化/模块化
  1. 对于组件,如下所示:
  • 一个应用/版块/页面中用于实现某个局部的功能(包括 html, js, css 等)
  • 把这些局部功能组装到一起就形成了完整的一个大的功能
  • 主要目的在于: 复用代码, 提高项目运行效率
  1. 对于组件化,如果一个应用是用多组件的方式进行综合开发的, 那么这个应用就是一个组件化应用。

  2. 对于模块,多个组件形成模块, 或者是一个提供特定功能的 js 文件, 主要特点在于耦合性低, 可移植性高, 执行效率好。

  3. 对于模块化,如果一个应用都是用模块的形式来构建的,那么这个应用就是模块化应用。

  4. 对于 React 中组件创建方式,有构造函数创建组件和 class 关键字创建组件这两种。

  5. 对于构造函数创建组件,如下所示:

  • 使用构造函数来创建组件时,如果要接收外界传递的数据,需要在构造函数的参数列表中使用 props 来接收;
  • 必须要向外 return 一个合法的 JSX 创建的虚拟 DOM
  • 简单组件、带参数组件和复合组件
  • 代码如下:
 <script type="text/babel">
    function Name (props) {
      return <p>{props.name}</p>
    }

    function Gender (props) {
      return <p>{props.gender}</p>
    }

    function Likes (props) {
      return <p>{props.likes}</p>
    }

    function Hello () {
      return (
        <div>
          <Name name="张三"/>
          <Gender gender="男"/>
          <Likes likes={['react', 'vue']}/>
        </div>
      )
    }

    ReactDOM.render(<Hello/>, document.getElementById('app'))
  </script>
  1. 对于class关键字创建组件,代码如下所示:
 <script type="text/babel">
    class Hello extends React.Component {
      render () {
        return (
          <div>
            <p>{props.name} --- {props.gender} --- {props.likes}</p>
          </div>
        )
      }
    }

    ReactDOM.render(
      <Hello name="张三" gender="男" likes={['react', 'vue']}/>,
      document.getElementById('app')
    )
  </script>
  1. 对于构造函数创建组件和 class 关键字创建组件的区别,如下所示:
  • 构造函数创建的组件叫:无状态组件;
  • class 关键字创建的组件叫:有状态组件;
  • 有状态组件与无状态组件的本质区别在于是否有 state(状态)属性;
二、React中的state(状态)
  1. state,如下所示:
  • React 把组件看成是一个状态机(State Machines), 通过状态(State) 去操作状态机;
  • 在开发中, 通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致;
  • React 中,只需更新组件的 state,然后根据新的 state 重新渲染用户界(不要操作 DOM
  1. 对于 state 的使用方式,代码如下所示:
 <script type="text/babel">
    class Hello extends React.Component {
      constructor (props) {
        super(props)
        this.state = {
          name: '张三',
          gender: "男",
          age: 24
        }
      }

      render () {
        const {name, gender, age} = this.state
        return (
          <div>
            <p>{props.name} --- {props.gender} --- {props.age}</p>
            <button onClick={() => this.updateClick()}>换一个</button>
          </div>
        )
      }

      updateClick () {
        this.setState({
          name: '李四',
          gender: "男",
          age: 26
        })
      }
    }

    ReactDOM.render(
      <Hello/>,
      document.getElementById('app')
    )

  </script>
三、props和state混合使用
  1. 对于需求,如下所示:
  • 分析 propsstate 的使用场景?
  • props 的使用细节?
  • 单组件中, 两者的区别?
  1. 具体实现,代码如下所示:
 <script type="text/babel">
    class Person extends React.Component {
      constructor (props) {
        super(props)
        // 初始化state
        this.state = {
          age: 24,
          friends: []
        }
      }

      // 设置props属性的默认值
      static defaultProps = {
        name: '张三',
        gender: '男'
      }

      // 设置props属性的类型
      static propTypes = {
        name: PropTypes.string.required,
        gender: PropTypes.string.isRequired
      }

      render () {
        const {name, gender} = this.props
        const {age, friends} = this.state
        return (
          <div>
            <p>姓名:{name},性别:{gender}</p>
            <p>年龄:{age}</p>
            <p>我的朋友:</p>
            <ul>
              {
                friends.map((friend, index) => (
                  <li key={index}>{friend}</li>
                ))
              }
            </ul>
            <button onClick={() => this.addYear()}>加一</button>
          </div>
        )
      }

      addYear () {
        // 增加
        let tempArr = this.state.friends
        tempArr.push('朋友'+Math.floor(Math.random()*100))
        // 更新状态
        this.setState({
          age: this.state.age+1,
          friends: tempArr
        })
      }
    }

    ReactDOM.render(
      <Person />,
      document.getElementById('app')
    )
  </script>
  1. 对于这个的总结,如下所示:
  • 在单组件中, props 一般用于接收外部传入的数据; 而 state 则用于记录组件内部数据, 而且是需要经常改变的数据;
  • state 是组件内部的状态(数据),不能够直接修改,必须要通过 setState 来改变值的状态,从而达到更新组件内部数据的作用;
  • props 更多是组件间传递数据的一种方式,props 同样也可以传递 state。由于 React 的数据流是自上而下的,所以是从父组件向子组件进行传递;另外组件内部的 this.props 属性是只读的不可修改;
四、ref的使用
  1. 对于 refRefs 提供了一种方式,用于访问在 render 方法中创建的 DOM 节点或 React 元素。

  2. 对于 ref 的使用场景,如下所示:

  • 处理焦点、文本选择或媒体控制;
  • 触发强制动画;
  • 集成第三方 DOM 库;
  1. 注意,官方提示, 如果可以通过声明式实现,则尽量避免使用 refs。话外音: React 无法控制局面的时候,就需要直接操作 Refs 了。

  2. 具体实现,代码如下所示:

 <script type="text/babel">

    class CustomTextInput extends React.Component {
      constructor (props) {
        super(props)
        // 绑定ref
        this.myInput = React.createRef()
        this.myBtn = React.createRef()
      }

      render () {
        return (
          <div>
            <input ref={this.myInput} type="text" placeholder="请输入内容" />
            <input ref={this.myBtn} type="button" value="获取焦点" onClick={() => this.focusTextInput()}/>
          </div>
        )
      }

      focusTextInput () {
        // 获取焦点
        this.myInput.current.focus()
      }
    }

    ReactDOM.render(
      <CustomTextInput />,
      document.getElementById('app')
    )
  </script>
五、多组件的应用
  1. 多组件应用的删除和添加,具体实现,代码如下所示:
<!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>
  <style>
      #app{margin: 50px auto;width: 600px;}
      fieldset{border: 1px solid purple;margin-bottom: 20px;}
      fieldset input{width: 200px;height: 30px;margin: 10px 0;}
      table{width: 600px;border: 2px solid purple;text-align: center;}
      thead{background-color: purple;color: #fff;}
  </style>
</head>
<body>
  <div id="app"></div>

  <script src="../js/react.development.js"></script>
  <script src="../js/react-dom.development.js"></script>
  <script src="../js/babel.min.js"></script>
  <script src="../js/prop-types.js"></script>
  <script type="text/babel">
    class App extends React.Component {
      constructor (props) {
        super(props)
        this.state = {
          studentArr: [
            {name: '周杰伦', age: 30, gender: '男', phone: '18899989839'},
            {name: '谢霆锋', age: 40, gender: '男', phone: '18299839890'},
            {name: '刘德华', age: 50, gender: '男', phone: '18998938783'}
          ]
        }
        this.delFromArrWithIndex = this.delFromArrWithIndex.bind(this)
      }

      delFromArrWithIndex (index) {
        const { studentArr } = this.state
        studentArr.splice(index, 1)
        this.setState({
          studentArr
        })
      }

      render () {
        return (
          <div>
            <Add />
            <List studentArr={this.state.studentArr} delFromArr={this.delFromArrWithIndex}/>
          </div>
        )
      }
    }
    
    class Add extends React.Component {
      render () {
        return (
          <div>
              <fieldset>
                <legend>信息录入系统(React版)</legend>
                <div>
                    <span>姓名: </span>
                    <input type="text" placeholder="请输入姓名"/>
                </div>
                <div>
                    <span>年龄: </span>
                    <input type="text" placeholder="请输入年龄"/>
                </div>
                <div>
                    <span>性别: </span>
                    <select>
                        <option value="男"></option>
                        <option value="女"></option>
                    </select>
                </div>
                <div>
                    <span>手机: </span>
                    <input type="text" placeholder="请输入手机号码"/>
                </div>
                <button>创建新用户</button>
            </fieldset>
          </div>
        )
      }
    }

    class List extends React.Component {
      static propTypes = {
        studentArr: PropTypes.array.isRequired,
        delFromArr: PropTypes.func.isRequired
      }

      render () {
        const { studentArr, delFromArr } = this.props
        return (
          <div>
            <table>
              <thead>
              <tr>
                  <td>姓名</td>
                  <td>性别</td>
                  <td>年龄</td>
                  <td>手机</td>
                  <td>删除</td>
              </tr>
              </thead>
              <tbody>
              {
                studentArr.map((student, index) => (
                  <tr key={index}>
                    <td>{student.name}</td>
                    <td>{student.gender}</td>
                    <td>{student.age}</td>
                    <td>{student.phone}</td>
                    <td>
                        <button onClick={() => this.delFromArr(index)}>删除</button>
                    </td>
                  </tr>
                ))
              }
              </tbody>
            </table>
          </div>
        )
      }
    }

    ReactDOM.render(
      <App/>, document.getElementById('app')
    )
  </script>
</body>
</html>
  1. 多层组件中, 数据该放在何处?如果只用于一个组件, 则定义在该组件内容; 如果是运用于多个组件, 则定义在它们的父组件中。

  2. 多层组件中, 数据传递问题?父组件通过 props 传递数据给子组件, 子组件不能直接修改父组件的数据, 必须是父组件定义修改数据的函数, 传递给子组件然后由子组件调用。

  3. 受控方式的实现,代码如下所示:

 <script type="text/babel">
    class Login extends React.Component {
      constructor (props) {
        super(props)
        this.state = {
          userName: '',
          userPwd: ''
        }
      }

      render () {
        const { userName, userPwd} = this.state
        return (
          <form action="" onSubmit={() => this.login()}>
            <div>
              <span>用户名:</span>
              <input type="text" value={userName} onChange={(e) => this.userChange(e)}  />
            </div>
            <div>
              <span>密码:</span>
              <input type="password" value={userPwd} onChange={(e) => this.pwdChange(e)} /> 
            </div>
            <input type="submit" value="登录" />
          </form>
        )
      }

      userChange (e) {
        const userName = e.target.value
        this.setState({
          userName
        })
      }

      pwdChange (e) {
        const userPwd = e.target.value
        this.setState({
          userPwd
        })
      }

      login () {
        const { userPwd, userName } = this.state
        alert(`用户名:${userName},密码:${userPwd}`)
        return
      }
    }

    ReactDOM.render(
      <Login />,
      document.getElementById('app')
    )

  </script>
  1. 在开发中尽可能用受控组件, 因为 ref 方式官方不希望过渡使用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值