实战!增删改查的不平凡

简介: 结合 React 哲学 中的思想,我们可以很自然的想到该按钮中的数据有:// 任务列表const [jobs, setJobs] = useState<Array<Job>>([])// 编辑窗口显示与否const [show, setShow] = useState(false)// 每次输入时当前任务描述const [desc, setDesc] = useState('')单个任务的数据格式为interface Job { desc: string, id: string, createTime: number, isSelected: boolean}

微信图片_20220511163416.png


学习了 useState 与 useRef ,结合前面几章内容,我们可以实现一个非常经典的功能:任务列表。


当我点击新增时,编辑弹窗出现,输入框自动获得焦点


微信图片_20220511163422.png


输入任务描述之后,点击创建,此时任务创建成功,编辑弹窗消失,新增按钮再次出现


微信图片_20220511163426.png


结合 React 哲学 中的思想,我们可以很自然的想到该按钮中的数据有:


// 任务列表
const [jobs, setJobs] = useState<Array<Job>>([])
// 编辑窗口显示与否
const [show, setShow] = useState(false)
// 每次输入时当前任务描述
const [desc, setDesc] = useState('')


单个任务的数据格式为


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


点击「新增按钮」,编辑弹窗出现,新增按钮消失,因此在 JSX 中,我们可以这样去表达他们的交互关系


{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>}


input 框在失去焦点后编辑弹窗消失


我们可以使用 useRef  获得 input 组件的引用,以实现弹窗出现之后 input 能自动获取焦点的效果


const inputRef = useRef<HTMLInputElement>(null)


但是需要注意的是,input 元素是在 show 变成 true ,并且组件真实 DOM 再次渲染完成之后才能获取引用,因此这里运用了一个之后会学习的知识来解决这个问题


useEffect(() => {
// show 变成 true,并且组件渲染完成之后执行
  if (show) {
    inputRef.current?.focus()
  }
}, [show])


当编辑弹窗出现,我们在弹窗中输入内容,需要将输入内容保存在 desc 字段中。


基于只操作数据的思想,点击新增,其实只是往任务列表数据 jobs 中新增一个值


function add() {
  jobs.push({
    id: randomId(),
    desc,
    isSelected: false,
    createTime: Date.now()
  })
  setJobs([...jobs])
  setDesc('')
}


这里需要注意为了让 React 感知到你的数组发生了变化,需要重新创建一个新的引用数组。否则 React 无法识别。


jobs 表示任务列表,可以根据该数据遍历出整个列表


{jobs.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={() => remove(i)}>删除</div>
  </div>
))}


删除与编辑都只需要修改对应的数组数据即可


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


就这样,我们轻松实现了一个列表的增删改查,完整代码如下


import { useEffect, useRef, useState } from 'react';
import { randomId } from './utils/index'
import logo from './logo.svg';
import './App.css';
interface Job {
  desc: string,
  id: string,
  createTime: number,
  isSelected: boolean
}
function App() {
  const [jobs, setJobs] = useState<Array<Job>>([])
  const [show, setShow] = useState(false)
  const [desc, setDesc] = useState('')
  const inputRef = useRef<HTMLInputElement>(null)
  useEffect(() => {
    if (show) {
      inputRef.current?.focus()
    }
  }, [show])
  function add() {
    jobs.push({
      id: randomId(),
      desc,
      isSelected: false,
      createTime: Date.now()
    })
    setJobs([...jobs])
    setDesc('')
  }
  function remove(i: number) {
    jobs.splice(i, 1)
    setJobs([...jobs])
  }
  function troggleSelected(i: number) {
    jobs[i].isSelected = !jobs[i].isSelected
    setJobs([...jobs])
  }
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>React 知命境</h1>
      </header>
      <div className="container">
        <div className="task-header">
          <div className="title">进行中的任务</div>
          <div className="right">...</div>
        </div>
        {jobs.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={() => remove(i)}>删除</div>
          </div>
        ))}
        {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>}
      </div>
    </div>
  );
}
export default App;


微信图片_20220511163430.png

很显然,代码功能虽然实现了,但是代码上并不简洁,学习了 React 哲学的同学可以思考一下,我们应该从哪些角度去思考如何进一步简化代码呢?

相关文章
|
1月前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
98 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
20天前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
37 4
|
2月前
|
SQL NoSQL 数据库
Cassandra数据库与Cql实战笔记
Cassandra数据库与Cql实战笔记
20 1
Cassandra数据库与Cql实战笔记
|
28天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
158 1
|
2月前
|
前端开发 Java 数据库连接
javamvc配置,增删改查,文件上传下载。
【10月更文挑战第4天】javamvc配置,增删改查,文件上传下载。
39 1
|
2月前
|
存储 NoSQL API
使用Py2neo进行Neo4j图数据库的增删改查操作
使用Py2neo进行Neo4j图数据库的增删改查操作
79 5
|
2月前
|
数据可视化 API PHP
低代码开发工具-学生管理系统-老师管理增删改查实现
低代码开发工具-学生管理系统-老师管理增删改查实现
34 5
|
29天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
67 0
|
2月前
|
JavaScript 前端开发 测试技术
[新手入门]todolist增删改查:vue3+ts版本!
【10月更文挑战第15天】[新手入门]todolist增删改查:vue3+ts版本!
|
2月前
|
Java API 数据库
Data jpa 增删改查的方法分别有哪些
Data jpa 增删改查的方法分别有哪些