前端歌谣-第玖课-关于原始typescript实现todolist

前言

我是歌谣 最好的种树是十年前 其次是现在 今天继续给大家带来的是原始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))
// 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

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
}

运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

posted @   前端导师歌谣  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示