从零开始徒手撸一个vue的toast弹窗组件
相信普通的vue组件大家都会写,定义 -> 引入 -> 注册 -> 使用
,行云流水,一气呵成,但是如果我们今天是要自定义一个弹窗组件呢?
首先,我们来分析一下弹窗组件的特性(需求):
0. 轻量 –一个组件小于 1Kib (实际打包完不到0.8k)
1. 一般都是多处使用 –需要解决每个页面重复引用+注册
2. 一般都是跟js交互的 –无需 在<template>
里面写 <toast :show="true" text="弹窗消息"></toast>
今天,我们就抱着上面2个需求点,来实现一个基于vue的toast弹窗组件,下图是最终完成的效果图.
一. 先写一个普通的vue组件
文件位置 /src/toast/toast.vue
<template>
<div class="wrap">我是弹窗</div>
</template>
<style scoped>
.wrap{
position: fixed;
left: 50%;
top:50%;
background: rgba(0,0,0,.35);
padding: 10px;
border-radius: 5px;
transform: translate(-50%,-50%);
color:#fff;
}
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
二. 在我们需要使用的页面引入组件,方便看效果和错误
<template>
<div id="app">
<toast></toast>
</div>
</template>
<script>
import toast from './toast/toast'
export default {
components: {toast},
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
三. 实现动态加载组件
可以看到,已经显示出一个静态的弹出层了,接下来我们就来看看如何实现动态弹出.
我们先在 /src/toast/
目录下面,新建一个index.js
, 然后在index.js里面,敲入以下代码(由于该代码耦合比较严重,所以就不拆开一行一行讲解了,改成行内注释)
文件位置 /src/toast/index.js
import vue from 'vue'
// 这里就是我们刚刚创建的那个静态组件
import toastComponent from './toast.vue'
// 返回一个 扩展实例构造器
const ToastConstructor = vue.extend(toastComponent)
// 定义弹出组件的函数 接收2个参数, 要显示的文本 和 显示时间
function showToast(text, duration = 2000) {
// 实例化一个 toast.vue
const toastDom = new ToastConstructor({
el: document.createElement('div'),
data() {
return {
text:text,
show:true
}
}
})
// 把 实例化的 toast.vue 添加到 body 里
document.body.appendChild(toastDom.$el)
// 过了 duration 时间后隐藏
setTimeout(() => {toastDom.show = false} ,duration)
}
// 注册为全局组件的函数
function registryToast() {
// 将组件注册到 vue 的 原型链里去,
// 这样就可以在所有 vue 的实例里面使用 this.$toast()
vue.prototype.$toast = showToast
}
export default registryToast
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
附一个传送门 vue.extend 官方文档
四. 试用
到这里,我们已经初步完成了一个可以全局注册和动态加载的toast组件,接下来我们来试用一下看看
- 在vue的入口文件(脚手架生成的话是
./src/main.js
) 注册一下组件
文件位置 /src/main.js
import toastRegistry from './toast/index'
// 这里也可以直接执行 toastRegistry()
Vue.use(toastRegistry)
- 1
- 2
- 3
- 4
- 我们稍微修改一下使用方式,把
第二步
的引用静态组件的代码,改成如下
<template>
<div id="app">
<input type="button" value="显示弹窗" @click="showToast">
</div>
</template>
<script>
export default {
methods: {
showToast () {
this.$toast('我是弹出消息')
}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
可以看到,我们已经不需要
在页面里面引入
跟注册
组件,就可以直接使用this.$toast()
了.
五. 优化
现在我们已经初步实现了一个弹窗.不过离成功还差一点点,缺少一个动画,现在的弹出和隐藏都很生硬.
我们再对 toast/index.js
里的showToast
函数稍微做一下修改(有注释的地方是有改动的)
文件位置 /src/toast/index.js
function showToast(text, duration = 2000) {
const toastDom = new ToastConstructor({
el: document.createElement('div'),
data() {
return {
text:text,
showWrap:true, // 是否显示组件
showContent:true // 作用:在隐藏组件之前,显示隐藏动画
}
}
})
document.body.appendChild(toastDom.$el)
// 提前 250ms 执行淡出动画(因为我们再css里面设置的隐藏动画持续是250ms)
setTimeout(() => {toastDom.showContent = false} ,duration - 1250)
// 过了 duration 时间后隐藏整个组件
setTimeout(() => {toastDom.showWrap = false} ,duration)
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
然后,再修改一下toast.vue的样式
文件位置 /src/toast/toast.vue
<template>
<div class="wrap" v-if="showWrap" :class="showContent ?'fadein':'fadeout'">{{text}}</div>
</template>
<style scoped>
.wrap{
position: fixed;
left: 50%;
top:50%;
background: rgba(0,0,0,.35);
padding: 10px;
border-radius: 5px;
transform: translate(-50%,-50%);
color:#fff;
}
.fadein {
animation: animate_in 0.25s;
}
.fadeout {
animation: animate_out 0.25s;
opacity: 0;
}
@keyframes animate_in {
0% {
opacity: 0;
}
100%{
opacity: 1;
}
}
@keyframes animate_out {
0% {
opacity: 1;
}
100%{
opacity: 0;
}
}
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
大功告成,一个toast组件初步完成
总结
- vue.extend 函数可以生成一个
组件构造器
可以用这个函数构造出一个 vue组件实例 - 可以用 document.body.appendChild() 动态的把组件加到 body里面去
- vue.prototype.$toast = showToast 可以在全局注册组件
- 显示动画比较简单,隐藏动画必须要在隐藏之前预留足够的动画执行时间
- 本文源码地址 在这里
- 以上都不重要,重要的是 给本文来个star
从零开始徒手撸一个vue的toast弹窗组件的更多相关文章
- 徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!
我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中.Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小 ...
- 纯手工撸一个vue框架
前言 vue create 真的很方便,但是很多人欠缺的是手动撸一遍.有些人离开脚手架都不会开发了. Vue最简单的结构 步骤 搭建最基本的结构 打开空文件夹,通过 npm init 命令生成pack ...
- 一个 Vue 的滑动按钮组件
git 地址:https://github.com/SyMind/vue-sliding-button vue-better-slider 一个 Vue 的滑动按钮组件,有关滑动方面的处理借鉴 bet ...
- 撸一个vue的双向绑定
1.前言 说起双向绑定可能大家都会说:Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,当数据变化时通知视图更 ...
- mpvue的toast弹窗组件-mptosat
几乎每个小程序都会用到的弹窗功能,弹窗是为了友好的提示用户目前小程序的状态.这样以来toast弹窗就成了小程序不可或缺的组件.mptosat用过,不赖的一款.下面记录以下使用方法: 介绍 mptoas ...
- Vue自定义Popup弹窗组件|vue仿ios、微信弹窗|vue右键弹层
基于vue.js构建的轻量级Vue移动端弹出框组件Vpopup vpopup 汇聚了有赞Vant.京东NutUI等Vue组件库的Msg消息框.Popup弹层.Dialog对话框.Toast弱提示.Ac ...
- 撸一个 vue 的截图组件,按比例截取
<template> <div class="clip-img" :style="imgStyle"> <img :src=&qu ...
- 使用 Go 语言徒手撸一个负载均衡器
负载均衡器在 Web 架构中扮演着非常重要的角色,被用于为多个后端分发流量负载,提升服务的伸缩性.负载均衡器后面配置了多个服务,在某个服务发生故障时,负载均衡器可以很快地选择另一个可用的服务,所以整体 ...
- 大型情感类技术连续剧-徒手撸一个 uTools(二)
前言 上篇手把手教你实现一个支持插件化的 uTools 工具箱我们介绍过了如何通过 electron 实现 utools 的插件功能体系,并按照 utools 的交互和设计做出了一套可以支持插件化的桌 ...
随机推荐
- uva 11021
题意:有k只麻球,每只活一天就会死亡,临死之前可能会生出一些新的麻球.具体来说,生i个麻球的概率为pi.给定m,求m天后所有麻球死亡的概率.注意,不足m天时就已经全部死亡的情况也算在内. 分析:由于每 ...
- uva 11806 容斥原理+dfs
In most professional sporting events, cheerleaders play a major role in entertaining the spectators. ...
- java多线程编程核心技术学习-1
实现多线程的两种方式 继承Thread类,重写Thread类中的run方法 public class MyThread extends Thread{ @Override public void ru ...
- [Python] 'unicode' object is not callable
在Python中,出现'unicode' object is not callable的错误一般是把字符串当做函数使用了.
- python 之文件操作
一.文件基本操作 1.文件的打开 打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作 文件句柄 = open('文件路径', '模式') 2. ...
- Python使用eval强制转换字符串为字典时报错:File "<string>", line 1, in <module> NameError: name 'nan' is not defined
文本中保存的内容为: { 'QQQ': [0.067, 0.167, 0.2, 0.033, 0.233, 0.267, 0.1, 0.133], 'TTT': [0.5, 0.375, 0.25, ...
- Spring中Bean的后置处理器
以下内容引用自http://wiki.jikexueyuan.com/project/spring/bean-post-processors.html: Bean后置处理器 BeanPostProce ...
- php执行超时(nginx,linux环境)
与下面的参数有关 nginx: fastcgi_connect_timeout fastcgi_read_timeout fastcgi_send_timeout php-fpm:request_te ...
- android 获得屏幕宽度和高度
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...
- How to Install a Language Pack
https://www.phpbb.com/kb/article/how-to-install-a-language-pack