内容简介:这里还是以element-ui为例,那我们就看看里面的Message。它的dom结构什么的就写在node-modules/element-ui/packages/notification/src/main.vue里面可以看出,这里东西不多,只有一些对应的class、关闭按钮外,就剩下title和message了,这里看到用了slot,所以我们通常也只能将自己的自定义内容放入此插槽中。
这里还是以element-ui为例,那我们就看看里面的Message。
它的dom结构什么的就写在node-modules/element-ui/packages/notification/src/main.vue里面
<template> <transition name="el-notification-fade"> <div :class="['el-notification', customClass, horizontalClass]" v-show="visible" :style="positionStyle" @mouseenter="clearTimer()" @mouseleave="startTimer()" @click="click" role="alert" > <i :class="[ typeClass, iconClass ]" v-if="type || iconClass"> </i> <div :class="{ 'is-with-icon': typeClass || iconClass }"> <h2 v-text="title"></h2> <div v-show="message"> <slot> <p v-if="!dangerouslyUseHTMLString">{{ message }}</p> <p v-else v-html="message"></p> </slot> </div> <div v-if="showClose" @click.stop="close"></div> </div> </div> </transition> </template>
可以看出,这里东西不多,只有一些对应的class、关闭按钮外,就剩下title和message了,这里看到用了slot,所以我们通常也只能将自己的自定义内容放入此插槽中。
js方便就是支持大家常用的点击、关闭回调,里面维护了一个计时器来控制关闭。
我们能将它作为命令式只用的主要实现逻辑是在node-modules/element-ui/packages/notification/src/main.js里面。
这里的核心是Notification方法,这个包导出的也是它。
我们先看大家常用的 this.$message.success
方法是什么
['success', 'warning', 'info', 'error'].forEach(type => { Notification[type] = options => { if (typeof options === 'string' || isVNode(options)) { options = { message: options }; } options.type = type; return Notification(options); }; });
通过这里我们可以得知,原来平时使用的 this.$message.success
其实就是 Notification.success
,本质就是一个预先设定了 type
后再调用了 Notification
方法。
let instance; let instances = []; let seed = 1; const Notification = function(options) { if (Vue.prototype.$isServer) return; options = merge({}, options); const userOnClose = options.onClose; const id = 'notification_' + seed++; const position = options.position || 'top-right'; options.onClose = function() { Notification.close(id, userOnClose); }; instance = new NotificationConstructor({ data: options }); if (isVNode(options.message)) { instance.$slots.default = [options.message]; options.message = 'REPLACED_BY_VNODE'; } instance.id = id; instance.$mount(); document.body.appendChild(instance.$el); instance.visible = true; instance.dom = instance.$el; instance.dom.style.zIndex = PopupManager.nextZIndex(); let verticalOffset = options.offset || 0; instances.filter(item => item.position === position).forEach(item => { verticalOffset += item.$el.offsetHeight + 16; }); verticalOffset += 16; instance.verticalOffset = verticalOffset; instances.push(instance); return instance; };
上面的 NotificationConstructor
就是
import Main from './main.vue'; const NotificationConstructor = Vue.extend(Main);
使用Vue构造函数生成组件实例 instance
,这和我们默认用vue-cli生成vue项目的main.js是不是很像。
import App from './app.vue'; new Vue({ render: h => h(App), router, store: new Vuex.Store(store), }).$mount("#app");
唯一的区别是我们在 mounted
的时候没有传参数,这意味着我们需要自己将生成的dom插入目标位置,这也更符合我们的预期。
instances
数组是用来存储多个组件实例的,在垂直方向如果有多个组件实例的话,会给它们直接加入16px的偏移量避免它们重叠在一起。
这里还给每个实例更新了 verticalOffset
属性的值来记录垂直方向的偏移量,方便 positionStyle
变更,更新组件的位置。
我们同样可以看到,在移除组件的时候,需要同步变更 instances
数组里面该 instance
后面的实例对应的style样式。
Notification.close = function(id, userOnClose) { let index = -1; const len = instances.length; const instance = instances.filter((instance, i) => { if (instance.id === id) { index = i; return true; } return false; })[0]; if (!instance) return; if (typeof userOnClose === 'function') { userOnClose(instance); } instances.splice(index, 1); if (len <= 1) return; const position = instance.position; const removedHeight = instance.dom.offsetHeight; for (let i = index; i < len - 1 ; i++) { if (instances[i].position === position) { instances[i].dom.style[instance.verticalProperty] = parseInt(instances[i].dom.style[instance.verticalProperty], 10) - removedHeight - 16 + 'px'; } } };
顺便提一下, PopupManager
是element-ui里面公共的通过z-index来确保最新创建的dom永远保持在最上方不被旧的元素遮挡的机制,实现原理也很简单。
鉴于message传参的options.message支持传入vNode,所以会有针对vNode相关的判断和处理逻辑。
简单总结一下,使用Vue构造函数这种方法是常用的命令式组件的套路,类似的还有Dialog(有的组件库叫Modal)、Notice等。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 命令式与声明式——Kubernetes部署教程
- 声明式 (declarative) vs 命令式 (imperative)
- Nim 1.0 发布,命令式编程语言
- Nim 0.17.2 发布,命令式编程语言
- Nim 0.18.0 发布,命令式编程语言
- 使用配置文件对 Kubernetes 对象的命令式管理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。