[typescript]原生ts实现todoList

建议搭配视频讲解食用~

https://www.bilibili.com/video/BV1Jt4y1k7dS

传统写法

绑定事件处理函数 – 数据

  1. 增加项 – 列表数据 -> 增加一项{ id timestamp, content string, completed: false }

    每一项的视图 -> 列表

  2. 删除项 – 列表数据 -> id -> removeItem将对应项的视图 -> 列表 -> 删除

  3. 改变完成状态 – 列表数据 -> id -> change completed将对应项的完成状态 -> 是否完成 toggle

面向对象、类的继承、横向切割程序 – 设计方案

程序进行分类 外层:调用浏览器的事件 -> 调用方法 -> 事件处理函数的绑定 操作数据:addTodoremoveTodotoggleComplete操作DOM:addItemremoveItemchangeCompleted管理模板:todoView -> 接收参数,生成视觉模板

1目录结构

初始化npm项目,并初始化ts配置。

npm init
tsc --init

可使用vite启动项目。

npm install vite -D
vite
[typescript]原生ts实现todoList

2index.html文件

主页入口。

<!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>
</head>
<body>
    <div class="app">
        <div class="todo-input">
            <input type="text" placeholder="请输入代办事项">
            <button>增加</button>
        </div>
        <div class="todo-list"></div>
    </div>
    <script type="module" src="./src/app.ts"></script>
</body>
</html>

3js/typings.ts文件

定义一个item的数据结构

export interface ITodoData {
    id: number;
    content: string;
    completed: boolean;
}

4js/utils.ts文件

一些工具方法。

// 找到指定className的父节点
export function findParentNode (target: HTMLElement, className: string): HTMLElement {
    while (target = target.parentNode as HTMLElement) {
        if (target.className === className) {
            return target;
        }
    }
}

// 创建一个todoList的Item
export function createItem (tagName: string, className: string, todoItem: string): HTMLElement {
    const oItem: HTMLElement = document.createElement(tagName);
    oItem.className = className;
    oItem.innerHTML = todoItem;

    return oItem;
}

5js/TodoTemplate.ts文件

传入一个ITodoData对象,生成一个todoItemtemplate

import { ITodoData } from "./typings";

class TodoTemplate {
    // 传入一个ITodoData,生成view的渲染模板
    protected todoView ({ id, content, completed }: ITodoData): string {
        return `
<input type="checkbox" ${ completed ? 'checked' : '' } color: #e06c75;line-height: 26px;">${ id }
" />
<span style="text-decoration: ${ completed ? 'line-through' : 'none' }">${ content }</span>
<button color: #e06c75;line-height: 26px;">${ id }">删除</button>
`;
    }
}

export default TodoTemplate;

6js/TodoDom.ts文件

封装操作

import TodoTemplate from "./TodoTemplate";
import { ITodoData } from "./typings";
import { createItem, findParentNode } from "./utils";

class TodoDom extends TodoTemplate {
  private todoWrapper: HTMLElement;
 
  constructor(todoWrapper: HTMLElement) {
    super();
    this.todoWrapper = todoWrapper;
  }
 
  // 初始化todoList列表
  protected initList (todoData: ITodoData[]) {
    if (todoData.length) {
      const oFrag: DocumentFragment = document.createDocumentFragment();
      todoData.map((todo: ITodoData) => {
        const oItem: HTMLElement = createItem('div''todo-item'this.todoView(todo));
        oFrag.appendChild(oItem);
      });
      this.todoWrapper.appendChild(oFrag);
    }
  }
  
  // 添加一个todo的item
  protected addItem (todo: ITodoData) {
    const oItem: HTMLElement = createItem('div''todo-item'this.todoView(todo));
    this.todoWrapper.appendChild(oItem);
  }
  
  // 删除item
  protected removeItem (target: HTMLElement) {
    const oParentNode: HTMLElement = findParentNode(target, 'todo-item');
    oParentNode.remove();
  }
  
  // 切换是否完成状态
  protected changeCompleted (target: HTMLElement, completed: boolean) {
    const oParentNode: HTMLElement = findParentNode(target, 'todo-item');
    const oContent: HTMLElement = oParentNode.getElementsByTagName('span')[0];

    oContent.style.textDecoration = completed ? 'line-through' : 'none';
  }
}

export default TodoDom;

7js/TodoEvent.ts文件

在操作Dom的类上继承,实现事件的处理

import TodoDom from "./TodoDom";
import { ITodoData } from "./typings";

class TodoEvent extends TodoDom {
  
  private todoData: ITodoData[];

  constructor (todoData: ITodoData[], todoWrapper: HTMLElement) {
    super(todoWrapper);
    this.todoData = todoData;

    this.init();
  }

  // 添加数据
  public addTodo (todo: ITodoData): undefined | number {
    const _todo: null | ITodoData = this.todoData.find((item: ITodoData) => item.content === todo.content);

    if (!_todo) {
      this.todoData.push(todo);
      this.addItem(todo);
      return;
    }

    return 1001;
  }

  // 初始化数据
  private init () {
    this.initList(this.todoData);
  }

  // 删除todo
  public removeTodo (target: HTMLElement, id: number): void {
    this.todoData = this.todoData.filter((todo: ITodoData) => todo.id !== id);
    this.removeItem(target);
  }

  // 点击切换完成状态
  public toggleComplete (target: HTMLElement, id: number): void {
    this.todoData = this.todoData.map((todo: ITodoData) => {
      if (todo.id === id) {
        todo.completed = !todo.completed;
        this.changeCompleted(target, todo.completed);
      }
      return todo;
    })
  }
}

export default TodoEvent;

8最后效果

[typescript]原生ts实现todoList


原文始发于微信公众号(豆子前端):[typescript]原生ts实现todoList

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/56659.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!