vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.04k stars 8.24k forks source link

Setting inheritAttrs=false breaks scoped style #5234

Open OpenGG opened 2 years ago

OpenGG commented 2 years ago

Version

3.2.26

Reproduction link

stackblitz.com SFC Playground

Steps to reproduce

  1. AttrsComp.vue: set inheritAttrs=false, pass attrs to child <img v-bind="$attrs">.
  2. App.vue: render <AttrsComp class="test" />, where .test { width: 90vw } is defined in <style scoped>

What is expected?

  1. attrs pass to child: <img class="test">
  2. child <img > rendered with 90vw width

What is actually happening?

  1. attrs pass to child: <img class="test">
  2. child <img> rendered with default width ❌

Use case:

  1. AttrsComp.vue was once single <img>, inheriting scoped class from App.vue.
  2. With feature changes, AttrsComp.vue refactored into <picture>, all attrs should be passed into child <img>

Due to this issue, all classes passed into <AttrsComp> must be moved to non-scoped, which breaks component encapsulation.

LinusBorg commented 2 years ago

I'd not rate this a bug as the SFC spec explicitly states that the style scoping only extends to the root element of a child component, but I see a use in discussing how to enhance the behaviour for this specific usecase

In the meantime, we have :deep() to extend styles to deeply nested elements as well as css modules as usable alternatives.

OpenGG commented 2 years ago

@LinusBorg

Noted.

Maybe css-modules fit this use case better, but the Vue community invested in scoped styles, so...

LinusBorg commented 2 years ago

Sure, as I said I see the use here. So far it's just a blind spot in the spec. One that can be worked around with :deep() at least.