详解React中如何拆分组件

 更新时间:2023年12月27日 10:49:40   作者:这波能反杀  
这篇文章主要为大家详细介绍了React中拆分组件的相关知识,文中的示例代码讲解详细,对我们掌握React有一定的帮助,需要的小伙伴可以参考一下

学习过 React 哲学的同学应该知道,我们在思考如何拆分组件时,要以简化代码为目的,充分分析当前页面/组件的交互特性、结构特性、数据特性,来判断当前的页面应该如何拆分。

上一篇文章中,我们在不思考拆分的情况下,实现了任务列表的增删改查。但是结果是代码比较复杂,并不简洁。因此结合上面讲到的拆分依据,我们可以将该页面拆分为如下三个步骤

<header />
<List />
<Addition />

如果对于这个拆分结果感觉还比较懵的话,建议结合直播回放回顾一下我们的 React 哲学。

OK,接下来就是分析如何实现。

header 部分因为只是简单的结构与样式,没有额外的功能,比较简单,因此我们不用过多的考虑该部分。

List 组件为一个列表。很显然,它需要一个数组从外部传入作为数据源。除此之外,它的内部还具有删除与修改操作。而数据源又是从外部传入,因此我们需要对外提供两个方法来让外部响应内部的删除与修改操作

所以,List 组件的 props 类型声明如下

import {Job} from './index'

interface ListProps {
  list: Job[],
  onRemove: (i: number) => any,
  onEditor: (i: number, value: Job) => any
}

明确了 List 的 props,它的封装代码就很好写了

import {Job} from './index'
interface ListProps {
  list: Job[],
  onRemove: (i: number) => any,
  onEditor: (i: number, value: Job) => any
}

export default function List(props: ListProps) {
  const {list, onRemove, onEditor} = props

  function troggleSelected(i: number) {
    const job = list[i]
    onEditor(i, { 
      ...job, isSelected: !job.isSelected
    })
  }

  return (
    <div className="container">
      <div className="task-header">
        <div className="title">进行中的任务</div>
        <div className="right">...</div>
      </div>

      {list.map((job, i) => (
        <div className="job-wrapper" key={job.id}>
          <div className="selected" onClick={() => troggleSelected(i)}>
            {job.isSelected && <div className="circle"></div>}
          </div>
          <div className="desc">{job.desc}</div>
          <div className="remove" onClick={() => onRemove(i)}>删除</div>
        </div>
      ))}
    </div>
  )
}

Addition 组件的思考稍微复杂一点。

编辑弹窗的交互行为属于 Addition 的内部行为,因此控制它显示隐藏的数据也可以为内部数据。对外只需要提供一个添加时的钩子函数,把内部数据传到父级去即可。

这样的表述难免有点枯燥,结合代码来理解比较合适。

代码如下:

import { useEffect, useRef, useState } from 'react';
import { randomId } from '../../utils';
import {Job} from './index'

interface AdditionProps {
  onAdd: (job: Job) => any
}

export default function Addition(props: AdditionProps) {
  const [desc, setDesc] = useState('')
  const [show, setShow] = useState(false)
  const inputRef = useRef<HTMLInputElement>(null)
  const {onAdd} = props

  useEffect(() => {
    if (show) {
      inputRef.current?.focus()
    }
  }, [show])

  function add() {
    onAdd({
      id: randomId(),
      desc,
      isSelected: false,
      createTime: Date.now()
    })
  }

  return (
    <>
      {show ? (
        <div className="dialog">
          <input
            onChange={event => setDesc(event.target.value)}
            ref={inputRef}
            placeholder="请输入任务描述"
            onBlur={() => {setTimeout(() => { setShow(false) }, 0)}}
          />
          <div className="create" onClick={add}>创建</div>
        </div>
      ) : <div className="add" onClick={() => setShow(true)}>新增</div>}
    </>
  )
}

这样,我们的主逻辑就变得非常简单,数据上只需要维护一个 jobs 即可。

import { useState } from 'react';
import logo from './logo.svg';
import Addition from './Addition'
import List from './List'
import './index.css';

export interface Job {
  desc: string,
  id: string,
  createTime: number,
  isSelected: boolean
}

function App() {
  const [jobs, setJobs] = useState<Array<Job>>([])

  function remove(i: number) {
    jobs.splice(i, 1)
    setJobs([...jobs])
  }

  function editor(i: number, job: Job) {
    jobs[i] = job
    setJobs([...jobs])
  }

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>React 知命境</h1>
      </header>
      <List list={jobs} onRemove={remove} onEditor={editor} />
      <Addition onAdd={(job) => setJobs([...jobs, job])} />
    </div>
  );
}

export default App;

组件的拆分是一个简化代码的过程,在这个过程中,我们剔除了主逻辑中的所有干扰因素,让主代码变得非常简洁,极大提高了可维护性。

组件拆分是一个需要我们不断积累与思考的软技能。它是决定你代码质量高低的核心部分。

到此这篇关于详解React中如何拆分组件的文章就介绍到这了,更多相关React拆分组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React中FormData的使用实例详解

    React中FormData的使用实例详解

    FormData 是一个非常灵活的工具,适用于处理表单数据,特别是在需要发送文件或复杂表单数据时,本文给大家介绍React中FormData的使用示例详解,感兴趣的朋友一起看看吧
    2025-04-04
  • React Router中Link和NavLink的学习心得总结

    React Router中Link和NavLink的学习心得总结

    这篇文章主要介绍了React Router中Link和NavLink的学习心得总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • React useImperativeHandle处理组件状态和生命周期用法详解

    React useImperativeHandle处理组件状态和生命周期用法详解

    React Hooks 为我们提供了一种全新的方式来处理组件的状态和生命周期,useImperativeHandle是一个相对较少被提及的Hook,但在某些场景下,它是非常有用的,本文将深讨useImperativeHandle的用法,并通过实例来加深理解
    2023-09-09
  • react-native 完整实现登录功能的示例代码

    react-native 完整实现登录功能的示例代码

    本篇文章主要介绍了react-native 完整实现登录功能的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • React onBlur回调中使用document.activeElement返回body完美解决方案

    React onBlur回调中使用document.activeElement返回body完美解决方案

    这篇文章主要介绍了React onBlur回调中使用document.activeElement返回body完美解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • VSCode搭建React Native环境

    VSCode搭建React Native环境

    这篇文章主要介绍了VSCode搭建React Native环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • React Redux使用配置详解

    React Redux使用配置详解

    react-redux是redux官方react绑定库,能够使react组件从redux store中读取数据,并且向store分发actions以此来更新数据,这篇文章主要介绍了react-redux的设置,需要的朋友可以参考下
    2022-08-08
  • react实现一个优雅的图片占位模块组件详解

    react实现一个优雅的图片占位模块组件详解

    这篇文章主要给大家介绍了关于react如何实现一个还算优雅的占位模块图片组件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-10-10
  • 手把手带你用React撸一个日程组件

    手把手带你用React撸一个日程组件

    这篇文章主要给大家介绍了关于利用React撸一个日程组件的相关资料,包括日常组件的实现思路、使用的技术、以及遇到的技术难点,并给提供了详细的实例代码,需要的朋友可以参考下
    2021-07-07
  • React+Electron快速创建并打包成桌面应用的实例代码

    React+Electron快速创建并打包成桌面应用的实例代码

    这篇文章主要介绍了React+Electron快速创建并打包成桌面应用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12

最新评论