关于原生typescript实现todolist

  前言

ed70c8fca79d7370ba91e7098b56dcc2.png

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

 环境配置

714f4cc4bf463bb572b9508818b16a05.png

npm init -y

yarn add vite -D

  修改page.json配置端口

645727d803aa3d9df6f2a5eb2b014abc.png

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

 目录结构

9a472b1a5056fb877bfe75cf485dfdf5.png

d6a2ced3e0346790372031ed996d2e16.png

 index.html

a034db0a45dbdaf6000aa79777202da2.png

<!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

46a347b52c50c40f772e9c8ca34e2798.png

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

4ab621b54117c814671588678db6e1d0.png

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

83bc9b00ff0e284dd8b317698380b33f.png

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

d1c931714982f0766626cdab40396517.png

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

cc894b7b08f8c572467d508b7b920f4e.png

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

 utils.ts

34ce7f01a164a0562e2189f386c18e87.png

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
}

运行结果

1c03f0e94c388514e3b5b73a4e54b988.png

3103ec765b92349d517fbbf05d70cfea.png

fa2bb09c1d77392cac2d8b874c94f44c.png

7221d6bfef317bef755dfc537f556994.png

点击上方蓝字关注我们

ecf4193ec9de2e5e42f2d1d0bbc14d98.png

下方查看历史文章

d9c95da9a38ee05e7be3b7ba435db20f.png

关于面向对象

关于原型

关于this指向

关于回调

关于闭包(完)笔记

posted @ 2023-10-11 07:02  前端导师歌谣  阅读(28)  评论(0)    收藏  举报  来源