本文介绍Vue2与Vue3中动态弹窗组件的实现方法,包括Vue.extend与$mount的使用,以及Vue3中createVNode和render函数的应用。
Vue2实现主要思路
- Vue.extend+$mount将组件挂载
- install插件化挂到实例原型上面
/plugins/Tip.js
import Vue from "vue";
import TipComponent from "@/components/Tip.vue";
const TipConstructor = Vue.extend(TipComponent);
const activeInstances = [];
const baseOffset = 20;
const gap = 10;
function calcOffset() {
let offset = baseOffset;
activeInstances.forEach((instance) => {
const el = instance.$el;
const height = el ? el.offsetHeight : 0;
offset += height + gap;
});
return offset;
}
function createTip({
message = "",
type = "info",
duration = 2000,
closable = false,
zIndex = 3000,
} = {}) {
//实例化构造函数
const instance = new TipConstructor({
propsData: {
message,
type,
duration,
closable,
zIndex,
},
});
// 挂载实例挂在dom到$el
instance.$mount();
document.body.appendChild(instance.$el);
instance.offset = calcOffset();
instance.onClose = () => {
const idx = activeInstances.indexOf(instance);
if (idx > -1) activeInstances.splice(idx, 1);
// 重新计算tips的偏移量
for (let i = idx; i < activeInstances.length; i++) {
const cur = activeInstances[i];
const prevEl = i === 0 ? null : activeInstances[i - 1].$el;
const top =
i === 0
? baseOffset
: prevEl
? prevEl.offsetTop + prevEl.offsetHeight + gap
: baseOffset;
cur.offset = top;
}
};
activeInstances.push(instance);
Vue.nextTick(() => instance.open());
return instance;
}
function mountToPrototype(app) {
app.prototype.$tip = (options) => createTip(options);
["success", "warning", "error", "info"].forEach((t) => {
app.prototype.$tip[t] = (msg, opts = {}) =>
createTip({ message: msg, type: t, ...opts });
});
}
export default {
install(app) {
mountToPrototype(app);
},
};
export { createTip };
2022/9/18大约 2 分钟