前言
我是歌谣 最好的种树是十年前 其次是现在 今天继续给大家带来的是原始typescript的讲解
环境配置
| npm init -y |
| yarn add vite -D |
修改page.json配置端口
| { |
| "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
| <!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
| 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
| 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)) |
| |
| |
| |
| oFrag.appendChild(oItem) |
| }) |
| this.todoWarpper.appendChild(oFrag) |
| } |
| } |
| protected addItem(todo:ITodoData){ |
| const oItem:HTMLElement= createItem("div","todo-item",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
| 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
| 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
| export interface ITodoData{ |
| id:number, |
| content:string, |
| completed:boolean |
| } |
utils.ts
| 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 |
| } |
运行结果



【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!