Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotations have an impact on the length of the slot #9655

Closed
Lazydd opened this issue Nov 22, 2023 · 3 comments
Closed

Annotations have an impact on the length of the slot #9655

Lazydd opened this issue Nov 22, 2023 · 3 comments

Comments

@Lazydd
Copy link

Lazydd commented Nov 22, 2023

@DragonnZhang
Copy link

DragonnZhang commented Nov 22, 2023

This problem does not occur in production mode, because Vue compiler will delete comment nodes in production mode.

@jh-leong
Copy link
Member

jh-leong commented Nov 23, 2023

Comment nodes are allowed as valid child elements. Although they don't affect the rendering of the component's default slot, they might lead to confusion when users check for the presence of the default slot using the useSlots API (related issue #7699).

The issue with inconsistent results in slot.default().length in the provided minimal reproduction is caused by different handling of comment nodes when passed into the default slot of a component in packages/compiler-core/src/transforms/vSlot.ts. This behavior depends on whether <template v-slot> is present or not (in L325, L342):

if (!hasTemplateSlots) {
// implicit default slot (on component)
slotsProperties.push(buildDefaultSlotProperty(undefined, children))
} else if (
implicitDefaultChildren.length &&
// #3766
// with whitespace: 'preserve', whitespaces between slots will end up in
// implicitDefaultChildren. Ignore if all implicit children are whitespaces.
implicitDefaultChildren.some(node => isNonWhitespaceContent(node))
) {
// implicit default slot (mixed with named slots)
if (hasNamedDefaultSlot) {
context.onError(
createCompilerError(
ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
implicitDefaultChildren[0].loc
)
)
} else {
slotsProperties.push(
buildDefaultSlotProperty(undefined, implicitDefaultChildren)
)

Deciding on changes to how comment nodes are handled in slots, requires further discussion and work. If you need to check whether there is actual content rendered in the default slot using useSlots, you can use the following workarounds:

  1. Remove comment nodes to avoid interference.
  2. Filter out comment nodes when checking, as below:
<script setup>
import { useSlots, Comment } from 'vue';
const foo = useSlots()
  .default()
  .filter((i) => i.type !== Comment);
</script>

Hope this helps.

@Lazydd
Copy link
Author

Lazydd commented Nov 23, 2023

Comment nodes are allowed as valid child elements. Although they don't affect the rendering of the component's default slot, they might lead to confusion when users check for the presence of the default slot using the useSlots API (related issue #7699).

The issue with inconsistent results in slot.default().length in the provided minimal reproduction is caused by different handling of comment nodes when passed into the default slot of a component in packages/compiler-core/src/transforms/vSlot.ts. This behavior depends on whether <template v-slot> is present or not (in L325, L342):

if (!hasTemplateSlots) {
// implicit default slot (on component)
slotsProperties.push(buildDefaultSlotProperty(undefined, children))
} else if (
implicitDefaultChildren.length &&
// #3766
// with whitespace: 'preserve', whitespaces between slots will end up in
// implicitDefaultChildren. Ignore if all implicit children are whitespaces.
implicitDefaultChildren.some(node => isNonWhitespaceContent(node))
) {
// implicit default slot (mixed with named slots)
if (hasNamedDefaultSlot) {
context.onError(
createCompilerError(
ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
implicitDefaultChildren[0].loc
)
)
} else {
slotsProperties.push(
buildDefaultSlotProperty(undefined, implicitDefaultChildren)
)

Deciding on changes to how comment nodes are handled in slots, requires further discussion and work. If you need to check whether there is actual content rendered in the default slot using useSlots, you can use the following workarounds:

  1. Remove comment nodes to avoid interference.
  2. Filter out comment nodes when checking, as below:
<script setup>
import { useSlots, Comment } from 'vue';
const hasDefaultSlot = useSlots()
  .default()
  .filter((i) => i.type !== Comment);
</script>

Hope this helps.

Weird, not to be exaggerated things, but I need to filter them out

@Lazydd Lazydd closed this as completed Nov 23, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Dec 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants