初学TypeScript系列——实现一个小案例(二)

88 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

接着上一篇案例的具体实现,这一篇文章来实现页面操作相关功能。

  1. 创建一个OperationFun类用于处理页面新增和删除数据。
    (1)在类中创建增加数据方法addData,接收参数(接口中小喵的数据),动态创建一个li元素,并加入数据内容,追加到ul元素中;
    (2)同时还要创建删除数据方法deleteData, 接收点击的元素作为参数,获取该元素的父元素,实现当前整个数据的移除。
class OperationFun{
    //public 描述类内部的修饰的属性或方法是公有的
    //static 修饰符修饰的属性或者方法。存在于类本身上,可以直接通过类来调用
    public static addData(data: CatType): void{
      //new一个cat实例
      const cat: Cat = new Cat(data);
      //创建一个li元素,声明类型为HTMLLIElement(因为li元素是新建的,确定存在,所以不用指定类型为null)
      const tableRow: HTMLLIElement  = document.createElement('li');
      tableRow.innerHTML = `
          <span><img src="${cat.url}"></span>
          <span>${cat.height}</span>
          <span>${cat.width}</span>
          <span class="delete">删除</span>
          <span class="down" data-url="${cat.url}">下载</span>
      `
      tableBody?.appendChild(tableRow);
    }

![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2a67c78160fc4ce58cd96c6d9b504602~tplv-k3u1fbpfcp-watermark.image?)
    public static deleteData(deleteButton: HTMLElement): void {
      const li = deleteButton.parentElement as HTMLLIElement;      
      li.remove();
    }
}
  1. 创建接收数据方法,根据接口url,获取小猫的数据,并使用OperationFun类的addData把小猫数据展示到页面中
async function getJSON<T>(url: string): Promise<T> {
  const response: Response = await fetch(url);    
  const json: Promise<T> = await response.json();
  return json;
}

async function getData(): Promise<void> {
    try {
        const json: CatType[] = await getJSON<CatType[]>(url);
        const data: CatType = json[0];
        OperationFun.addData(data);
    }
    catch (error: Error | unknown) {
        let message: string;
        if (error instanceof Error) {
            message = error.message;
        } else {
            message = String(error);
        }
        console.log(error);
    }
}
  1. “随机一只喵”按钮点击事件
button?.addEventListener<'click'>('click', getData);
  1. 每只喵的删除事件,利用事件委托实现。
    (1)定义整个ul的监听事件,当删除元素(子元素)被点击时,由于事件冒泡原理,会冒泡到ul元素,所以可以在ul元素的监听函数处理这个点击事件;查看event对象的目标节点是不是实际操作的当前元素(根据当前点击的目标元素的类名是不是删除元素的类名),如果是,就执行删除操作。
    (2)同理执行图片的下载操作
tableBody?.addEventListener<'click'>('click', (e: MouseEvent) => {
    //您需要明确地告诉 TypeScript 作为目标的 HTMLElement 的类型。
    // 这样做的方法是使用泛型类型将其转换为正确的类型:
    const target = e.target as HTMLSpanElement;
    if(target.className === "delete"){
      console.log(target.className )
      OperationFun.deleteData(<HTMLElement>e.target);
    }else if(target.className === "down"){
      const imgUrl = target.getAttribute('data-url');
      if(imgUrl){
        downloadIamge(imgUrl, '图片的名称') 
      }
    }
  });
  1. 下载图片的实现
    (1)一开始打算简单的使用a标签实现下载,但是发现无法实现。
    a 标签中添加了 download 属性,点击没有进行下载,而是在当前页面打开了图片。a标签实现下载图片,必须要下载的图片地址和浏览器访问地址同源时才能实现。
    (2) 使用 canvas 方式 保存图片

image.png 问题: 高版本chrome出于安全考虑,禁止打开base64图片

image.png

解决方法:使用 canvas 绘制图片,并把图片的 base64 编码,设置为创建的 a标签的地址,需要给a标签属性加上download 属性(能够强制触发下载操作),可以指定浏览器下载图片时的默认名称。当点击下载,download属性值里的名称会显示到弹出的下载框里。(ps: 操作中提示过好些ts提示相关的问题,搜索解决就忘记记录了)

页面展示:

image.png