如何等到模态关闭并根据单击确定或取消继续执行?
Posted
技术标签:
【中文标题】如何等到模态关闭并根据单击确定或取消继续执行?【英文标题】:How to wait until modal is closed and continue execution based on either OK or CANCEL was clicked? 【发布时间】:2019-06-29 05:11:14 【问题描述】:算法:
-
我发现两个对象数组之间的区别(什么是新的、什么是删除的、重命名的等)。差异存储在
data[1-5]
基于#1,我为模态准备了一个文本摘要(文本对象)
通知用户发现了什么不同。此摘要存储在someDataToShowInModal
。
发现差异时,必须向用户显示带有摘要的模式。用户应接受(单击确定)或拒绝(单击取消)以应用更改。
问题:如何等到用户点击模态框的 OK 或 CANCEL 按钮?
在代码中我展示了两种可能的解决方案,但不知道如何实现它们:
将模态包装到 Promise 中。
使用state.doSave
并以某种方式等待它被myModalComponent
更改。
如果用户单击“确定”,则应用更改。
下面是伪代码,显示了我尝试实现的逻辑:
state.js
modalTextSummary =
action.js
async myAction ( state )
let modalClosed
let someDataToShowInModal =
let data1 = []
let data2 = []
let data3 = []
let data4 = []
let data5 = []
// #1. Push difference to "data[1-5]"
data1.push(xyz1)
data2.push(xyz2)
data3.push(xyz3)
data4.push(xyz4)
data5.push(xyz5)
// #2. Based on data[1-5] prepare "someDataToShowInModal"
someDataToShowInModal = xyz
// #3. We change "state.modalTextSummary" and by this we open
// a Modal (because "myModalCompont" has "watch: modalTextSummary")
state.modalTextSummary = someDataToShowInModal
// #4. HOW TO WAIT UNTIL USER CLICKS Modal's "OK" or "CANCEL"?
// v1:
// something like...
modalClosed = await myModalComponent
// v2:
// I can add "state.doSave = ''" which can be
// set by "myModalComponent" to either 'OK' or 'CANCEL', but how
// in this case I can wait for state changes?
modalClosed = await state.doSave !== ''
// #5. Apply changes
if (modalCloses === 'OK')
// ... code which handles data from data[1-5]
myModalComponent.js
<script>
import mapState from 'vuex'
export default
computed:
...mapState([
'modalTextSummary'
])
,
watch:
modalTextSummary: function ()
if (this.modalTextSummary !== )
// Here I show bootstrap-vue modal
</script>
我知道一旦通过 OK 按钮关闭模态框后如何调用函数,但在这种情况下,有必要在 vuex 中临时保存数据 [1-5] 以便在被调用函数中再次选择它们,我想要使用更简单的方法来避免它。
【问题讨论】:
由于 javascript 的异步特性,您将无法真正“等待”直到模式关闭;您将不得不实现回调或一些Promise
。如果您使用的是现代 JS,您可以尝试使用 await
,但在幕后,它将使用 Promise
。
是的,我知道。这就是您可以在我的代码中找到async/await
的原因。我会澄清的。谢谢。
我明白了...我现在无法编写示例代码,但要使用Promise
,您需要将 OK/CANCEL 按钮的单击事件捕获封装在内部Promise
,点击事件本身需要调用resolve
函数。
这与我正在谈论的内容相似,但不是从某个发射器捕获事件,而是从按钮捕获事件:***.com/a/29933215/679240
【参考方案1】:
我想为您提供一些重构:)
1) 商店的操作不应该知道接口(服务器端渲染问题,...) - 不好的做法。
2) 最好将 modal 的数据存储在 modal 的父组件中。 这是一个例子: https://jsfiddle.net/yyx990803/70yyx8z2/
然后你就可以做这样的事情(伪代码):
<my-modal
v-if="showModal"
@cancel="processModalCancel"
@submit="processModalSubmit"
>
<!-- mutating-manipulations with modalData -->
</my-modal>
---
openModal()
this.showModal = true;
this.modalData = store.dispatch('prepareDataToShowInModal'); // myAction, first part
,
processModalCancel()
this.showModal = false;
this.modalData = null;
,
processModalSubmit()
this.showModal = false;
store.dispatch('saveModalData', this.modalData); // myAction, second part
this.modalData = null;
,
【讨论】:
1.我不需要 s-s-r,至少在不久的将来。 2. 好像漏了// ... code which handles data from data[1-5]
。这里的关键部分是data[1-5]
(即在第一部分我发现了一个差异,然后我向用户展示了这个差异,在第二部分我处理来自data1、data2 等的数据)。如我所见,如果使用您的代码,我需要在第一步将临时 data[1-5]
存储在某处,并在第二步获得访问权限。
store.dispatch('saveModalData', this.modalData);
处理您的数据[]。您可以从 prepareDataToShowInModal
返回所需的值 -> 将其存储在 this.modalData
-> 并通过 saveModalData
保存到存储。【参考方案2】:
如果您使用 bsModal,您必须为两个按钮编写单独的函数绑定,直到用户单击任一按钮或单击模态外部,它将保持打开状态。因此,将函数的其余部分放在关闭或确认按钮单击事件中
<button (click)="confirm()"></button>
<button (click)="Cancel()"></button>
import BsModalRef from 'ngx-bootstrap';
constructor()public modalRef: BsModalRef
confirm()
//do anything
this.modalRef.close();
Cancel()
//do anything
this.modalRef.close();
【讨论】:
我关于 VueJs 的问题,而不是关于 Angular 的问题(您可能会在此处被否决)。但是,我理解您试图向我展示的内容,但这并不能解决我的问题。【参考方案3】:感谢post,找到了如何通过 v2 实现它的方法。
gleam 的答案更简洁明了,因此您应该更喜欢他的解决方案。我下面的解决方案仅出于教育目的发布。
state.js
modalTextSummary =
doSave = false
action.js
// My 'store' file is at the root. Where is yours - I do not know :)
import store from '@/store'
async myAction ( state )
state.doSave = false
let modalClosed
let someDataToShowInModal =
let data1 = []
let data2 = []
let data3 = []
let data4 = []
let data5 = []
// #1. Push difference to "data[1-5]"
data1.push(xyz1)
data2.push(xyz2)
data3.push(xyz3)
data4.push(xyz4)
data5.push(xyz5)
// #2. Based on data[1-5] prepare "someDataToShowInModal"
someDataToShowInModal = xyz
// #3. We change "state.modalTextSummary" and by this we open
// a Modal (because "myModalCompont" has "watch: modalTextSummary")
state.modalTextSummary = someDataToShowInModal
// #4. Wait until user closes modal or clicks OK
const unwatch = store.watch(
(state) => state.doSave,
(value) =>
// #5. Apply changes
if (value === true)
unwatch()
// ... code which handles data from data[1-5]
else if (value === 'unwatch')
unwatch()
)
为什么我们需要unwatch()
?
在我的情况下,myAction
由“someButton”(示例名称)调用,结果打开了模式。如果我们在没有点击 OK 按钮的情况下打开/关闭 modal 5 次,我们也会观看 state.doSave
5 次,当第 6 次打开 OK 按钮后,data[1-5]
将被处理 6 次。所以,如果modal在没有点击OK按钮的情况下关闭,我们需要取消关注state.doSave
。
myModalComponent.js
<template>
<b-modal
ref="myModal"
ok-title="OK"
cancel-title="Close"
@keydown.native.enter="closeModalAndSave"
@ok="closeModalAndSave"
@hide="closeModalAndUnwatch"
>
modalTextSummary
</b-modal>
</template>
<script>
import mapState, mapMutations from 'vuex'
export default
computed:
...mapState([
'modalTextSummary'
])
,
watch:
modalTextSummary: function ()
if (this.modalTextSummary !== )
this.$refs.myModal.show()
,
methods:
...mapMutations('media', [
'doSave'
]),
closeModalAndUnwatch (bvEvent)
// "this.$refs.myModal.hide()" fires @hide with "bvEvent.trigger === null".
// We need to 'unwatch' just when bvEvent.trigger === 'cancel' or 'backdrop',
// or 'header-close', ie not null.
if (bvEvent.trigger !== null)
this.doSave('unwatch')
,
closeModalAndSave ()
this.doSave(true)
this.$refs.myModal.hide()
// End of "methods"
</script>
【讨论】:
以上是关于如何等到模态关闭并根据单击确定或取消继续执行?的主要内容,如果未能解决你的问题,请参考以下文章
知道何时在 Apple Watch 模态界面控制器中单击取消按钮