nutUI的toast提示框组件源码,教你一步一步,封装公共组件
作者:互联网
话不多说,这个篇博客只为了,将toast组件原滋原味的放到自己的项目,看源码,理解大致意思,后续会去封装属于自己的组件
首先:在components文件夹中创建如下文件:
下面我将按照逻辑顺序将各个文件的源码贴出来:
index.js: (可以看到,给toast对象添加了自定义方法install,用来在vue实例上挂载组件)
import Toast from './_toast'; import './toast.scss'; Toast.install = function (Vue) { Vue.prototype['$toast'] = Toast; } export default Toast;
_toast.js:
这个js文件主要用Vue的extend方法来把自己写的vue文件传进去,创建一个构造器,然后再渲染,最后挂载在body上;主要代码在红色的代码上;最后抛出了一个toast对象。
import Vue from "vue"; import settings from "./toast.vue"; let ToastConstructor = Vue.extend(settings); let instance;//实例 let instanceArr = [];//实例列表 let defaultOptionsMap = {};//默认配置参数地图 const defaultOptions = {//默认配置参数 msg: "",//提示语 visible: false,//是否显示 duration: 2000, //显示时间(毫秒) timer: null,//计时器 center: true,//位置 type: "",//类型 customClass: "",//自定义类名 bottom: 300,//距离底部多少距离 size: "base",//大小 icon: null,//icon textAlignCenter: true, loadingRotate: true, bgColor: "rgba(36, 36, 36, 0.8)",//北京颜色 onClose: null, textTimer: null, cover: false, //透明遮罩层 coverColor: "rgba(0, 0, 0, 0)", timeStamp: null,//时间戳 closeOnClickOverlay: false, }; let currentOptions = { ...defaultOptions }; function _showToast() { instance.vm = instance.$mount(); document.body.appendChild(instance.$el); Vue.nextTick(() => { instance.visible = true; }); } function _getInstance(obj) { //获取实例 let opt = { id: new Date().getTime(), ...currentOptions,//默认配置 ...defaultOptionsMap[obj.type], ...obj,//传入的配置 }; //有相同id者共用一个实例,否则新增实例 if (opt["id"] && instanceArr[opt["id"]]) { instance = instanceArr[opt["id"]]; instance.hide(true); instance = Object.assign(instance, opt); } else { instance = new ToastConstructor({ //混入 data: Object.assign(opt, obj) }); opt["id"] && (instanceArr[opt["id"]] = instance); } _showToast(); return instance; } function errorMsg(msg) { if (!msg) { console.warn("[NutUI Toast]: msg不能为空"); return; } } let Toast = { text(msg, obj = {}) { errorMsg(msg); return _getInstance({ ...obj, msg, type: "text" }); }, success(msg, obj = {}) { errorMsg(msg); return _getInstance({ ...obj, msg, type: "success" }); }, fail(msg, obj = {}) { errorMsg(msg); return _getInstance({ ...obj, msg, type: "fail" }); }, warn(msg, obj = {}) { errorMsg(msg); return _getInstance({ ...obj, msg, type: "warn" }); }, loading(msg, obj = {}) { obj = { ...obj, id: obj.id || "loading", msg, type: "loading" }; obj.cover = typeof obj.cover !== "undefined" ? obj.cover : true; //loading类型默认打开遮罩层 obj.duration = obj.duration || 0; //loading类型默认不自动关闭 return _getInstance(obj); }, setDefaultOptions(type, options) { if (typeof type === "string") { defaultOptionsMap[type] = options; } else { Object.assign(currentOptions, type); } }, resetDefaultOptions(type) { if (typeof type === "string") { defaultOptionsMap[type] = null; } else { currentOptions = { ...defaultOptions }; defaultOptionsMap = {}; } } }; export default Toast;
再来看一下toast.vue文件:这是模板文件
<template> <transition name="toastfade"> <div :id="id" :class="toastClass" v-if="visible" :style="{ bottom: center ? 'auto' : bottom + 'px', 'background-color': coverColor }" @click="clickCover" > <div class="nut-toast-inner" :style="{ 'text-align': textAlignCenter ? 'center' : 'left', 'background-color': bgColor }" > <span v-if="hasIcon" class="nut-toast-icon-wrapper"> <i :class="[ 'nut-toast-icon', type, { 'nut-toast-icon-rotate': type === 'loading' && loadingRotate } ]" :style="{ 'background-image': cusIcon }" ></i> </span> <span class="nut-toast-text" v-html="msg"></span> </div> </div> </transition> </template> <script> export default { name: "nut-toast", props: {}, data() { return { id: "", msg: "", visible: false, duration: 2000, //显示时间(毫秒) timer: null, center: true, type: "", customClass: "", bottom: 30, size: "base", icon: null, textAlignCenter: true, loadingRotate: true, bgColor: "rgba(46, 46, 46, 0.7)", onClose: null, textTimer: null, cover: false, coverColor: "rgba(0, 0, 0, 0)", timeStamp: null, closeOnClickOverlay: false }; }, watch: { visible(val) { if (val) { this.show(); } } }, computed: { cusIcon() { return this.icon ? `url("${this.icon}")` : ""; }, toastClass() { return [ "nut-toast", { "nut-toast-center": this.center }, { "nut-toast-has-icon": this.hasIcon }, { "nut-toast-cover": this.cover }, { "nut-loading": this.type == "loading" }, this.customClass, "nut-toast-" + this.size ]; }, hasIcon() { if (this.type !== "text") { return true; } else { return this.cusIcon; } } }, methods: { show(force) { this.clearTimer(); clearTimeout(this.textTimer); if (this.duration) { this.timer = setTimeout(() => { this.hide(force); }, this.duration); } }, hide(force) { this.clearTimer(); this.visible = false; if (force) { clearTimeout(this.textTimer); } else { this.textTimer = setTimeout(() => { clearTimeout(this.textTimer); this.msg = ""; }, 300); } typeof this.onClose === "function" && this.onClose(); }, clearTimer() { if (this.timer) { clearTimeout(this.timer); this.timer = null; } }, clickCover() { if (this.closeOnClickOverlay) { this.hide(); } } }, destroyed() { this.textTimer = null; this.timer = null; } }; </script>
以上是主要的js文件,下面把两个样式文件也贴上,这个组件样式和逻辑代码使用的都很巧妙,不能说哪个重要哪个不重要:
toast.scss
@import "./animation/rotate"; .nut-toast { position: fixed; left: 0; bottom: 150px; width: 100%; text-align: center; pointer-events: none; z-index: 9999; font-family: $font-family; &.nut-toast-small { .nut-toast-inner { font-size: $font-size-small; } } &.nut-toast-large { .nut-toast-inner { font-size: $font-size-large; } } &.nut-toast-cover { display: flex; align-items: center; justify-content: center; pointer-events: auto; height: 100%; } .nut-toast-inner { position: relative; display: inline-block; font-size: $font-size-base; max-width: 65%; text-align: center; line-height: 1.5; padding: 10px 30px; word-break: break-all; background: rgba(46, 46, 46, .8); border-radius: 7px; color: #fff; } &.nut-toast-has-icon { .nut-toast-inner { padding: 70px 50px 30px; } .nut-toast-icon-wrapper { position: absolute; left: 0; top: 20px; width: 100%; height: 50px; display: flex; align-items: center; justify-content: center; } .nut-toast-icon { display: inline-block; width: 30px; height: 30px; background-repeat: no-repeat; background-size: 100%; &.success { background-image: url("data:image/svg+xml,%3Csvg width='48' height='46' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd' %3E%3Cpath d='M8 0h18c11.046 0 20 8.954 20 20v18a8 8 0 0 1-8 8H20C8.954 46 0 37.046 0 26V8a8 8 0 0 1 8-8z' fill='rgb(255,255,255)'/%3E%3Cpath d='M43.562 3L22.01 23.803l-4.855-4.557a2.934 2.934 0 0 0-4.147.132l-1.324 1.41a1 1 0 0 0 .045 1.414l9.047 8.49a2 2 0 0 0 2.763-.025L47.741 7.12 43.562 3z' fill='rgb(44,42,53)'/%3E%3C/g%3E%3C/svg%3E"); } &.fail { background-image: url("data:image/svg+xml,%3Csvg width='46' height='46' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M8 0h18c11.046 0 20 8.954 20 20v18a8 8 0 0 1-8 8H20C8.954 46 0 37.046 0 26V8a8 8 0 0 1 8-8z' fill='rgb(255,255,255)'/%3E%3Cg fill='rgb(44,42,53)'%3E%3Cpath d='M13.6 15.722l1.415-1.414a2 2 0 0 1 2.828 0L33.4 29.864a1 1 0 0 1 0 1.414l-1.414 1.414a2 2 0 0 1-2.828 0L13.6 17.136a1 1 0 0 1 0-1.414z'/%3E%3Cpath d='M33.4 15.722l-1.415-1.414a2 2 0 0 0-2.828 0L13.6 29.864a1 1 0 0 0 0 1.414l1.414 1.414a2 2 0 0 0 2.828 0L33.4 17.136a1 1 0 0 0 0-1.414z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); } &.warn { background-image: url("data:image/svg+xml,%3Csvg width='46' height='46' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M8 0h18c11.046 0 20 8.954 20 20v18a8 8 0 0 1-8 8H20C8.954 46 0 37.046 0 26V8a8 8 0 0 1 8-8z' fill='rgb(255,255,255)'/%3E%3Cpath d='M23 23V12' stroke='rgb(44,42,53)' stroke-width='6' stroke-linecap='round'/%3E%3Cpath d='M21 30h3a2 2 0 0 1 2 2v3a1 1 0 0 1-1 1h-3a2 2 0 0 1-2-2v-3a1 1 0 0 1 1-1z' fill='rgb(44,42,53)'/%3E%3C/g%3E%3C/svg%3E"); } &.loading { background: url("data:image/svg+xml, %3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='rgb(230,230,230)' d='M874.667 533.333h-192c-12.8 0-21.334-8.533-21.334-21.333 0-12.8 8.534-21.333 21.334-21.333h192c12.8 0 21.333 8.533 21.333 21.333 0 12.8-8.533 21.333-21.333 21.333zM648.533 407.467C640 416 627.2 416 618.667 407.467c-8.534-8.534-8.534-21.334 0-29.867L755.2 241.067c8.533-8.534 21.333-8.534 29.867 0 8.533 8.533 8.533 21.333 0 29.866L648.533 407.467zM512 896c-12.8 0-21.333-8.533-21.333-21.333v-192c0-12.8 8.533-21.334 21.333-21.334s21.333 8.534 21.333 21.334v192c0 12.8-8.533 21.333-21.333 21.333zm0-533.333c-12.8 0-21.333-8.534-21.333-21.334v-192c0-12.8 8.533-21.333 21.333-21.333s21.333 8.533 21.333 21.333v192c0 12.8-8.533 21.334-21.333 21.334zM270.933 782.933c-8.533 8.534-21.333 8.534-29.866 0s-8.534-21.333 0-29.866L377.6 616.533c8.533-8.533 21.333-8.533 29.867 0 8.533 8.534 8.533 21.334 0 29.867L270.933 782.933zm104.534-375.466L238.933 270.933c-8.533-8.533-8.533-21.333 0-29.866s21.334-8.534 29.867 0L405.333 377.6c8.534 8.533 8.534 21.333 0 29.867-6.4 6.4-21.333 6.4-29.866 0zM362.667 512c0 12.8-8.534 21.333-21.334 21.333h-192C136.533 533.333 128 524.8 128 512c0-12.8 8.533-21.333 21.333-21.333h192c12.8 0 21.334 8.533 21.334 21.333zm285.866 104.533l136.534 136.534c8.533 8.533 8.533 21.333 0 29.866-8.534 8.534-21.334 8.534-29.867 0L618.667 646.4c-8.534-8.533-8.534-21.333 0-29.867 6.4-6.4 21.333-6.4 29.866 0z'/%3E%3C/svg%3E") no-repeat; background-size: cover; } } } &.nut-toast-center { top: 50%; transform: translateY(-50%); } &.nut-loading { .nut-toast-inner { padding: 25px; display: inline-flex; flex-direction: column; justify-content: center; align-items: center; } .nut-toast-icon-wrapper { position: static; height: 30px; } .nut-toast-text:not(:empty) { margin-top: 10px; margin-bottom: -10px; } .nut-toast-icon { width: 40px; height: 40px; &.nut-toast-icon-rotate { animation: rotation 2s linear infinite; } } } } .toastfade-enter-active { transition: opacity 0.1s; } .toastfade-leave-active { transition: opacity 0.3s; } .toastfade-enter, .toastfade-leave-active { opacity: 0; }
animation/rotate.scss
@keyframes rotation { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); } } @include make-animation(nutRotate);
将toast文件放到项目中后如何使用呢???
首先,在main.js中:注册一下
import toast from '@/components/toast'; toast.install(Vue);
在项目中使用:
this.$toast.success("123")
以上就是nutUI的toast组件的源码,主要是熟悉一下组件的封装,后续就可以封装属于自己的全局组件了!
。
标签:toast,8.533,一步,21.333,3E%,源码,组件,obj,nut 来源: https://www.cnblogs.com/fqh123/p/13121402.html