javascript VueJS更新属性延迟

xtfmy6hx  于 2023-01-16  发布在  Java
关注(0)|答案(2)|浏览(172)

我有一个简单的组件,比如Transaction.vue,在它里面有一个名为TransactionEditModal.vue的子组件。
在Transaction. vue组件中,我通过单击按钮调用方法"openTransactionEditModal",方法的流程是,在使用"showModal()"打开模态之前,我首先编辑我的子属性"this. chosenTransactionId"。

// Transaction.vue
<button ref="editTransactionButton" v-on:click="openTransactionEditModal($event)" class="btn btn-primary">
    <i style="pointer-events: none" class="far fa-edit"></i>
</button>
<TransactionEditModal ref="transactionEditModal" v-bind:transactionId="chosenTransactionId" />
<script>
  data: function () {
     return {
        chosenTransactionId: "",
     }
  }
  methods: {
    openTransactionEditModal(event: MouseEvent) {
        if (event.currentTarget instanceof HTMLButtonElement) {
           this.chosenTransactionId = event.currentTarget.id;
           console.log("Chosen Transaction Id is Updated", event.currentTarget.id);
        }
        var transactionEditModal: any = this.$refs.transactionEditModal;         transactionEditModal.initializeExistingValues(this.transactions[6]);
        transactionEditModal.showModal();
    }
  }
</script>
// TransactionEditModal.vue

<script>
  props: {
     transactionId: String,
  },
  methods: {
    showModal() {
      console.log("Child component props should have been updated, is it? ", this.transactionId);
      var reportApproveModal: JQuery<HTMLDivElement> = $('#transactionEditModal');
      reportApproveModal.modal('show');
    },
  }
</script>

但是为什么 prop 只有在第二次点击后才更新呢?
结果:
一个二个一个一个

更新1

在子组件中使用监视功能后,我得到以下结果:

Chosen Transaction Id is Updated 5aa1dfc7-4b2f-4dbe-911f-98d70a2624f2 Transaction.vue:365 
Child component props should have been updated, is it? TransactionEditModal.vue:36  
Means updated after watch 5aa1dfc7-4b2f-4dbe-911f-98d70a2624f2 TransactionEditModal.vue:42

我推断它是在调用showModal()之后更新的,我实际上发现这很奇怪,也许更新 prop 是异步的?

// TransactionEdit.vue
<script>
  watch: {
      transactionId(newVal, oldVal) {
      console.log('Means updated after watch', newVal, oldVal);
    },
  },
</script>
nnt7mjpx

nnt7mjpx1#

之所以要在第二次点击后才更新props,是因为Vue使用了异步更新队列来更新组件,也就是说当你在openTransactionEditModal方法中更新props的时候,并不是立即生效,而是加入到更新队列中,在当前事件循环之后进行处理,当你第一次点击按钮的时候,更新props并添加到更新队列中,但是在更新之前调用了showModal方法,所以子组件仍然有旧的props,第二次点击按钮时,更新已经被处理并且子组件现在具有更新的 prop 。使用子组件中的监视功能,您可以检查 prop 的更新值以及更新的确切时间。
您可以重构代码以确保子组件在调用showModal方法之前接收到更新的props:

// Transaction.vue
<button v-on:click="openTransactionEditModal($event)" class="btn btn-primary">
    <i class="far fa-edit"></i>
</button>
<TransactionEditModal v-bind:transactionId="chosenTransactionId" @modal-open="showModal" ref="transactionEditModal" />

<script>
  data: function () {
     return {
        chosenTransactionId: "",
     }
  },
  methods: {
    openTransactionEditModal(event: MouseEvent) {
        if (event.currentTarget instanceof HTMLButtonElement) {
           this.chosenTransactionId = event.currentTarget.id;
        }
        this.$nextTick(() => {
          this.$refs.transactionEditModal.initializeExistingValues(this.transactions[6]);
          this.$refs.transactionEditModal.$emit('modal-open');
        });
    },
    showModal() {
      var reportApproveModal: JQuery<HTMLDivElement> = $('#transactionEditModal');
      reportApproveModal.modal('show');
    },
  }
</script>

// TransactionEditModal.vue
<script>
  props: {
     transactionId: String,
  },
</script>

我添加了一个自定义事件'modal-open',它在更新chosenTransactionId后从父组件发出,并触发showModal()方法。这样,我们可以确保子组件在打开模态之前已经接收到更新的props。
此外,我还将initializeExistingValues()$emit('modal-open')函数 Package 在this.$nextTick(() =>{})中,以确保在调用该函数之前已经更新了值。
此外,我还删除了不必要的ref属性和HTMLButtonElement的类型转换。

wgmfuz8q

wgmfuz8q2#

是否确定已设置正确的transactionIdReact?

Transaction.vue中,您定义了一个名为transactionId的无功变量。
但是在该组件的代码中,您引用了名为chosenTransactionId的变量。
我建议您将其合理化为两者都只有transactionId
或者,如果您确实需要两个单独的变量,则将chosenTransationId添加到Transaction.vue中的data函数。

一旦设置了transactionId,只允许modal存在怎么样?

你可以改变

<TransactionEditModal ref="transactionEditModal" v-bind:transactionId="chosenTransactionId" />

<TransactionEditModal 
    v-if="chosenTransactionId" 
    ref="transactionEditModal" 
    v-bind:transactionId="chosenTransactionId" 
/>

这是一种更传统的方法,你甚至可以用一个v-bind参数把初始化信息发送给子组件,这样父组件就不必直接调用Modal中的函数了。
一般来说,最好避免在子节点中调用函数的模式,相反,只有当所有必要的信息都可用并准备好传递给子节点时,才让子节点存在(使用v-if)。

相关问题