/vuetify-message-snackbar

函数式使用 vuetify-snackbar,使用Typescript,链式调用增强体验

Primary LanguageTypeScript

Vuetify Message Snackbar

开发插件时vuetify的版本号是2.3.10,支持Nuxt

Vuetify Snackbar 的样式和功能都很有特点,但美中不足,没有提供函数式调用的能力。

习惯 ElementUI 函数式唤起消息条的人可能不会再想笨重的写 DOM,再通过数据驱动控制消息条的显隐,麻烦,影响开发效率。

所以本插件参考了 ElementUI Message 的调用方式对 v-snackbar 进行了封装与扩展,并提供了便捷的函数式配置能力。

在线预览效果

特点

  • 函数式显示与隐藏 Snackbar
  • 六个方向支持多消息同时显示(上左中右、下左中右)
  • 支持 VNode (内容与右侧的关闭按钮都支持)
  • 链式调用设置属性
  • 自动设置过渡动画
  • 自定义配置支持缓存再调用

安装

npm install -D vuetify-message-snackbar
Browser
import Vue from 'vue'
import message from 'vuetify-message-snackbar';

Vue.use(message[, option]);
  • option

Vue.use 时的option请参考下方的配置项说明,可不传

const vuetifyPreset = {};
const vuetify = new Vuetify(vuetifyPreset);

Vue.use(Message, {
	autoRemove: true,
	closeButtonContent: 'CLOSE',
	offsetTop: 10,
	autoTransitionSetting: true,
	class: 'margin-top-animation',
	// 预设icon
	presetIcon: {
		success: 'mdi-checkbox-marked-circle'
	},
	// 传入实例可以确保snackbar的样式表现统一
	// 保持和初始化vue时传入的实例统一
	vuetifyInstance: vuetify,
	// 初始化时拿不到vuetify的实例,可以配置传参
	// 但是这种方式在一定情况下表现可能还是有差异,不过可以通过动态设置实例解决
	// 具体请参考下方的说明 (#样式表现不一致的问题)
	vuetifyPreset,
	// ...以及几乎所有的组件属性都可以在这里进行设置, 比如:
	absolute: true,
	dark: true,
	width: 600,
	height: 200,
	transition: 'scroll-x-transition',
})

new Vue({
  el: '#app',
  render: (h) => h(App),
  vuetify,
})
CDN

下方链接仅供参考

<script src="https://cdn.jsdelivr.net/npm/vuetify-message-snackbar"></script>

<script>
	Vue.use(VuetifyMessageSnackbar[, option]);
</script>
Nuxt

/plugins 文件夹中新建message目录,message目录下新建index.js / index.ts文件

import Vue from 'vue'
import message from './vuetify-message-snackbar'

Vue.use(message[, option]);

nuxt.config.js中,找到plugins字段,添加一项

plugins: [
  '~/plugins/message'
]

组件需知

如果你是以按需加载的方式加载的Vuetify,请确保以下组件已经被注册:

  • v-snackbar
  • v-icon
  • v-btn

参考下方示例代码:

import Vuetify, { VSnackbar, VBtn, VIcon } from “vuetify/lib”;

Vue.use(Vuetify);

Vue.component("v-snackbar", VSnackbar);
Vue.component("v-btn", VBtn);
Vue.component("v-icon", VIcon);

使用

  • 基本的用法
// 传参
this.$message({
	message: 'Hello',
	color: 'success',
})

// 快捷方法
this.$message.success('success');
this.$message.info('info');
this.$message.warning('warning');
this.$message.error('error');

// 默认底色(color)
this.$message.show('show');
  • 自定义方向
this.$message.top().success('top'); // 上中
this.$message.bottomLeft().success('bottomLeft'); // 下左
// (top/topLeft/topRight/bottom/bottomLeft/bottomRight) 共六个方向
在JS/TS文件中使用
import { Notify } from "vuetify-message-snackbar";
Notify.success('use in js');
  • 函数式配置
通过函数可以设置绝大部分属性

除了方向相关以及value外的所有属性都可以设置(top/left/right/bottom/value),因为方向相关的已经封装了对应的六个函数(top/topLeft/bottomRight等);而value是控制显隐的,属于特殊属性所以不允许外部控制

this.$message.top().timeout(-1).info('timeout');	// 设置自动隐藏时间
纯布尔值默认为真

如果属性是纯布尔值的(不是多类型或者非布尔的),那么调用不传参默认就是设置为true

this.$message.topRight().light().success('light');	// 设置为浅色的主题
this.$message.topRight().light(true).success('light');	// 与上面的那句等价

this.$message.topRight().light(false).success('light');	// 设置非浅色的主题
消息条ICON

0.2.3 版本预设了success/info/warning/error的字体图标

如果传入string,比如mdi-domain,那将会转换成<v-icon left>mdi-domain</v-icon>的结构,所以请确保传入的参数可以被v-icon正确的解析)

通过Vue.use或者this.$message.messageIcon传参可覆盖

messageVNode类型时,该功能失效

this.$message.messageIcon("mdi-domain").success("自定义Icon"); // string
this.$message.messageIcon(this.$createElement("v-icon", {
	props: {
		small: true,
	}
}, ["mdi-domain"])).success("自定义Icon"); // VNode

this.$message.messageIcon().success("Hide Icon"); // 隐藏预设的icon
配置链式调用

相同配置以最后一次执行的值为准

this.$message.vertical().height(100).info('配置链式调用'); // 链式调用
this.$message.height(600).height(10).height(300).info('高度为300'); // 重复配置

需要注意一点,如果要自定义背景色(color),最后需要调用show方法,而不可以是success/info/warning/error(因为这几个命令对color的赋值优先级是最高的,调用后自定义color值将被覆盖)

this.$message.top().color('#12d6cd').show();	// 自定义背景色
随机动画效果

调用 transition 时不传参的话,会从vuetify默认自带的 10 个过渡效果中随机选择一个

this.$message.transition().success('random');
带有横线的参数支持两种配置方式
// 所有带横线的参数都支持下面两种写法
this.$message['min-width'](100).success('min-width');
this.$message.minWidth(100).success('minWidth');
设置关闭按钮(官方属性外的扩展设置)
// 设置按钮标题
// 如果传文本,需要保证全局支持`v-btn`,因为关闭按钮默认就是`v-btn`
this.$message.closeButtonContent('关闭').success('close-button');

// 自定义 VNode
this.$message.closeButtonContent(this.$createElement('div', 'VNode Close')).success('关闭按钮使用VNode');

// 传空字符串会隐藏关闭按钮
this.$message.closeButtonContent('').success('隐藏关闭按钮');
设置消息条的边距(官方属性外的扩展设置)
this.$message.offsetTop(100).success('offset-top');

方法

  • $message.closeAll

    • 描述:隐藏当前所有的消息条
    • 返回值:无
this.$message.closeAll();
  • $message | $message.success | $message.info | $message.warning | $message.error | $message.show

    • 描述:创建消息条
    • 返回值:{ close(): void, again(): { close() => void } }
  • close

    • 描述:隐藏创建的消息条
    • 返回值:无
  • again

    • 描述:按照相同参数创建一个新的消息条
    • 返回值:{ close(): void }
const bar = this.$message.success('message');
bar.close();	// 隐藏消息条
bar.again();	// 创建一个新的相同的消息条
  • save( name: string )

    • 描述:保存当前函数式配置产生的参数,通过read方法可以根据name读取所保存的参数
    • 返回值:实例
  • read( name: string )

    • 描述:根据name读取相对应的通过save方法保存的配置参数
    • 返回值:实例
this.$message.top().closeButton('关闭').absolute().elevation(10).save('test');
this.$message.read('test').success('custom');
this.$message.read('test').success('custom1');
// 等同于下方
this.$message.top().closeButton('关闭').absolute().elevation(10).success('custom');
this.$message.top().closeButton('关闭').absolute().elevation(10).success('custom1');

说明

自动设置过渡动画

在通过top/topLeft/topRight/bottom/bottomLeft/bottomRight设置方向时,并且没有人为设置过渡动画,这时候插件会自动设置对应的过渡动画。

Vue.use 时,参数中设置 autoTransitionSetting: false可关闭此效果

对于已经使用 transition()进行了函数配置了,或者通过传参设置了该值的情况下,也不会自动设置过渡动画

位置 过渡动画
top scroll-y
bottom scroll-y-reverse
topLeft/bottomLeft slide-y
topRight/bottomRight slide-y-reverse
marginTop 过渡效果说明

在有多个消息条时,插件通过设置marginTop将消息条与消息条隔开,并通过内置的 CSS margin-top-animationmarginTop简单的做了一个过渡效果,使消息条消失时其余的消息条会有一个平移的效果。

如果不想要这个效果或者想自定义效果,Vue.use注册本插件时通过设置参数class即可,该参数说明见下方配置项相关中的表格。

配置项相关
  • 配置项优先级

$message(option)传入的参数 > 函数式配置产生的参数 > 插件内置默认参数 > Vue.use时传入的参数

  • 插件内置默认参数
参数名 参数值
top true
bottom false
left false
right false
timeout 3000

下方几个属性为插件的属性,非官方组件的属性

  • 只能在 Vue.use 时使用
参数名 类型 默认值 描述
appendTo string | Element undefined 指定消息条渲染在哪个节点下,默认会选择.v-application/#app/body,如果都获取不到则会放到根节点下(没有渲染在v-app组件下会影响部分样式)
presetIcon {[messageType: string]: string} undefined 预设icon (0.2.4新增)
vuetifyInstance Vuetify
vuetifyPreset VuetifyPreset
  • Vue.use时与$message(option)时都支持
参数名 类型 默认值 描述
autoRemove boolean true 消息条隐藏后是否从树中移除
closeButtonContent string | VNode "" 消息条取消按钮的文案
offsetTop number 10 消息条与消息条之间的间隔
class string | string[] undefined 每个消息条的类名,传空字符串或空数组可覆盖默认的margin-top-animation
autoTransitionSetting boolean true 未手动设置过渡动画时,是否自动根据对应位置设置不同效果的过渡动画
message string | VNode undefined 消息条内容(Vue.use时设置此值可作为消息条内容的默认值)
messageIcon string | VNode undefined 指定消息条内容的字体图标(0.2.3新增)

函数式配置具体都能配置哪些参数,可以去看官方文档该组件的参数:https://vuetifyjs.com/zh-Hans/components/snackbars/

不过查看项目内的 TS 文件的话是最准确的

样式表现不一致的问题

issue: #7

  • 普通web项目传入vuetify实例

  • Nuxt项目传入配置项或者在created时动态设置

import { setVuetifyInstance } from "vuetify-message-snackbar"

export default {
	created() {
		setVuetifyInstance(this.$root.$options.vuetify);
	}
}