13

React todo 待办事项

 3 years ago
source link: https://yazhen.me/_posts/2021/React%E6%8B%96%E6%8B%BD-todo-Demo/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

React todo 待办事项

By王亚振

发布于: 2021年05月23日 



React hooks 方式实现,上个例子中的待办事项功能。

最后渲染 TaskApp 组件就可以了。

效果预览:

您的浏览器不支持播放该视频!

const STATUS_TODO = 'STATUS_TODO';
const STATUS_DOING = 'STATUS_DOING';
const STATUS_DONE = 'STATUS_DONE';

const STATUS_CODE = {
  STATUS_TODO: '待处理',
  STATUS_DOING: '进行中',
  STATUS_DONE: '已完成'
}

let _tasks = [{
  id: 0,
  status: STATUS_TODO,
  title: '每周七天阅读五次,每次阅读完要做100字的读书笔记',
  username: '小夏',
  point: 10
}, {
  id: 1,
  status: STATUS_TODO,
  title: '每周七天健身4次,每次健身时间需要大于20分钟',
  username: '橘子🍊',
  point: 5
}, {
  id: 2,
  status: STATUS_TODO,
  title: '单词*100',
  username: '┑( ̄Д  ̄)┍',
  point: 2
}, {
  id: 3,
  status: STATUS_TODO,
  title: '单词*150',
  username: '┑( ̄Д  ̄)┍',
  point: 2
}, {
  id: 4,
  status: STATUS_TODO,
  title: '单词*200',
  username: '┑( ̄Д  ̄)┍',
  point: 2
}, {
  id: 5,
  status: STATUS_TODO,
  title: '单词*250',
  username: '┑( ̄Д  ̄)┍',
  point: 2
}]

const TaskItem = ({ id, title, point, username, active, onDragEnd, onDragStart }) => {
  return (
    <div
      onDragStart={() => onDragStart(id)}
      onDragEnd={onDragEnd}
      id={`item-${id}`}
      className={'item' + (active ? ' active' : '')}
      draggable="true"
    >
      <header className="item-header">
        <span className="item-header-username">{username}</span>
        <span className="item-header-point">{point}</span>
      </header>
      <main className="item-main">{title}</main>
    </div>
  )
}

const TaskCol = ({ status, canDragIn, dragTo, children }) => {
  const [canIn, setIn] = React.useState(false)

  const handleDrop = (e) => {
    e.preventDefault();
    dragTo(status);
    setIn(false)
  }

  const handleEnter = (e) => {
    e.preventDefault();
    if (canDragIn) {
      setIn(true)
    }
  }

  return (
    <div
      className="col"
      onDragEnter={handleEnter}
      onDragLeave={() => canDragIn && setIn(false)}
      onDragOver={handleEnter}
      onDrop={handleDrop}
      draggable="true"
    >
      <header className="col-header">
        {STATUS_CODE[status]}
      </header>
      <main className={'col-main' + (canIn ? ' active' : '')}>
        {children}
      </main>
    </div>
  )
}

const TaskApp = () => {
  const [tasks, setTasks] = useState(_tasks);
  const [activeId, setActiveId] = useState(null);


  const dragTo = (status) => {
    let task = tasks[activeId];
    if (task.status !== status) {
      task.status = status;
      setTasks(tasks)
    }
    cancelSelect();
  }
  const cancelSelect = () => setActiveId(null);
  const onDragStart = (id) => setActiveId(id);

  return (
    <div
      className="task-wrapper"
    >
      {
        Object.keys(STATUS_CODE).map(status =>(
          <TaskCol
            status={status}
            key={status}
            dragTo={dragTo}
            canDragIn={activeId != null && tasks[activeId].status !== status}
          >
            {
              tasks.filter(t => t.status === status).map(t =>
                <TaskItem
                  key={t.id}
                  active={t.id === activeId}
                  id={t.id}
                  title={t.title}
                  point={t.point}
                  username={t.username}
                  onDragStart={onDragStart}
                  onDragEnd={cancelSelect}
                />)
            }
          </TaskCol>
        ))
      }
    </div>
  )
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK