如何等待直到模式关闭,然后再单击“确定”或“取消”才能继续执行?

时间:2019-02-05 11:32:23

标签: javascript vuejs2 bootstrap-4 vuex bootstrap-vue

算法:

  1. 我发现了两个对象数组之间的区别(什么是新的,什么被删除,重命名等)。差异存储在data[1-5]
  2. 基于#1,我准备了一个文本摘要(文本对象),用于 通知用户发现了什么区别。此摘要存储在someDataToShowInModal中。
  3. 找到差异后,必须向用户显示带有摘要的模态。用户应接受(单击确定)或拒绝(单击取消)以应用更改。
  4. 问题:如何等待用户单击模式的“确定”或“取消” 按钮?

    在代码中,我展示了两种可能的解决方案,但不知道如何实现它们:

    1. 将模式包装到Promise中。

    2. 使用state.doSave,然后以某种方式等待myModalComponent对其进行更改。

  5. 如果用户单击“确定”,则应用更改。

下面是伪代码,显示了我尝试实现的逻辑:

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],以便在调用的函数中再次选择它们。避免使用更简单的方法。

3 个答案:

答案 0 :(得分:2)

我想为您提供一些重构方法:)

1)存储区的操作不应该知道接口(服务器端呈现问题,...)-不良做法。

2)最好将模态的数据存储在模态的父组件中。 这是一个例子: 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 :(得分:0)

如果您正在使用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();
}

答案 2 :(得分:0)

借助此post,找到了通过v2实现该方法的方法。

微光的答案更短,更清晰,因此您应该选择他的解决方案。我的以下解决方案仅出于教育目的而发布。

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”(示例名称)调用,结果打开了模式。如果在没有单击“确定”按钮的情况下打开/关闭模式5次,我们还将观看state.doSave 5次,并且在第六次打开确定按钮之后,单击data[1-5]将被处理6次。因此,如果在未单击“确定”按钮的情况下关闭了模式对话框,则需要取消监视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>