如何等到模式关闭并根据单击“确定”或“取消”继续执行?
How to wait until modal is closed and continue execution based on either OK or CANCEL was clicked?
算法:
- 我发现了两个对象数组之间的区别(新的、删除的、重命名的等)。差异存储在
data[1-5]
- 基于#1,我为模态准备了一个文本摘要(文本对象)
通知用户发现了什么差异。此摘要存储在
someDataToShowInModal
.
- 当发现差异时,必须向用户显示带有摘要的模式。用户应接受(单击“确定”)或拒绝(单击“取消”)以应用更改。
问题:如何等待用户点击模式的确定或取消
按钮?
在代码中我展示了两种可能的解决方案,但不知道如何实现它们:
将模态包装到 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>
我知道如何通过确定按钮关闭模态后调用函数,但在这种情况下,有必要在 vuex 中临时保存数据[1-5],以便在被调用函数中再次选择它们,并且我想使用更简单的方法来避免它。
如果您使用的是 bsModal,则必须为两个按钮编写单独的函数绑定,直到用户单击任一按钮或单击模态框外,它将保持 open.so 将函数的其余部分放在那些关闭或确认按钮点击事件
<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();
}
我想请你做一些重构:)
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;
},
感谢这个 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"(示例名称)调用,结果打开了模态。如果我们 open/close 模式 5 次没有点击 OK 按钮,我们将观看 state.doSave
也 5 次,当第 6 次打开后点击 OK 按钮,data[1-5]
将被处理 6 次。所以,如果没有点击 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>
算法:
- 我发现了两个对象数组之间的区别(新的、删除的、重命名的等)。差异存储在
data[1-5]
- 基于#1,我为模态准备了一个文本摘要(文本对象)
通知用户发现了什么差异。此摘要存储在
someDataToShowInModal
. - 当发现差异时,必须向用户显示带有摘要的模式。用户应接受(单击“确定”)或拒绝(单击“取消”)以应用更改。
问题:如何等待用户点击模式的确定或取消 按钮?
在代码中我展示了两种可能的解决方案,但不知道如何实现它们:
将模态包装到 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>
我知道如何通过确定按钮关闭模态后调用函数,但在这种情况下,有必要在 vuex 中临时保存数据[1-5],以便在被调用函数中再次选择它们,并且我想使用更简单的方法来避免它。
如果您使用的是 bsModal,则必须为两个按钮编写单独的函数绑定,直到用户单击任一按钮或单击模态框外,它将保持 open.so 将函数的其余部分放在那些关闭或确认按钮点击事件
<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();
}
我想请你做一些重构:)
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;
},
感谢这个 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"(示例名称)调用,结果打开了模态。如果我们 open/close 模式 5 次没有点击 OK 按钮,我们将观看 state.doSave
也 5 次,当第 6 次打开后点击 OK 按钮,data[1-5]
将被处理 6 次。所以,如果没有点击 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>