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

.vue 文件中使用 jsx, style 的 scoped 不起作用 #51

Closed
BoltDoggy opened this issue Aug 3, 2020 · 8 comments
Closed

.vue 文件中使用 jsx, style 的 scoped 不起作用 #51

BoltDoggy opened this issue Aug 3, 2020 · 8 comments

Comments

@BoltDoggy
Copy link

style 的 scoped 生成的 data-v-xxxx, jsx 生成的为 data-v-xxxx-s

image

image

===

自己尝试看了一下源码, 没有解决的, 目前猜想是, jsx 的 vnode 丢失了 scopeId 属性, 导致 vue3 的 runtime 把 jsx 的 dom 当做了 slot.

因为 template 中执行了这个方法, 使得 vnode 获取了 scopeId

image

image

@Amour1688
Copy link
Member

Amour1688 commented Aug 3, 2020

在 Vue 2 中 JSX 也是不支持 scoped css 的。使用 JSX 的话,建议使用 CSS-IN-JS 的方案。

但是 JSX 也不应该生成 scopeId。

@BoltDoggy
Copy link
Author

BoltDoggy commented Aug 3, 2020

https://forum.vuejs.org/t/jsx-with-scoped-styles-possible/7523 社区中肯定是有一些人喜欢 jsx + scoped css 的. 虽然 Vue 2 一直没有人实现, 但我认为是值得尝试的.

只要取到 __scopeId, 就可以在 setup/render 函数中, 使用下面方法实现 scoped css

     const _withId = withScopeId(__scopeId);
...
     return _withId(() => <div class="bolt">
        <HelloWorld>{_withId(() => <div>asdf</div>)()}</HelloWorld>
      </div>)

目前可以取到 __scopedId 的方法有:

方案1:

// main.js
import { createApp } from 'vue';
import App from './App.vue'

createApp(App(App)).mount('#app') // 这里将 App 传回组件

// ./App.vue
export default ({ __scopeId }) => {
   // 这里可以取到 __scopeId
})

方案2:

// ./App.vue
export default {
   render(ctx) {
       // ctx._.type.__scopeId
   }
}

方案3: setup 可以返回一个 render 方法, 用于 render jsx

// ./App.vue
export default {
   setup() {
        return (ctx) {
             // ctx._.type.__scopeId
        }
   }
}

@Amour1688
Copy link
Member

Amour1688 commented Aug 3, 2020

@Mikeccx
Copy link

Mikeccx commented Jan 31, 2021

// this may do work
import { defineComponent, computed, ref, getCurrentInstance, withScopeId } from 'vue'
export default defineComponent({
setup() {
const instance = getCurrentInstance()
const scopeId = instance.type.__scopeId
const withId = withScopeId(scopeId)
return withId( () => ( <div class="page-wraper">)
}

@Arman19941113
Copy link

// this may do work
import { defineComponent, computed, ref, getCurrentInstance, withScopeId } from 'vue'
export default defineComponent({
setup() {
const instance = getCurrentInstance()
const scopeId = instance.type.__scopeId
const withId = withScopeId(scopeId)
return withId( () => (

)
}

This works indeed. But not elegant. Is there any way to support this feature more graceful.

@xialvjun
Copy link

xialvjun commented Mar 5, 2021

@yyx990803 Will you plan to support scoped css in vue SFC written with jsx/tsx ?

In current status, it seems almost support it. Vue3 renders <div class="aaa" data-v-05d27cca-s=""></div> and the inject style is .aaa[data-v-05d27cca]. I don't know why it add a -s after.

@xialvjun
Copy link

xialvjun commented Mar 5, 2021

在 Vue 2 中 JSX 也是不支持 scoped css 的。使用 JSX 的话,建议使用 CSS-IN-JS 的方案。

但是 JSX 也不应该生成 scopeId。

Vue 2 中是支持的

<template></template>
<script lang="tsx">
import { h, defineComponent, ref } from "@vue/composition-api";
export default defineComponent({
  setup: (props, ctx) => {
    const count = ref(0);
    const increase = () => count.value++;
    return () => <div class="huge_size" onClick={increase}>{count.value}</div>
  }
});
</script>
<style lang="less" scoped>
.huge_size {
  font-size: 96px;
}
</style>
// babel.config.js
module.exports = {
  presets: [["@vue/jsx"], ["@vue/app", { jsx: { injectH: false } }]],
};
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "preserve",
  },
}

@sendking
Copy link

有个疑问,就是每个文件里去引 withScopeId 不觉得累么

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants