如何使用 vue 编写一个显示模态弹出窗口的插件.调用应作为函数()进行



我正在尝试制作一个 VueJS 插件,该插件导出一个全局方法,当调用时,将弹出一条带有输入文本字段的消息。理想情况下,我希望能够从任何 Vue 组件进行以下调用:

this.$disaplayMessageWithInput("Title","Body","Value");

屏幕上应该会出现一个弹出窗口。

我尝试构建它,但是当 install(( 调用 this.$ref. 时,它无法识别:

删除确认.vue

<template>
<b-modal size="lg" ref="deleteConfirmationModal" :title="this.title" header-bg-variant="danger" @ok="confirmDelete" @cancel="confirmCancel">
<p>
{{this.body}}
</p>
</b-modal>
</template>
<script>
export default {
data()
{
return {
title: null,
body: null,
valueCheck: null,
value: null
};
},
install(vue, options)
{
Vue.prototype.$deleteConfirmation = function(title, body, expectedValue)
{
this.title = title;
this.body = body;
this.valueCheck = expectedValue;
this.$refs.$deleteConfirmation.show()
}
},
}
</script>

应用.js

import DeleteConfirmation from './components/global/DeleteConfirmation/DeleteConfirmation';
Vue.use(DeleteConfirmation);

我试图打的电话是:

$vm0.$deleteConfirmation("title","body","val");

我在运行时收到以下错误:

app.js?id=c27b2799e01554aae7e1:33 Uncaught TypeError: Cannot read property 'show' of undefined
at Vue.$deleteConfirmation (app.js?id=c27b2799e01554aae7e1:33)
at <anonymous>:1:6
Vue.$deleteConfirmation @ app.js?id=c27b2799e01554aae7e1:33
(anonymous) @ VM1481:1

看起来,DeleteConfirmation.vue 中的this.$refs是未定义的。

尽量避免使用 vue $ref($ref 这里是针对第三方和一些非常特殊的情况$ref
不是反应性的,而是在渲染后填充的......

对我来说,最好的解决方案是使用这样的事件总线:

const EventBus = new Vue({
name: 'EventBus',
});
Vue.set(Vue.prototype, '$bus', EventBus);

然后使用事件总线调用模态的功能...

(this.$bus.on('event-name', callback)/this.$bus.off('event-name');this.$bus.$emit('event-name', payload);)


您可以像我一样围绕引导模式创建一个小包装器 ( 除 A 使用甜蜜模态(

<template>
<div>
<sweet-modal
:ref="modalUid"
:title="title"
:width="width"
:class="klass"
class="modal-form"
@open="onModalOpen"
@close="onModalClose"
>
<slot />
</sweet-modal>
</div>
</template>
<script>
export default {
name: 'TModal',
props: {
eventId: {
type: String,
default: null,
},
title: {
type: String,
default: null,
},
width: {
type: String,
default: null,
},
klass: {
type: String,
default: '',
},
},
computed: {
modalUid() {
return `${this._uid}_modal`; // eslint-disable-line no-underscore-dangle
},
modalRef() {
return this.$refs[this.modalUid];
},
},
mounted() {
if (this.eventId !== null) {
this.$bus.$on([this.eventName('open'), this.eventName('close')], this.catchModalArguments);
this.$bus.$on(this.eventName('open'), this.modalRef ? this.modalRef.open : this._.noop);
this.$bus.$on(this.eventName('close'), this.modalRef ? this.modalRef.close : this._.noop);
}
},
beforeDestroy() {
if (this.eventId !== null) {
this.$off([this.eventName('open'), this.eventName('close')]);
}
},
methods: {
onModalOpen() {
this.$bus.$emit(this.eventName('opened'), ...this.modalRef.args);
},
onModalClose() {
if (this.modalRef.is_open) {
this.$bus.$emit(this.eventName('closed'), ...this.modalRef.args);
}
},
eventName(action) {
return `t-event.t-modal.${this.eventId}.${action}`;
},
catchModalArguments(...args) {
if (this.modalRef) {
this.modalRef.args = args || [];
}
},
},
};
</script>
<style lang="scss" scoped>
/deep/ .sweet-modal {
.sweet-title > h2 {
line-height: 64px !important;
margin: 0 !important;
}
}
</style>

AppModal.vue

<template>
<div class="modal-wrapper" v-if="visible">
<h2>{{ title }}</h2>
<p>{{ text }}</p>
<div class="modal-buttons">
<button class="modal-button" @click="hide">Close</button>
<button class="modal-button" @click="confirm">Confirm</button>
</div>
</div>
</template>

<script>
export default {
data() {
return {
visible: false, 
title: '',
text: ''
}
},
methods: {
hide() {
this.visible = false;
},
}
}
</script>

模态.js(插件(

import AppModal from 'AppModal.vue'
const Modal = {
install(Vue, options) {
this.EventBus = new Vue()
Vue.component('app-modal', AppModal)
Vue.prototype.$modal = {
show(params) {
Modal.EventBus.$emit('show', params)
}
}
}
}
export default Modal

主.js

import Modal from 'plugin.js'
// ...
Vue.use(Modal)

App.vue

<template>
<div id="app">
// ... 
<app-modal/>
</div>
</template>

这看起来很复杂。为什么不使用像这样的即用型弹出组件?https://www.npmjs.com/package/@soldeplata/popper-vue

最新更新