为什么 Vue 道具更改不会触发捆绑组件中的反应性?



我已经对这个问题进行了一段时间的故障排除,现在我没有什么想法了。我希望一些新鲜的眼光能给我一个更好的视角。

简而言之:我在一个组件中有几个computed属性,这些属性只有在绑定之后才对props中的更改做出反应。在绑定之前,computed属性完全按照预期工作。

以下是相关的代码。对于上下文,这是分页数据表组件的一部分。

setup(props) {
props = reactive(props);

const isNextDisabled = computed(() => props.index + props.pageSize >= props.totalSize
const rangeUpperBound = computed(() => {
let upperBound = props.index + props.pageSize;
if (upperBound > props.totalSize) {
upperBound = props.totalSize;
}
return upperBound;
});
return {
isNextDisabled,
upperBound,
}
}

我正在使用Storybook.js将这个组件作为库的一部分进行开发。我还试图模拟异步数据获取,所以我的道具最初是空值,然后我有一个setTimeout函数,它在1.5秒后从文件中加载一些数据。换句话说,我的道具肯定在更新,我希望我的computed属性会被评估两次(一次是在第一次渲染时,另一次是当它们所依赖的道具更新时(。

当我使用普通的npm run storybook命令开发组件时,一切都按预期进行。一旦超时结束,所有计算的属性都会正确更新,并且组件会正确渲染。我在捆绑组件时遇到了障碍。

我使用Vue CLI的默认配置来捆绑东西,我的命令是:

vue-cli-service build --target lib --name copper-vue src/index.js

这是src/index.js文件:

export { default as DataTable } from "./components/DataTable/DataTable";

这是我的问题:当我使用捆绑文件中的组件时,在setTimeout之后更新道具时,组件中的任何计算属性都不会更新。我已经用日志记录语句和调试器验证了计算的属性在组件首次呈现时只评估一次,而且它们似乎完全忽略了它们所依赖的道具已经更新的事实。我还在测试期间添加的watchEffect调用中验证了这一点。

我一直在测试这一点,在我的故事书故事中导入捆绑组件,而不是.vue文件中的组件,如下所示:

// Shortcut story in question:
<template>
<span>This story waits 1.5 seconds before it loads any data, as a rudimentary way to simulate async data fetching.</span>
<data-table
:data="dataSubset"
:columns="columns"
@editRow="handleEditRow"
paginate
:index="index"
:page-size="pageSize"
:total-size="totalSize"
@change-page="getNewPage"
@change-page-size="changePageSize"
/>
</template>
<script>
// This is the import to use the component from the SFC
// import DataTable  from "./DataTable.vue";
// Here's how I import the component from the bundled file which causes issues
import { DataTable } from "../../../dist/copper-vue.common";
...
</script>

其他相关细节:

  • 这个错误在Chrome和Firefox中都会发生
  • 我使用的是Vue 3.2.8,Storybook 6.3.12
  • 在2020款M1 Macbook pro上运行/捆绑

接下来我可能会尝试的事情:

  • 返回一些Vue版本,看看3.1是否有效,3.0是否有效等

我在这里做得不对的反应式API有什么问题吗?我完全弄不明白为什么在";dev";模式,而不是使用Vue CLI捆绑时。任何提示都将不胜感激。

对于其他遇到此问题的人,我在经过几天的调试后发现了这一点。

根本原因是VS代码自动为我添加了一些导入,但没有完全正确。它尝试添加这个:

import { computed } from "@vue/reactivity";

真正需要的时候:

import { computed } from "vue";

当您告诉Vue CLI构建目标是一个库时,Vue CLI准备不捆绑vue,就像我所做的那样。但是,当您开始在vue中导入特定的包(如"@vue/reactivity"(时,它无论如何都会捆绑vue

这导致我的组件和我添加的Vue应用程序有单独的东西来管理依赖关系和效果,并导致我看到的行为。

这是我最终在Vue团队中公开的问题。他们建议将其作为一项新的esint规则,所以我们将看看这是否被接受。

最新更新