关于原生typescript实现todolist

2023-10-18 11:13:26 浏览数 (2)

前言

我是歌谣 最好的种树是十年前 其次是现在 今天继续给大家带来的是原始typescript的讲解

环境配置

npm init -y

yarn add vite -D

修改page.json配置端口

代码语言:javascript复制
{
  "name": "demo1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite --port 3002"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vite": "^4.4.9"
  }
}

目录结构

index.html

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ts</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>

app.ts

代码语言:javascript复制
import { ITodoData } from "./typings";
import TodoEvent from "./TodoEvent";
; ((doc) => {
    const oInput: HTMLInputElement = document.querySelector('input') as HTMLInputElement
    const oAddBtn: HTMLElement = document.querySelector('button') as HTMLElement
    const oTodoList: HTMLElement = document.querySelector('.todo-list') as HTMLElement


    const todoData: ITodoData[] = [
        {
            id: 1,
            content: 'geyao',
            completed: false
        },
        {
            id: 2,
            content: 'fangfang',
            completed: false
        },
        {
            id: 3,
            content: 'kang',
            completed: false
        }
    ]


    const init = (): void => {
        bindEvent()
    }


    function bindEvent(): void {
        oAddBtn.addEventListener("click", handleAddBtnClick, false)
        oTodoList.addEventListener("click", handleListClick, false)
    }
    function handleAddBtnClick(): void {
        const val:string=oInput.value.trim()
        console.log(val,"val is")
        if(val.length){
           const ret= todoEvent.addTodo(<ITodoData>{
                id: 4,
                content: val,
                completed: false
            })
            if(ret&&ret===1001){
                alert("列表已经存在")
                return
            }
            oInput.value=''
        }
       
   
    }
    function handleListClick(e: MouseEvent): void {
        const tar = e.target as HTMLElement
        const tagName = tar.tagName.toLowerCase()
        if (tagName === 'input' || tagName === 'button') {
            const id=parseInt(tar.dataset.id as string)
            switch (tagName) {
                case 'input':
                    todoEvent.toggleComplete(tar,id)
                    break;
                case 'button':
                    todoEvent.removeTodo(tar,id)
                    break;
                default:
                    break;
            }
        }
    }
    const todoEvent: TodoEvent = new TodoEvent(todoData,oTodoList)
    init()


})(document)

TodoDom.ts

代码语言:javascript复制
import TodoTemplate from "./TodoTemplate";
import { ITodoData } from "./typings";
import { createItem, findParentNode } from "./utils";


class TodoDom extends TodoTemplate{
    private todoWarpper:HTMLElement;
    constructor(todoWarpper:HTMLElement){
        super()
        this.todoWarpper=todoWarpper
    }
    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))
                // const oItem:HTMLElement=document.createElement("div")
                // oItem.className='todo-item'
                // oItem.innerHTML=this.todoView(todo)
                 oFrag.appendChild(oItem)
            })
            this.todoWarpper.appendChild(oFrag)
        }
    }
    protected addItem(todo:ITodoData){
        const oItem:HTMLElement= createItem("div","todo-item",this.todoView(todo))
    //    const oItem:HTMLElement=document.createElement('div');
    //    oItem.className='todo-item'
    //    oItem.innerHTML=this.todoView(todo)
       this.todoWarpper.appendChild(oItem)
    }
    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

todoEvent.ts

代码语言:javascript复制
import TodoDom from "./TodoDom";
import { ITodoData } from "./typings";


 class TodoEvent extends TodoDom{
    private todoData: ITodoData[]


    constructor(todoData: ITodoData[],todoWarpper:HTMLElement) {
        super(todoWarpper)
        this.todoData = todoData
        this.init()
    }
    public addTodo(todo: ITodoData): undefined | number {
        const _todo: null | ITodoData | undefined = this.todoData.find((item: ITodoData) => item.content===todo.content)
        console.log(_todo,"_todo is")
        if (!_todo) {
            this.todoData.push(todo)
            this.addItem(todo)
            return
        }
        return 1001
    }
    protected init(){
        this.initList(this.todoData)
    }
    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

todoTemplate.ts

代码语言:javascript复制
import { ITodoData } from "./typings";
class TodoTemplate{
   protected todoView({id,content,completed}:ITodoData):string{
      return `
      <input type="checkbox" ${completed}?'checked':'' data-id="${id}"/>
      <span style="text-decoration":${completed}?'line-through':'none'>${content}</span>
      <button data-id='${id}'>删除</button>
      `
   }
}


export default TodoTemplate

typing.ts

代码语言:javascript复制
export interface ITodoData{
    id:number,
    content:string,
    completed:boolean
}

utils.ts

代码语言:javascript复制
import { callbackify } from "util"
export function findParentNode(target:HTMLElement,className:string):any{
    while(target=target.parentNode as HTMLElement){
        if(target.className===className){
            return target 
        }
    }
}


export function createItem(tagName:string,className:string,todoItem:string):HTMLElement{
    const oItem:HTMLElement=document.createElement(tagName)
    oItem.className=className
    oItem.innerHTML=todoItem
    return oItem
}

运行结果

0 人点赞