React组件化02

此文项目代码:https://github.com/bei-yang/I-want-to-be-an-architect
码字不易,辛苦点个star,感谢!

引言


此篇文章主要涉及以下内容:

  1. 函数化组件Hook
  2. 上下文的使用
  3. 设计并实现一个表单组件

学习资源


  • Hook
  • Context

Hook


HookReact 16.8一个新增项,它可以让你在不编写class的情况下使用state以及其他的React特性。
Hook的特点:

  • 使你在无需修改组件结构的情况下复用状态逻辑
  • 可将组件中相互关联的部分拆分成更小的函数,复杂组件将变得更容易理解
  • 更简洁、更易理解的代码

准备工作

  • 升级react、react-dom
npm i react react-dom -S

状态钩子-State Hook

  • 创建HookTest.js
import React, { useState } from 'react'
export default function HooksTest() {
  // useState(initialState),接收初始状态,返回一个状态变量和其更新函数
  const [count, setCount] = useState(0)
  // 多个状态
  const age = useAge();
  const [fruit, setFruit] = useState("banana");
  const [input, setInput] = useState("");
  const [fruits, setFruits] = useState(["apple", "banana"]);
  return (
    

点击了{count}次

年龄:{age ? age : 'loading...'}

选择的水果:{fruit}

setInput(e.target.value)} />

    {fruits.map(f => (
  • setFruit(f)}> {f}
  • ))}
) }

副作用钩子-Effect Hook

userEffect就是一个Effect Hook,给函数组件增加了操作副作用的能力。它跟class组件中的componentDidMount、componentDidUpdatecomponentWillUnmount具有相同的用途,只不过被合并成了一个api

  • 更新HooksTest.js
import React, { useState, useEffect } from 'react'
// 副作用钩子会在每次渲染时都执行
// 如果仅打算执行一次,传递第二个参数为[]
//   componentDidMount
useEffect(() => {
  // api调用
  console.log("api调用");
}, []);
useEffect(() => {
  // Update the documnet title using the browser api
  document.title = `点击了${count}次`
})

自定义钩子-Custom Hook

自定义Hook是一个函数,其名称以use开头,函数内部可以调用其他的Hook

function useAge() {
  const [age, setAge] = useState(0)
  useEffect(() => {
    setTimeout(() => {
      setAge(20)
    }, 2000)
  })
  return age
}

// 使用
const age = useAge()

年龄{age ? age : 'loading...'}

其他Hook

useContextuseReduceruseCallbackuseMemo

组件跨层级通信-Context


上下文提供一种不需要每层设置props就能跨多级组件传递数据的方式

Context相关API

  • React.createContext
  • Context.Provider
  • Class.contextType
  • Context.Consumer

基本用法

创建文件contextText.js

  • 创建上下文
const MyContext = React.createContext();
  • 提供上下文
const { Provider } = MyContext
export default function App() {
  return (
    
) }
  • 消费上下文
function Child3(props) {
  return 
{props.foo}
} export default function App() { return (
{value => }
) }

组件设计与实现


表单组件实现

import React from 'react'
import { Input, Button } from 'antd'
import { log } from 'util'

/* 
  创建一个高阶组件:
    1、扩展现有表单
    2、事件处理
    3、数据收集
    4、校验1
*/
function kFromCreate(Comp) {
  return class extends React.Component {
    constructor(props) {
      super(props)
      this.options = {}
      this.state = {}
    }
    handleChange = e => {
      const { name, value } = e.target
      console.log(name, value)
      this.setState({ [name]: value }, () => {
        // 确保值发生变化再校验
        this.validateField(name)
      })
    }
    validateField = field => {
      // 1.获取校验规则
      const rules = this.options[field].rules
      // 任意一项失败则返回false
      const ret = !rules.some(rule => {
        if (rule.required) {
          if (!this.state[field]) {
            // 校验失败
            this.setState({
              [field + 'Message']: rule.message
            })
            return true
          }
        }
      })
      if (ret) {
        this.setState({
          [field + 'Message']: ''
        })
      }
      return ret
    }
    // 校验所有字段
    validate = cb => {
      const rets = Object.keys(this.options).map(field =>
        this.validateField(field)
      )
      const ret = rets.every(v => v === true)
      cb(ret, this.state)
    }
    // 创建input包装器
    getFieldDec = (field, option) => {
      // 保存当前输入项配置
      this.options[field] = option
      return InputComp => (
        
{React.cloneElement(InputComp, { name: field, value: this.state[field] || '', onChange: this.handleChange })} {/* 校验错误信息 */} {this.state[field + 'Message'] && (

{this.state[field + 'Message']}

)}
) } render() { return ( ) } } } @kFromCreate class KForm extends React.Component { onSubmit = () => { console.log('submit') // 校验所有项 this.props.validate((isValid, data) => { if (isValid) { //提交登录 console.log('denglu:', data) // 后续登录逻辑 } else { alert('校验失败') } }) } render() { const { getFieldDec } = this.props return (
{getFieldDec('uname', { rules: [{ required: true, message: '用户名必填' }] })()} {getFieldDec('pwd', { rules: [{ required: true, message: '密码必填' }] })()}
) } } export default KForm

你的赞是我前进的动力

求赞,求评论,求分享...

你可能感兴趣的:(React组件化02)