mirror of
https://github.com/withastro/astro.git
synced 2024-12-30 22:03:56 -05:00
fix(vue): useId() collisions (#12112)
This commit is contained in:
parent
34d79527a4
commit
f9dd9428c6
7 changed files with 60 additions and 1 deletions
5
.changeset/beige-students-compete.md
Normal file
5
.changeset/beige-students-compete.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/vue': patch
|
||||
---
|
||||
|
||||
Fixes a case where IDs generated by `useId()` (introduced in Vue 3.5) would not be unique between islands
|
|
@ -40,6 +40,7 @@ export default (element) =>
|
|||
return content;
|
||||
},
|
||||
});
|
||||
app.config.idPrefix = element.getAttribute('prefix');
|
||||
await setup(app);
|
||||
app.mount(element, isHydrate);
|
||||
appMap.set(element, appInstance);
|
||||
|
|
24
packages/integrations/vue/context.js
Normal file
24
packages/integrations/vue/context.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
const contexts = new WeakMap();
|
||||
|
||||
const ID_PREFIX = 'v';
|
||||
|
||||
function getContext(rendererContextResult) {
|
||||
if (contexts.has(rendererContextResult)) {
|
||||
return contexts.get(rendererContextResult);
|
||||
}
|
||||
const ctx = {
|
||||
currentIndex: 0,
|
||||
get id() {
|
||||
return ID_PREFIX + this.currentIndex.toString();
|
||||
},
|
||||
};
|
||||
contexts.set(rendererContextResult, ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export function incrementId(rendererContextResult) {
|
||||
const ctx = getContext(rendererContextResult);
|
||||
const id = ctx.id;
|
||||
ctx.currentIndex++;
|
||||
return id;
|
||||
}
|
|
@ -2,12 +2,19 @@ import { setup } from 'virtual:@astrojs/vue/app';
|
|||
import { createSSRApp, h } from 'vue';
|
||||
import { renderToString } from 'vue/server-renderer';
|
||||
import StaticHtml from './static-html.js';
|
||||
import { incrementId } from './context.js';
|
||||
|
||||
function check(Component) {
|
||||
return !!Component['ssrRender'] || !!Component['__ssrInlineRender'];
|
||||
}
|
||||
|
||||
async function renderToStaticMarkup(Component, inputProps, slotted, metadata) {
|
||||
let prefix;
|
||||
if (this && this.result) {
|
||||
prefix = incrementId(this.result);
|
||||
}
|
||||
const attrs = { prefix };
|
||||
|
||||
const slots = {};
|
||||
const props = { ...inputProps };
|
||||
delete props.slot;
|
||||
|
@ -21,9 +28,10 @@ async function renderToStaticMarkup(Component, inputProps, slotted, metadata) {
|
|||
});
|
||||
}
|
||||
const app = createSSRApp({ render: () => h(Component, props, slots) });
|
||||
app.config.idPrefix = prefix;
|
||||
await setup(app);
|
||||
const html = await renderToString(app);
|
||||
return { html };
|
||||
return { html, attrs };
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
|
@ -30,4 +30,13 @@ describe('Basics', () => {
|
|||
assert.notEqual(img, undefined);
|
||||
assert.equal(img.getAttribute('src'), '/light_walrus.avif');
|
||||
});
|
||||
|
||||
it('Should generate unique ids when using useId()', async () => {
|
||||
const data = await fixture.readFile('/index.html');
|
||||
const { document } = parseHTML(data);
|
||||
|
||||
const els = document.querySelectorAll('.vue-use-id');
|
||||
assert.equal(els.length, 2);
|
||||
assert.notEqual(els[0].getAttribute('id'), els[1].getAttribute('id'));
|
||||
});
|
||||
});
|
||||
|
|
9
packages/integrations/vue/test/fixtures/basics/src/components/WithId.vue
vendored
Normal file
9
packages/integrations/vue/test/fixtures/basics/src/components/WithId.vue
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<script setup>
|
||||
import { useId } from "vue"
|
||||
|
||||
const id = useId()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p class="vue-use-id" :id="id">{{ id }}</p>
|
||||
</template>
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
import Bar from '../components/Foo.vue';
|
||||
import Parent from '../components/Parent.astro';
|
||||
import WithId from '../components/WithId.vue';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
@ -10,5 +11,7 @@ import Parent from '../components/Parent.astro';
|
|||
<Parent>
|
||||
<Bar slot="footer" />
|
||||
</Parent>
|
||||
<WithId client:idle />
|
||||
<WithId client:idle />
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue