配置
新项目
在npm create vue
命令中设置jsx即可在项目中使用jsx
已有项目(vite)
在vite.config.js
中增加插件
js
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [
// ...
vueJsx(),
],
})
写法
javascript
// App.jsx
import { defineComponent, ref } from "vue";
const Comp = defineComponent({
props: ["onClick"],
setup(props, { slots }) {
return () => (
<button onClick={props.onClick}>{slots.default?.() ?? "a"}</button>
);
},
});
const App = defineComponent({
setup() {
const num = ref(0);
return () => <Comp onClick={() => num.value++}>{num.value}</Comp>;
},
});
export default App;
说明
setup
的返回值是一个render函数 ()=>jsx 而不是普通的jsx 可以理解成react类组件中的render函数- setup函数的签名是
setup(props,{ slots, emit, attrs })
但仅推荐使用props和slots - 传入的
onClick
、class
等会被自动应用到子组件的最外层 需要设置inheritAttrs:false
- 上述的参数会被收集至
setup
的attrs
参数中,需要设置props: ["onClick"]
才会识别为props
.这种情况下,不需要配置inheritAttrs:false
- 插槽位于
slots
对象中,类型是函数,用法是
arduino
{slots.default?.() ?? default-view}
default是默认插槽的名字 如果有其他的具名插槽 使用slots.插槽名
即可
插槽函数可以传递参数 和template中插槽功能一样
-
jsx方式中 只能传输不带参数的默认插槽 类似于react中的children参数
-
jsx方式中 这种写法依旧是不行的
css
Modal.info({ content: <span></span> })
必须使用h('span')
ts
vue+jsx姑且能用 但是vue+tsx就相当恶心了
ts中 传onClick得这么做
typescript
import type { PropType } from 'vue'
defineComponent({
props: {
onClick: Function as PropType<()=> void>
},
setup(props, { slots }) {
//...
},
});
可以设置defineComponent
的模板类型 但是还是会导致onClick被自动应用到子组件最外层以及被视作attrs
插槽方面应该也有一些问题 不过劝退的理由不需要太多 原先的一堆问题再加这个已经足够了
总结
本文的标题其实一开始是在vue中使用jsx
我之前对这种写法是抱有很多期待的 心理流程大概是这样的
- ref非常方便 本体和属性都能直接传给v-model hook限制好少 有点爽
- v-model不好 至少element ui里使用体验极差 组件不听话
js
<el-tabs modelValue="0">
<el-tab-pane name="0"></el-tab-pane>
<el-tab-pane name="1"></el-tab-pane>
</el-tabs>
我都这么写了 它还是能自由切换 是真不愿意受控啊
- vue+jsx能把
ref
和value-onChange
模式结合起来 还能不用写那该死的:@# 简直是vue和react的融合超进化 值得一试 - 一坨
又回过头来看最开始的那个想法 ref其实也没那么好
我需要找一个变量被更新的位置 并没有一个专用的setState 我得查看那个变量被引用的所有位置 无论是取值还是设置
话又说回来 有use-immer react的状态更新还是很方便的
hook方面 有eslint其实还好 而且只要把文档记在心中 其实也很难犯错
至于效率问题 现代浏览器一般不会有这方面的问题 真卡顿再优化也不迟
vue项目一坨一坨盘根错节的组件也不少 不见得比react好到哪里去