我目前在我的项目中使用 vue3-tree 并尝试配置节点,我使用 pinia 将 props.filter.data 存储到父级,但我不断收到此错误:
未捕获(承诺)超出最大递归更新数。这意味着您有一个反应效应,它会改变其自身的依赖关系,从而递归地触发自身。可能的来源包括组件模板、渲染函数、更新的钩子或观察者源函数。
我的组件目前看起来像这样:
<template>
<div data-cy="filter-tree-list">
<tree
data-cy="filter-tree-list-component"
data-test="filter-tree-list"
class="flex flex-row w-full justify-start items-stretch rounded-md px-3 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300"
v-if="props.filter.data"
rowHoverBackground="#b2ffff40"
:nodes="props.filter.data"
:use-checkbox="true"
@update:nodes="onUpdate"
@nodeClick="onNodeClick"
>
</tree>
</div>
</template>
<script setup lang="ts">
import { inject, defineEmits, defineProps, ref, watch } from "vue";
import { Filter } from "../../types/common/filter";
interface Node {
id: string;
label: string;
nodes: Array<Node>;
checked?: boolean;
}
const piniaRef: unknown = inject("piniaStore");
const props = defineProps({
filter: {
type: Object as () => Filter,
required: true,
},
isReadOnly: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["filterChange"]);
const changed = ref(false);
const checkedIds = ref<string[]>([]);
const filterValueHasChanged = () => {
if (props.filter.value === "") {
clearCheckedIds(props.filter.data as unknown as Node[]);
}
};
watch(() => props.filter.value, filterValueHasChanged);
const onUpdate = (nodes: Node[]) => {
if (piniaRef && props.filter.value === undefined) return;
checkedIds.value = [];
getCheckedIds(nodes);
//vue 3 doesnt recommend changing v-model values as props, disable warning until fixed
// eslint-disable-next-line
props.filter.value =
checkedIds.value.length > 0 ? checkedIds.value.join(",") : "";
filterHasChanged();
if (piniaRef && props.filter.immediate) {
emitFilterChange();
}
};
const onNodeClick = (node: Node) => {
const checked = node.checked;
if (Array.isArray(node.nodes)) {
node.nodes.forEach((childNode) => {
childNode.checked = checked;
});
}
};
const getCheckedIds = (nodes: Node[]) => {
if (Array.isArray(nodes)) {
nodes.forEach((node) => {
if (Array.isArray(node.nodes)) {
getCheckedIds(node.nodes);
} else if (node.checked) {
checkedIds.value.push(node.id);
}
});
}
};
const clearCheckedIds = (nodes: Node[]) => {
if (Array.isArray(nodes)) {
nodes.forEach((node) => {
node.checked = false;
if (Array.isArray(node.nodes)) {
clearCheckedIds(node.nodes);
}
});
}
};
const filterHasChanged = () => {
changed.value = true;
};
const emitFilterChange = () => {
if (changed.value) {
emit("filterChange", props.filter);
changed.value = false;
}
};
</script>
此错误在生产中不断中断,导致无限重新渲染,但在开发中运行良好。我尝试将 props 放入 ref 和计算方法中,但无济于事。
非常感谢任何帮助。
我决定使用 PrimeVue treeSelect,因为 vue3-tree 库已从根本上损坏并且与最新版本的 vue 3 不兼容。 该组件允许选择和取消选择道具,这允许我选择键并将其添加到空数组中:
<template>
<div class="card flex justify-content-center">
<TreeSelect
v-model="selectedValue"
:options="nodes"
selectionMode="checkbox"
placeholder="Select Item"
class="md:w-20rem w-full"
@nodeSelect="onNodeSelect"
@nodeUnselect="onNodeUnselect"
/>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { NodeService } from './service/NodeService';
const nodes = ref(null);
const selectedValue = ref(null);
const selectedIds = ref([])
onMounted(() => {
NodeService.getTreeNodes().then((data) => (nodes.value = data));
});
const onNodeSelect = (node) => {
console.log('selected', node.key)
selectedIds.value.push(node.key)
console.log(selectedIds.value)
}
const onNodeUnselect = (node) => {
let unselectedId = node.key
console.log('unselectedId: ' , unselectedId)
selectedIds.value = selectedIds.value.filter(key => key !== unselectedId);
console.log(selectedIds.value)
}
</script>