为什么 Vue 道具更改不会触发我的捆绑组件中的反应性?
Why aren't Vue prop changes triggering reactivity in my bundled component?
我已经解决这个问题一段时间了,但我 运行 没有想法。我希望一些新鲜的眼睛能给我一个更好的视角。
简而言之:我在一个组件中有几个 computed
属性,这些属性仅在捆绑 之后才对 props 的变化做出反应 。在捆绑之前,computed
属性完全按预期工作。
这是相关的代码。对于上下文,这是分页数据 table 组件的一部分。
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
属性被评估两次(第一次渲染时,当它们依赖的道具被更新时再次评估)。
当我使用 vanilla 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";
这是我的问题: 当我使用组件 来自组件中计算属性的捆绑文件 none在 setTimeout 之后更新道具时会更新。我已经使用日志记录语句和调试器验证了计算属性仅在组件首次呈现时计算一次,并且它们似乎完全忽略了它们所依赖的道具已更新的事实。我还通过我在测试期间添加的 watchEffect
调用验证了这种情况。
我一直在通过导入捆绑组件而不是我的 .vue
文件中的组件来测试它,在我的 Storybook 故事中是这样的:
// 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
- Running/bundling 2020 M1 Macbook pro
接下来我可能会尝试的事情:
- 回顾一些 Vue 版本以查看 3.1 是否有效、3.0 是否有效等
关于响应式 API,我在这里做错了什么吗?我完全不明白为什么当 运行 处于“开发”模式时事情会按预期工作,而不是使用 Vue CLI 捆绑时。任何提示表示赞赏。
对于遇到此问题的任何其他人,我经过几天的调试后发现了这一点。
根本原因是 VS Code 自动为我添加了一些导入,但没有完全正确。它尝试添加这个:
import { computed } from "@vue/reactivity";
真正需要的时候:
import { computed } from "vue";
当您告诉 Vue CLI 构建目标是一个库时,Vue CLI 准备好不捆绑 vue
,就像我所做的那样。但是,当您开始在 vue
中导入特定包时,例如 "@vue/reactivity"
,那么它无论如何都会捆绑 vue
。
这导致我的组件和我添加它们的 Vue 应用程序具有单独的事物来管理依赖项和效果,并导致我看到的行为。
Here's the issue 我最终选择了 Vue 团队。他们建议将其作为新的 eslint 规则提出,所以我们将看看它是否被接受。
我已经解决这个问题一段时间了,但我 运行 没有想法。我希望一些新鲜的眼睛能给我一个更好的视角。
简而言之:我在一个组件中有几个 computed
属性,这些属性仅在捆绑 之后才对 props 的变化做出反应 。在捆绑之前,computed
属性完全按预期工作。
这是相关的代码。对于上下文,这是分页数据 table 组件的一部分。
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
属性被评估两次(第一次渲染时,当它们依赖的道具被更新时再次评估)。
当我使用 vanilla 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";
这是我的问题: 当我使用组件 来自组件中计算属性的捆绑文件 none在 setTimeout 之后更新道具时会更新。我已经使用日志记录语句和调试器验证了计算属性仅在组件首次呈现时计算一次,并且它们似乎完全忽略了它们所依赖的道具已更新的事实。我还通过我在测试期间添加的 watchEffect
调用验证了这种情况。
我一直在通过导入捆绑组件而不是我的 .vue
文件中的组件来测试它,在我的 Storybook 故事中是这样的:
// 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
- Running/bundling 2020 M1 Macbook pro
接下来我可能会尝试的事情:
- 回顾一些 Vue 版本以查看 3.1 是否有效、3.0 是否有效等
关于响应式 API,我在这里做错了什么吗?我完全不明白为什么当 运行 处于“开发”模式时事情会按预期工作,而不是使用 Vue CLI 捆绑时。任何提示表示赞赏。
对于遇到此问题的任何其他人,我经过几天的调试后发现了这一点。
根本原因是 VS Code 自动为我添加了一些导入,但没有完全正确。它尝试添加这个:
import { computed } from "@vue/reactivity";
真正需要的时候:
import { computed } from "vue";
当您告诉 Vue CLI 构建目标是一个库时,Vue CLI 准备好不捆绑 vue
,就像我所做的那样。但是,当您开始在 vue
中导入特定包时,例如 "@vue/reactivity"
,那么它无论如何都会捆绑 vue
。
这导致我的组件和我添加它们的 Vue 应用程序具有单独的事物来管理依赖项和效果,并导致我看到的行为。
Here's the issue 我最终选择了 Vue 团队。他们建议将其作为新的 eslint 规则提出,所以我们将看看它是否被接受。