VueをTypeScriptで扱うにあたって、SFC/comosition apiでのtemplateの型に困りすぎてjsx記法を検討している。
tsxとして記述できるのは知っていたが、Vueが魔術的に解決している scoped な css はどうやるのかな? というのを確かめる必要があった。
結論から言うと、 SFCの<style>
をscoped
でなく module
として記述し、
setup
や render
関数の中で useCssModule()
を呼ぶことで <style>
内の宣言にアクセスできる。
{useCssModule} from 'vue';
とかライブラリの機能でかすぎない?
以下の感じ。
SampleComponent.vue
<script lang="tsx">
import {defineComponent, PropType, useCssModule} from 'vue';
interface Props {
hoge : {
text : string
}
fuga? : number
}
export const SampleComponent = defineComponent({
props : {
hoge : {
type : Object as PropType<Props[`hoge`]>,
required: true
},
fuga : {
type : Number as PropType<Props[`fuga`]>
}
},
setup(props : Props){
const styles = useCssModule();
return ()=>{
return (
<div class={styles.sample} >
<h1 > Sample { props.hoge.text } </h1>
{ props.fuga && (
<div>
{props.fuga}
</div>
)}
</div>
);
};
}
})
</script>
<style module lang="scss">
.sample {
color: red;
}
</style>
ちょっとSFC内で別コンポーネント切り出ししたいときとかはこうなるかも
import {defineComponent, PropType, FunctionalComponent, HTMLAttributes, useCssModule} from "vue";
...
const MyButton : FunctionalComponent<HTMLAttributes & {styles : Record<string, string>}> = (props , {slots} )=>{
return (
<button {...props} class={props.styles.mybtn}>
{ slots.default && slots.default() }
</button>
);
}
Vueの ref
と併せ、これで全体の操作感がちょっと前の 「React + tsx + mobx + css modules」 構成に近い書き味となった。
ならはじめからReactでいいのでは?というとそうかもしれない。