虽然官方建议我们使用template的方式进行开发,不得不承认JSX语法的灵活性给我们开发带来极大的便捷让我们的开发效率进一步的提升。手把手教你写一个很简单的vue3通用性组件和jsx语法的使用,当然,在vue3中,createBlock方法在编写组件的时候特别有效,同学们一定要掌握这个方法,平时可以多写一些组件使用。
废话少说,直接上案例
1、首先我们需要安装的插件有(vue的jsx语法解析的插件):
npm i @vue/babel-plugin-jsx -D
2、需要在bable.config.js中进行配置 来到这一步,恭喜你,vue可以使用jsx语法了
plugins: [ "@vue/babel-plugin-jsx"]
3、启动项目
- 案例:编写一个自定义的bottom组件 使用defineComponent方法,此处css模块我就不上代码了 Bottom.jsx
import {
defineComponent,
SetupContext,
renderSlot,
createBlock,
openBlock,
createCommentVNode,
} from "vue";
const MyButton = defineComponent({
name: 'MyButton',
props: {
// 定义传入的属性做类型检查和校验
type: {
type: String,
default: 'default',
validator: (val) => {
return [
'primary',
'success',
].includes(val);
},
},
size: String,
icon: {
type: String,
defalut: '',
},
loading: Boolean,
disabled: Boolean,
// 需要定义的属性可以自己加进来
},
// 事件需要在这里进行注册
emits: ['click'],
// props 传入的props参数
// ctx 上下文 携带有 attrs emit expose slots props 属性
setup(props, ctx: SetupContext) {
// 定义点击事件
const handleClick = (e: MouseEvent) => {
ctx.emit('click', e);
}
return {
handleClick,
}
},
});
// 渲染函数 当然这里也是可以写入到 defineComponent里面的
// 需要用到的renderSlot,slot插槽 如<MyButton>xxx</MyButton>那么renderSlot(ctx.$slots,'default') 就是xxx的内容,以此类推
// cache 为缓存函数
// 方法一,直接处理
function render(ctx, cache, $props, $setup, $data, $options) {
const props = {
...$props,
onClick: cache[1] || (cache[1] = (e: MouseEvent) => (ctx.handleClick(e)))
}
return (
<ElButton {...props}>
{ renderSlot(ctx.$slots,'default') }
</ElButton>
);
}
// 方法二, 通过vue.openBlock和vue.createBlock方法进行处理 创建代码块的方式
// 两个方法都是虚拟dom,createBlock接收五个参数,通过vue3源码可以看出
/* function createBlock(
type: VNodeTypes | ClassComponent,
props?: Record<string, any> | null,
children?: any,
patchFlag?: number,
dynamicProps?: string[]
) {...} */
// 于是有了下面的方式
function render2(ctx, cache, $props, $setup, $data, $options) {
return (openBlock(), createBlock(
'button',
{
class: 'xxx',
diabled: ctx.buttonDisabled,
onClick: cache[1] || (cache[1] = (e: MouseEvent) => (ctx.handleClick(e)),
..., // 其它属性的处理可以继续往下加
},
// 处理children 如
[
ctx.loading ?
(openBlock(), createBlock('span') : createCommentVNode('v-if', true))
],
10, // patch的标识 CLASS, PROPS
['disabled'] // 动态属性也就是可能会被改变的
))
}
// 这里必须进行render否则无效
MyButton.render = render;
export default MyButton;
路漫漫其修远兮
吾将上下而求索