vue.js - 在 SPA 上下文之外启动 Vue 模态组件
问题描述
我们正在用一些更新的表格改造一个成熟的网站。我们正在用 SPA 完全替换一些系统,而有些系统只是不保证这样做。
但是,我们需要一些系统全局模式屏幕。其中一些已被移植到 Vue 并在 SPA 中运行良好,我们希望在我们的非 SPA 页面中获得增强的交互性的好处。
因此,虽然之前我们会像这样绑定我们的事件:
$('a.newBooking').on('click', function(ev){
// code to open bootstrap modal screen, download HTML, etc.
});
我们如何启动一个组件?
我知道我在这里没有包含任何严肃的代码,但我们的模态基本上只是文档示例模态组件的修饰版本。不同的是我们没有按钮。我们希望能够从页面各处启动这些模式。
解决方案
我的意见:
对于您的模态组件:
为您的模态使用单例模式(因为基本上我们只允许同时弹出一个模态),这将使逻辑更简单。
自定义一个安装函数以将 Modals 的 Vue 实例添加到
Vue.prototype
,例如_Vue.prototype.$my = yourModals
然后按需注册您的插件,例如
Vue.use(installFunc, {plugins: [SModal, AModal, BModal]})
在您的 JQuery(或其他非 Vue)应用程序中:
将 Modals 注册到 Vue,然后创建 Vue 实例
显示或隐藏您的模态,例如
vueInstance.$my.SModal.show
下面是一个简单的演示:
Vue.config.productionTip = false
/*---Modal Plugin---*/
let vm = null // the instance for your Vue modal
let timeout = null //async/delay popup
const SModal = {
isActive: false,
show ({
delay = 500,
message = '',
customClass = 'my-modal-class'
} = {}) {
if (this.isActive) {
vm && vm.$forceUpdate()
return
}
timeout = setTimeout(() => {
timeout = null
const node = document.createElement('div')
document.body.appendChild(node)
let staticClass = ''
vm = new this.__Vue({
name: 's-modal',
el: node,
render (h) { // uses render() which is a closer-to-the-compiler alternative to templates
return h('div', {
staticClass,
'class': customClass,
domProps: {
innerHTML: message
}
})
}
})
}, delay)
this.isActive = true
},
hide () {
if (!this.isActive) {
return
}
if (timeout) {
clearTimeout(timeout)
timeout = null
} else {
vm.$destroy()
document.body.removeChild(vm.$el)
vm = null
}
this.isActive = false
},
__Vue: null,
__installed: false,
install ({ $my, Vue }) {
if (this.__installed) { return }
this.__installed = true
$my.SModal = SModal // added your SModal object to $my
this.__Vue = Vue //get the Vue constructor
}
}
/*---Modal Plugin End---*/
/*---Custom Install Function in order to manage all modals---*/
let installFunc = function (_Vue, opts = {}) {
if (this.__installed) {
return
}
this.__installed = true
const $my = {
'memo': 'I am a plugin management.'
}
if (opts.plugins) {
Object.keys(opts.plugins).forEach(key => {
const p = opts.plugins[key]
if (typeof p.install === 'function') {
p.install({ $my, Vue: _Vue })
}
})
}
_Vue.prototype.$my = $my
}
/*---Install Plugins---*/
Vue.use(installFunc, {
plugins: [SModal]
})
let globalVue = new Vue({
el: '#vue-app'
})
$('#test').on('click', 'span', function () {
globalVue.$my.SModal.isActive ? globalVue.$my.SModal.hide() : globalVue.$my.SModal.show({'message':'test', 'delay':100})
})
span {
cursor:pointer;
color:red;
}
.my-modal-class {
position:absolute;
top:50px;
left:150px;
width:200px;
height:200px;
background-color:red;
z-index:9999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="vue-app">
</div>
<div id="test">
<h3>One Example</h3>
<p><span>Hello</span>, how are you?</p>
<p>Me? I'm <span>good</span>.</p>
</div>
推荐阅读
- lua - 使用主表内的函数编辑主表内的子表
- macos - 如何挂载多个 EFI 分区?
- python - 执行 np.log() 时遇到错误“str”对象没有属性“log”
- r - 创建组内所有变量的组合
- display - 如何识别 I2C 显示控制器
- java - 如何在 Eclipse 星云中绘制时间?
- javascript - Fetch 通话挂起,没有任何响应
- sql - 如何使用 Coalesce 编写具有多个条件的 T-sql Case 语句
- python - Python multiprocessing.Process OSError:[Errno 24]打开的文件太多
- java - 如何通过让应用程序继续执行任务而无需使用 Spring 进行过多的空值检查来解决应用程序中的空指针异常