Skip to content

Commit 2ac2717

Browse files
committed
simplify rendering logic in KonvaNode and improve tests for dynamic layer handling. close #201
1 parent 7d036b4 commit 2ac2717

File tree

3 files changed

+81
-8
lines changed

3 files changed

+81
-8
lines changed

src/components/KonvaNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export default function (componentName: string, NodeConstructor: KonvaNodeConstr
102102
});
103103

104104
const isContainer = CONTAINERS.hasOwnProperty(componentName);
105-
return () => (isContainer ? h('template', {}, slots.default?.()) : null);
105+
return () => (isContainer ? slots.default?.() : null);
106106
},
107107
});
108108
}

src/components/Stage.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ export default defineComponent({
7373

7474
onMounted(() => {
7575
if (container.value) {
76-
container.value.innerHTML = '';
7776
__konvaNode.container(container.value);
7877
}
7978
uploadKonva();

tests/index.test.ts

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ describe('Test references', () => {
6262
template: `
6363
<v-stage ref='stage' :config='stage'>
6464
<v-layer ref='layer'>
65+
<v-rect :config='{ width: 50, height: 50 }' />
66+
<v-circle :config='{ radius: 25 }' />
6567
</v-layer>
6668
</v-stage>
6769
`,
@@ -80,6 +82,13 @@ describe('Test references', () => {
8082

8183
const layer = (vm.$refs.layer as any).getNode();
8284
expect(layer instanceof Konva.Layer).to.equal(true);
85+
86+
// Shapes and containers should not create any DOM elements.
87+
// Only Konva's own content div should be in the stage container.
88+
const stageContainer = stage.container();
89+
const allDomElements = stageContainer.querySelectorAll('*');
90+
const konvaElements = stageContainer.querySelectorAll('.konvajs-content, .konvajs-content *');
91+
expect(allDomElements.length).to.equal(konvaElements.length);
8392
});
8493

8594
it('Make sure it does not draw HTML', () => {
@@ -101,13 +110,12 @@ describe('Test references', () => {
101110
});
102111

103112
const stage = (vm.$refs.stage as any).getStage();
113+
const container = stage.container();
104114

105-
setTimeout(() => {
106-
const container = stage.container();
107-
108-
expect(container.children.length).to.equal(1);
109-
// done() TODO
110-
}, 50);
115+
// Only Konva's own content div should be in the stage container.
116+
// No Vue DOM elements should leak into it.
117+
expect(container.children.length).to.equal(1);
118+
expect(container.children[0].classList.contains('konvajs-content')).to.equal(true);
111119
});
112120
});
113121

@@ -1654,6 +1662,72 @@ describe('test reconciler', () => {
16541662
`,
16551663
});
16561664
});
1665+
1666+
it('can dynamically add layers with v-for', async () => {
1667+
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {});
1668+
const { vm } = mount({
1669+
template: `
1670+
<v-stage ref='stage' :config='stage'>
1671+
<v-layer v-for='layer in layers' :key='layer.id' :config='{ name: layer.name }'>
1672+
<v-rect :config='{ width: 50, height: 50 }' />
1673+
</v-layer>
1674+
</v-stage>
1675+
`,
1676+
data() {
1677+
return {
1678+
stage: { width: 300, height: 400 },
1679+
layers: [{ id: 1, name: 'layer1' }],
1680+
};
1681+
},
1682+
});
1683+
1684+
const stage = (vm.$refs.stage as any).getStage();
1685+
expect(stage.children.length).to.equal(1);
1686+
1687+
// dynamically add a layer
1688+
vm.layers.push({ id: 2, name: 'layer2' });
1689+
await nextTick();
1690+
expect(stage.children.length).to.equal(2);
1691+
1692+
expect(consoleError).not.toHaveBeenCalled();
1693+
consoleError.mockRestore();
1694+
});
1695+
1696+
it('can toggle layers with v-if', async () => {
1697+
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {});
1698+
const { vm } = mount({
1699+
template: `
1700+
<v-stage ref='stage' :config='stage'>
1701+
<v-layer :config="{ name: 'base' }">
1702+
<v-rect :config='{ width: 50, height: 50 }' />
1703+
</v-layer>
1704+
<v-layer v-if='showExtra' :config="{ name: 'extra' }">
1705+
<v-rect :config='{ width: 50, height: 50 }' />
1706+
</v-layer>
1707+
</v-stage>
1708+
`,
1709+
data() {
1710+
return {
1711+
stage: { width: 300, height: 400 },
1712+
showExtra: false,
1713+
};
1714+
},
1715+
});
1716+
1717+
const stage = (vm.$refs.stage as any).getStage();
1718+
expect(stage.children.length).to.equal(1);
1719+
1720+
vm.showExtra = true;
1721+
await nextTick();
1722+
expect(stage.children.length).to.equal(2);
1723+
1724+
vm.showExtra = false;
1725+
await nextTick();
1726+
expect(stage.children.length).to.equal(1);
1727+
1728+
expect(consoleError).not.toHaveBeenCalled();
1729+
consoleError.mockRestore();
1730+
});
16571731
});
16581732

16591733
describe('Test plugin', () => {

0 commit comments

Comments
 (0)