为什么 Vue.js 在组件范围之外(在不同文件中)的辅助函数中更改组件 Props 时不会触发反应性?

Why Vue.js doesn't trigger reactivity when Component Props are changed in a helper function, outside of the Component scope(in a different file)?

当组件代码变得拥挤时,我更喜欢将功能移到组件之外。因此,当我将 Component Props 作为参数传递给 Component 范围之外的函数时,这是我遇到过几次的问题,作为辅助函数或 class 方法托管在不同的文件中。我的个人想法也助长了这个错误,即我应该在每个地方都使用不可变对象以获得更好的性能。

// the component file hosted in "MyComponent.vue"
<template>
  <button @click="update">Please, update!</button>
</template>

<script>
import {
  updatePrimitiveFn,
  updateLiteralObjectFn,
  updateArrayFn,
} from "../helpers.js";

export default {
  name: "MyComponent",
  data() {
    return {
      primitiveToBeUpdated: false,
      arrayToBeUpdated: [],
      literalObjectToBeUpdated: {},
    };
  },
  methods: {
    update() {
      updatePrimitiveFn(this.primitiveToBeUpdated);
      updatedLiteralObjectFn(this.literalObjectToBeUpdated);
      updateArrayFn(this.arrayToBeUpdated);
      console.log("primitiveToBeUpdated", this.primitiveToBeUpdated);
      console.log("literalObjectToBeUpdated", this.literalObjectToBeUpdated);
      console.log("arrayToBeUpdated", this.arrayToBeUpdated);
    },
  },
};
</script>
// the helpers functions hosted in "helpers.js"

export function updatePrimitiveFn(primitiveParameter) {
  primitiveParameter = true; // it will not trigger reactivity, the argument it's a primitive and for primitives JavaScript copies the argument value to the formal parameter. For arguments that are objects, JavaScript copies the pointers of these objects to the formal parameter, keeping the link between component props and formal parameters. Pointers stores the memory address where some data lives.
}
export function updateLiteralObjectFn(literalObjectParameter) {
  literalObjectParameter = { value: true }; // it will not trigger reactivity, it replaces the pointer of the received argument with a fresh new one. 
}

export function updateArrayFn(arrayToBeUpdated) {
  arrayToBeUpdated = [true]; // it will not trigger reactivity, it replaces the pointer of the received argument with a fresh new one.
}

解决方案是只将对象作为参数传递给外部函数并按如下方式改变它们:

// the helpers functions hosted in "helpers.js"

export function updatePrimitiveFn(primitiveParameter) {
  primitiveParameter = true; // it will not trigger reactivity, the argument it's a primitive and for primitives JavaScript copies the argument value to the formal parameter. For arguments that are objects, JavaScript copies the pointers of these objects to the formal parameter, keeping the link between component props and formal parameters. Pointers stores the memory address where some data lives.
}
export function updateLiteralObjectFn(literalObjectParameter) {
  literalObjectParameter.value = true; // mutation keeps pointing same object in memory
}
export function updateArrayFn(arrayToBeUpdated) {
  arrayToBeUpdated.push(true); mutation keeps pointing same object in memory
}

查看现场演示:https://codesandbox.io/s/hardcore-volhard-mf6x0?file=/src/components/MyComponent.vue:0-179

有关更多信息,可以研究主题“按值传递与按引用传递”。