Vue 3 中使用 JSX 如何绑定 scopeId

vue3 scopeId

前言

在特定情况下,我需要在 SFC 组件中使用 JSX 的方法进行部分页面内容处理,但是在默认的情况下,JSX 并不会带 scopeId,这导致我不能通过 scope css 的方法修改 JSX 的样式。在 jsx 这个插件的 github issues 中,查找到了在组件中带上组件 scopeId 的方法,虽然略显累赘,但终归是可以用。

方法

在 vue 中,导出对象有 withScopeId 这样一个函数,它可以传递一个

  1. 参数1:scopeId 前组件的 scopeId

执行后,它会返回另一个函数 withCtx

这个 withCtx 函数可以传递两个参数,执行后返回 renderFnWithContext,它的返回值是一个带 scopeId 的 VNode。

  1. 参数1:fn jsx 函数,签名 () => JSX.Element
  2. 参数2:ctx vue 实例,ComponentInternalInstance | null | undefined

至此,我们的 JSX 就带上了 scopeId

封装成成一个简单的 hooks 供调用

hooks.ts

import { JSX } from '@babel/types';
import { getCurrentInstance, withScopeId } from 'vue';

/**
 * 给 jsx/tsx 加 CSS Scope
 * @description jsx/tsx 在 Vue3 中不支持 CSS 的 Scope,目前用这个方法使得 jsx/tsx 元素添加 Scope Id 属性
 */
export function useScope() {
    const vm = getCurrentInstance();
    const scopeId = (vm?.type as any).__scopeId;
    const withScopeIdFunction = withScopeId(scopeId);
    const withScope = (element: () => JSX.Element) => withScopeIdFunction(element, vm) as VNodeFunction;
    return {
        scopeId, // scopedId
        vm, // vue 实例
        withScope, // 用这个函数包含 () => jsx/tsx 即可
    };
}

sample.vue

<script lang="tsx" setup>
// 得到带有 scope 的虚拟 DOM
const jsxWithScope = withScope(() => (
    <div class="my-class" onClick={xxx}>
        示例文本
    </TinyButton>
))
</script>

参考资料

https://github.com/vuejs/babel-plugin-jsx/issues/51#issuecomment-770400811

评论

0/500

全部评论 (0)

这里没有评论,要抢沙发吗?