Skip to content

Commit

Permalink
fix(tree): tree 组件,解决 watch 回调时间过迟的问题 (#2873)
Browse files Browse the repository at this point in the history
* fix(tree): tree 组件,解决 watch 回调时间过迟的问题

* style(tree): tree 组件,代码样式改进

* test(tree): tree 组件,完善单元测试,验证 mounted 赋值可在 nextTick 触发数据变更
  • Loading branch information
TabSpace authored Oct 24, 2023
1 parent 25d840c commit 21244bf
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 30 deletions.
62 changes: 61 additions & 1 deletion src/tree/__tests__/api.test.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import Tree from '@/src/tree/index.ts';
import { delay } from './kit';
import { delay, step } from './kit';

describe('Tree:api', () => {
vi.useRealTimers();
Expand Down Expand Up @@ -123,6 +123,66 @@ describe('Tree:api', () => {
expect(wrapper.find('[data-value="t1"]').text()).toBe('节点1');
});

it('mounted 生命周期初始化数据, 在 nextTick 触发视图更新', async () => {
const data = [
{
value: 't1',
children: [
{
value: 't1.1',
},
],
},
{
value: 't2',
children: [
{
value: 't2.1',
},
],
},
];

const step1 = step();
let count = 0;
const wrapper = mount({
data() {
return {
items: [],
checked: [],
};
},
mounted() {
this.items = data;
this.onInit();
},
methods: {
onInit() {
const { tree } = this.$refs;
this.$nextTick(() => {
tree.setItem('t1', {
checked: true,
});
const items = tree.getItems();
count = items.length;
step1.ready();
});
},
},
render() {
return <Tree ref="tree" expandAll checkable transition={false} data={this.items} v-model={this.checked} />;
},
});

await step1;
await delay(1);
expect(wrapper.find('[data-value="t1"] .t-checkbox').classes('t-is-checked')).toBe(true);
expect(wrapper.find('[data-value="t1.1"] .t-checkbox').classes('t-is-checked')).toBe(true);
expect(wrapper.find('[data-value="t2"] .t-checkbox').classes('t-is-checked')).toBe(false);
expect(wrapper.find('[data-value="t2.1"] .t-checkbox').classes('t-is-checked')).toBe(false);
expect(count).toBe(4);
});

it('可以设置节点属性 checked, 触发视图更新', async () => {
const data = [
{
Expand Down
31 changes: 3 additions & 28 deletions src/tree/hooks/useTreeStore.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import pick from 'lodash/pick';
import { TreeStore } from '../../_common/js/tree/tree-store';
import { watch } from '../adapt';
import {
TreeProps,
TreeNodeValue,
TypeValueMode,
TypeEventState,
TypeTreeNodeModel,
Expand All @@ -21,7 +19,6 @@ export default function useTreeStore(state: TypeTreeState) {
filter,
});

const { refProps } = state;
const [tValue] = state.vmValue;
const [tActived] = state.vmActived;
const [tExpanded] = state.vmExpanded;
Expand Down Expand Up @@ -137,6 +134,7 @@ export default function useTreeStore(state: TypeTreeState) {

const rebuild = (list: TreeProps['data']) => {
store.reload(list || []);
store.refreshNodes();
// 初始化选中状态
if (Array.isArray(tValue.value)) {
store.setChecked(tValue.value);
Expand Down Expand Up @@ -185,33 +183,10 @@ export default function useTreeStore(state: TypeTreeState) {
// 设置初始化状态
state.setStore(store);

// 配置属性监听
// tValue 就是 refProps.value
watch(tValue, (nVal: TreeNodeValue[]) => {
store.replaceChecked(nVal);
});
// tExpanded 就是 refProps.expanded
watch(tExpanded, (nVal: TreeNodeValue[]) => {
store.replaceExpanded(nVal);
});
// tActived 就是 refProps.actived
watch(tActived, (nVal: TreeNodeValue[]) => {
store.replaceActived(nVal);
});
watch(refProps.data, (list) => {
rebuild(list);
});
watch(refProps.filter, (nVal, previousVal) => {
checkFilterExpand(nVal, previousVal);
});
watch(refProps.keys, (keys) => {
store.setConfig({
keys,
});
});

return {
store,
rebuild,
checkFilterExpand,
updateStoreConfig,
updateExpanded,
expandFilterPath,
Expand Down
31 changes: 30 additions & 1 deletion src/tree/tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,31 @@ export default defineComponent({
...props,
},

watch: {
// 实测发现,composition api 中的 refsProps watch ,回调时间迟于 $nextTick 回调
// 因此改为在这里绑定属性监听,实测这里的 watch 回调,早于 $nextTick 回调发生
data(list) {
this.rebuild(list);
},
value(nVal: TreeNodeValue[]) {
this.store.replaceChecked(nVal);
},
expanded(nVal: TreeNodeValue[]) {
this.store.replaceExpanded(nVal);
},
actived(nVal: TreeNodeValue[]) {
this.store.replaceActived(nVal);
},
filter(nVal, previousVal) {
this.checkFilterExpand(nVal, previousVal);
},
keys(keys) {
this.store.setConfig({
keys,
});
},
},

setup(props, context) {
const { t, global } = useConfig('tree');
const classPrefix = usePrefixClass();
Expand All @@ -50,7 +75,9 @@ export default defineComponent({
// 用于 hooks 传递数据
const { state } = useTreeState(props, context);
const { treeContentRef, isScrolling } = state;
const { store, updateStoreConfig } = useTreeStore(state);
const {
store, updateStoreConfig, rebuild, checkFilterExpand,
} = useTreeStore(state);

useDragHandle(state);
const { setActived, setExpanded, setChecked } = useTreeAction(state);
Expand All @@ -72,6 +99,8 @@ export default defineComponent({
treeClasses,
treeContentRef,

rebuild,
checkFilterExpand,
updateStoreConfig,
setActived,
setExpanded,
Expand Down

0 comments on commit 21244bf

Please sign in to comment.