2. 做一个极简 UI 库之Toast 组件

news2024/11/17 16:46:14

效果

API 设计

先设计好了 API 写起来代码才不会犯迷糊

Toast(message: string; otherParams?: ToastParams): ToastReturn

interface ToastParams {time?: number;appendTo?: string | HTMLElement;dangerouslyUseHTMLString?: boolean;
}

interface ToastReturn {close():void
} 

ToastParams 详解

属性说明类型默认值
timeToast 存在的时长, 单位秒, -1 代表永不消失number2
appendTo将 Toast 放到那个 dom 下string 或 HTMLElementdocument.body
dangerouslyUseHTMLString是否将 message 解析为 html 片段booleanfalse

ToastReturn 详解

属性说明类型默认值
close关闭 ToastFunction

难点说明

先说一下实现一个居中的 Toast 提示的基本思路:

div {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);
} 

有了这个核心样式 Toast 就有了。再继续往下做其实还需要俩步:

1.解决覆盖(遮挡)问题:需要放到顶级元素 body 下
2.如何用 js 代码进行这个组件的调用

先说第一个

fixed 的设置是有限制的,就是不能有任何祖先元素设置了 transformperspective 或者 filter 样式属性。也就是说如果我们想要用 CSS transform 为祖先节点 <div class="outer"> 设置动画,就会不小心破坏模态框的布局!

z-index 受限于它的容器元素。如果有其他元素与 <div class="outer"> 重叠并有更高的 z-index,则它会覆盖住我们的模态框。

vue 中提供了 <Teleport> 来将元素插入到需要的元素上,实际上你也可以用这种方式来使用 ToastMessage.vue 组件。只是需要用 v-if 来控制

第二个问题

如何用 js 直接调用 ToastMessage.vue 组件呢?好像必须要写在 template 里面才行吧?这里其实就要用到一些高级技巧了:

import { createVNode, render } from "vue";
import ToastMessage from "ToastMessage.vue";// 将组件变为 vnode 节点, 这个就是写 jsx 的时候的 h 方法
const vnode = createVNode(ToastMessage, ...);
// 将 vnode 节点挂载到浏览器的 dom 元素上
render(vnode, document.body) 

这是关键的俩步,将这俩步封装成一个 Function 就可以四处调用了

注意事项

defineProps

我们平常使用 defineProps 可能是这个样子的:

const props = defineProps<{message: string;dangerouslyUseHTMLString?: boolean
}>(); 

基于上面的思路我就想到了把 defineProps 接受的类型单独拿出来变成这样方便处理,结果新的事情发生了:

// type.ts
export interface ToastMessageProps {message: string;dangerouslyUseHTMLString?: boolean
}
// ToastMessage.vue
import { ToastMessageProps } from "./type"
const props = defineProps<ToastMessageProps>(); 

这个时候就会出现下面的错误:

然后我又想到了思路二:

// ToastMessage.vue
export interface ToastMessageProps {message: string;dangerouslyUseHTMLString?: boolean
}

const props = defineProps<ToastMessageProps>(); 

这个时候其实类型 ToastMessageProps 对于 ts 来说是识别不到的,因为 .vue 文件在处理的时候是统一处理的。并没有其他类型, 可以看到 env.d.ts

/// <reference types="vite/client" />

declare module "*.vue" {import type { DefineComponent } from "vue";// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-typesconst component: DefineComponent<{}, {}, any>;export default component;
} 

因此最后的实现方式是:

// type.ts
export const toastMessageProps = {message: {type: String,default: "",},dangerouslyUseHTMLString: {type: Boolean,default: false,},
};
export type ToastMessageProps = ExtractPropTypes<typeof toastMessageProps>;

// ToastMessage.vue
const props = defineProps(toastMessageProps); 

采用了 vue 最原始的定义参数的方式,然后 vue 提供了 ExtractPropTypes 类型来帮你获得需要的类型,也是很方便的。

两个文件间的引用

目前我的文件划分是(也是正确的划分方式):

ToastMessage.vue // 实现 Toast 组件的地方
type.ts // 定义了 ToastMessage 相关的一些类型(props emit defineExpose)
index.ts // 实现非组件化调用 Toast 的地方 

之前的文件划分方式:

ToastMessage.vue // 实现 Toast 的地方
index.ts // 实现非组件化调用 Toast 的地方 和 ToastMessage 的相关类型 

这种方式就存在了下面的问题

// ToastMessage.vue
import { toastMessageProps } from './index.ts'
const props = defineProps(toastMessageProps);
// index.ts
import ToastMessage from "./ToastMessage.vue"
export const toastMessageProps = { ... };

function Toast( ... ) {createVNode(ToastMessage, props);
} 

简单而言就是 index.ts 依赖的导入 ToastMessage.vue 文件又依赖了 index.ts 的导出。这个时候就会出现:

其他逻辑

查看源码

这里教一个小技巧,在 github 的项目界面按: SHIFT + . 可以进入 github.dev 网站,简单来说就是用浏览器端的 vscode 打开你的项目。

总结

这里主要是对于 vue 的 createVNode render 的运用。然后还可以学到 ExtractPropTypes 这个类型处理的方法。当然了我走过的坑小伙伴们就别再走一次了

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/113336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Node.js - Express

文章目录目标一、初识 Express1、Express 简介&#xff08;1&#xff09;什么是 Express&#xff08;2&#xff09;进一步理解 Express&#xff08;3&#xff09;Express 能做什么2、Express 的基本使用&#xff08;1&#xff09;安装&#xff08;2&#xff09;创建基本的 Web …

认识 Fuchsia OS

认识 Fuchsia OS 1 说明背景 1.1 基本信息 开发者: Google编程语言: C、C、Rust、Go、Python、Dart内核: Zircon运作状态: 当前源码模式: 开放源代码初始版本: 2016年8月15日支持的语言: 英语支持平台: ARM64、X86-64内核类别: 微内核 基于能力 实时操作系统许可证: BSD 3 c…

node.js+uni计算机毕设项目高校迎新管理小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

【2023 AR元宇宙过圣诞!】《Merry Meta Christmas》

啥也不说了&#xff0c;先看最终效果 3D场景资源、EasyAR_Plugin、图片与安卓App资源均已上传&#xff0c;点击该处下载 一、前言 圣诞节的真正含义是为了纪念耶稣诞生&#xff0c;象征着团圆美满&#xff0c;万物复苏&#xff0c;日子变得愈发美好 2021年是元宇宙的元年&…

UE5 狐獴演示Demo分析

1.特效的生成方式 1.1临时特效的生成&#xff1a;使用了已生成轨道临时创建该特效&#xff08;不用在场景中放入该特效&#xff0c;而是临时创建即可&#xff09;、系统生命周期轨道设置该特效的播放时长 1.2长期特效的生成&#xff1a;特效时长为该镜头片段长度 2.特效的类…

输出数组中每一行(列)中的最小值(最大值)numpy.amin()numpy.amax()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 输出数组中每一行&#xff08;列&#xff09;中的最小值&#xff08;最大值&#xff09; numpy.amin() numpy.amax() [太阳]选择题 对下面代码中np.amin(myList, 0)输出的结果为&#xff1f;…

java基于ssh的旅游系统

本项目主要发西安各个旅游景点和附近酒店信息的网站&#xff0c;用户可以根据旅游团一起旅游&#xff0c;可以也可以自驾游&#xff0c;还可以发布旅游活动等。 演示视频 https://www.bilibili.com/video/BV1wv411x7cg/?share_sourcecopy_web&vd_sourceed0f04fbb713154db…

【Vue】七、Vue-cli工程化开发

后端程序员的vue学习之路一、 Vue-cli安装Vue-cli1、安装node.js2、配置node.js环境变量3、 Npm仓库设置淘宝源4、全局安装 vue-cli5、创建vue应用程序1、 创建vue项目基础骨架&#xff1a;2、 运行项目&#xff1a;6、vue项目结构二、Vue.js项目运行逻辑分析1、 npm run dev命…

3.11.2、虚拟局域网 VLAN 实现机制

虚拟局域网 VLAN 技术是在交换机上实现的&#xff0c;需要交换机能够实现以下两大功能 能够处理带有 VLAN 标记的帧&#xff1a;IEEE 802.1Q 帧交换机的各端口支持不同的端口类型&#xff08;帧的处理方式有所不同&#xff09; 1、IEEE 802.1Q 帧 IEEE 802.1Q 帧&#xff08…

Java项目:SpringBoot美容院预约管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本系统分为管理员与普通用户两种角色&#xff1b; 管理员角色包含以下功能&#xff1a; 登录,首页,新增管理员,管理员信息列表,网站用户信息列表…

node.js+uni计算机毕设项目基于微信小程序校园心理咨询(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

RabbitMQ 第一天 基础 1 MQ的基本概念 1.1 MQ 概述 1.2 MQ的优势和 劣势 1.3 MQ的优势

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础1 MQ的基本概念1.1 MQ 概述1.1.1 MQ 概述1.1.2 小结1.2 MQ的优势和 劣势1.2.1 概述1.3 MQ的优势1.3.1 应用解耦1.3.2 异步提速1.3.3 削峰填谷1.3.4 小结第一天 基础…

【SpringMVC】SpringMVC模型数据+视图解析器

目录 一、模型数据-如何将数据存入request域 二、模型数据-如何将数据存入session域 三、ModelAttribute 四、视图解析器 相关文章 【SpringMVC】入门篇&#xff1a;带你了解SpringMVC的执行流程【SpringMVC】入门篇&#xff1a;带你了解SpringMVC的执行流程 【SpringMVC】使用…

springboot整合swagger

特别说明&#xff1a;本次项目整合基于idea进行的&#xff0c;如果使用Eclipse可能操作会略有不同&#xff0c;不过总的来说不影响。 springboot整合之如何选择版本及项目搭建 springboot整合之版本号统一管理 springboot整合mybatis-plusdurid数据库连接池 springboot整合…

node.js+uni计算机毕设项目儿童健康成长档案小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

暂时性死区以及函数作用域

暂时性死区 暂时性死区也就是变量声明到声明完成的区块&#xff0c;这个区块是一个封闭的作用域&#xff0c;直到声明完成。 如果在变量声明之前使用该变量&#xff0c;那么该变量是不可用的&#xff0c;也就被称为暂时性死区。 var 没有暂时性死区&#xff0c;因为var存在变…

Python编程 递归函数

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.函数执行注意点 二.递归函数 1.递归的介绍 2.例子 前言 本章将会讲解…

新版H5微信网页JS-SDK自定义分享功能实现

1.先用 微信官方文档demo&#xff0c;下载下来去改就行&#xff0c; 概述 | 微信开放文档 2.&#xff08;后端&#xff09;填写上认证后的&#xff0c;公众号appid&#xff0c;appsecret。 3.&#xff08;前端代码&#xff09; 配置好需要的接口&#xff08;调试打开debug&a…

自研框架(Webx)整合Zuul网关工作总结

写在前面&#xff0c;最近被分配了一个技术任务&#xff0c;简单描述为自研框架&#xff08;类比Spring&#xff09;整合一个微服务网关&#xff0c;并且能用就行。 有人可能会问&#xff0c;想用微服务网关&#xff0c;不是直接引入zuul或者gateway相关的依赖&#xff0c;然后…

【Pandas入门教程】如何合并多个表中的数据

如何合并多个表中的数据 来源&#xff1a;Pandas官网&#xff1a;https://pandas.pydata.org/docs/getting_started/intro_tutorials/index.html 笔记托管&#xff1a;https://gitee.com/DingJiaxiong/machine-learning-study 文章目录如何合并多个表中的数据导包数据准备【1】…