为什么在调用this.$emit()后,Vue2中的props不会立即更新?

huangapple go评论76阅读模式
英文:

Why props is not updated instantly after call this.$emit() in Vue2?

问题

I'm curious that why the prop is not updated after call this.$emit() immediately? Instead, the updated value only can be obtained after some delay (such as in the this.$nextTick()).

The following code show the example, after click and execute the updateString function, the first console.log still print the initial empty string(""), but in the $nextTick() block, the latest updated string ("a new string") can be obtained.

I haven't found any reference relative to this problem in vue official doc, if someone can provide it, I would be very grateful, thanks.

英文:

I'm curious that why the prop is not updated after call this.$emit() immediately? Instead, the updated value only can be obtained after some delay (such as in the this.$nextTick()).

The following code show the example, after click and execute the updateString function, the first console.log still print the initial empty string(""), but in the $nextTick() block, the latest updated string ("a new string") can be obtained.

I haven't found any reference relative to this problem in vue official doc, if someone can provide it, I would be very grateful, thanks.

codesandbox

Parent.vue

<template>
  <div id="parent">
    <UpdateProps :string="string" @update-string="updateString" />
  </div>
</template>

<script>
import UpdateProps from "./UpdateProps";

export default {
  name: "Parent",
  components: {
    UpdateProps,
  },
  data() {
    return {
      string: "",
    };
  },
  methods: {
    updateString(newString) {
      this.string = newString;
    },
  },
};
</script>

Child.vue

<template>
  <div @click="updateString">update string</div>
</template>

<script>
export default {
  name: "Child",
  props: {
    string: String,
  },
  emits: ["update-string"],
  methods: {
    updateString() {
      this.$emit("update-string", "a new string");
      console.log("updateString currently: ", this.string); // will print ""

      this.$nextTick(() => {
        console.log("updateString in $nextTick: ", this.string); // will print "a new string"
      });
    },
  },
};
</script>

答案1

得分: 2

以下是事件顺序的说明:

  1. 发出更新事件
  2. 父组件的值被更新,父组件标记为已更改
  3. 在子组件中,函数在将第一条语句打印到控制台并注册回调到nextTick后完成
  4. Vue 检查已更改的内容并更新虚拟 DOM,这种情况下是与子组件的数据绑定
  5. 更新 DOM(在此情况下没有更改)
  6. 运行nextTick的回调,打印已更新的 prop 值

因此,Vue 在更新与子组件的数据绑定之前等待当前操作完成。这允许一次性处理所有更改,这更加高效。DOM 更新时机在响应性基础知识部分中有描述:

当您更改响应式状态时,DOM 会自动更新。但应注意,DOM 更新不会同步应用。相反,Vue 会将它们缓冲到更新周期中的“下一个刻度”以确保每个组件只更新一次,无论您已经进行了多少次状态更改。

英文:

Here is the order of events:

  1. The update event is emitted
  2. The value in the parent is updated and parent is marked as changed
  3. In the child, the function finishes after printing the first statement to console and registering the callback to nextTick
  4. Vue checks what has changed and updates the virtual DOM, in this case the data binding to the child
  5. DOM is updated (no changes in this case)
  6. The callback to nextTick is run, printing the updated prop value

So Vue waits until the current operation has finished before updating the data binding to the child. This allows to process all changes together, which is more efficient. DOM update timing is described in the reactivity fundamentals section:
>When you mutate reactive state, the DOM is updated automatically. However, it should be noted that the DOM updates are not applied synchronously. Instead, Vue buffers them until the "next tick" in the update cycle to ensure that each component updates only once no matter how many state changes you have made.

huangapple
  • 本文由 发表于 2023年8月10日 18:41:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76874967.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定