以 JSX 的方式来编写 Vue3 代码

摘要:创建 ASlotDemo 组件,ASlotDemo 有具名插槽 header,范围插槽 footer,在模板中定义插槽需要用到 , jsx 中使用renderSlot函数渲染插槽

创建项目

使用 vue ui 创建 vue3 项目

安装 vue-router vuex @vue/cli-plugin-typescript, @vue/babel-plugin-jsx

修改 babel.config.js 文件

module.exports = { presets: [ '@vue/cli-plugin-babel/preset' ], plugins: ["@vue/babel-plugin-jsx"] }

修改全部 .vue -> .jsx, 模板如下

import {defineComponent} from 'vue'; export default defineComponent({ name: "", setup() { return () => ( <> </> ) } })


路由

RouterView

和 <router-view/> 是一样的用法

import {defineComponent} from 'vue'; import {RouterView} from 'vue-router' export default defineComponent({ setup() { return () => <RouterView/> } })
import {defineComponent} from 'vue'; import {RouterLink} from 'vue-router' export default defineComponent({ name: "RouterLinkDemo", setup() { return () => <RouterLink to={'/home'}/> } })

Fragment

一个组件返回多个元素,和 React.Fragment 差不多
短语法 <></>

import {defineComponent, Fragment} from 'vue'; export default defineComponent({ name: "FragmentDemo", setup() { const a = ( <> <div>A</div> <div>A</div> </> ) return () => ( <Fragment> {a} <div>b</div> </Fragment> ) } })


插槽

带有插槽的组件

创建 ASlotDemo 组件,ASlotDemo 有具名插槽 header,范围插槽 footer

在模板中定义插槽需要用到 <slot/>, jsx 中使用renderSlot函数渲染插槽

renderSlot 接收 Slots, 插槽名,插槽数据,进行渲染

import {defineComponent, renderSlot} from "vue"; export default defineComponent({ name: "ASlotDemo", setup(props, {slots}) { const {default: defaultSlot, header, footer} = slots; const footerData = { text: "2020-1-20" } return () => ( <> <div> { header !== undefined ? renderSlot(slots, 'header') : "默认 header" } </div> <div> { defaultSlot !== undefined ? renderSlot(slots, 'default') : "没有传递默认插槽" } </div> <div> { footer !== undefined ? renderSlot(slots, 'footer', footerData) : "默认 footer" + footerData.text } </div> </> ) } })

使用

在使用范围插槽时,可以定义个接口,获得语法提示

import {defineComponent} from "vue"; import ASlotDemo from "@/components/slot/ASlotDemo"; interface IFooterSlotData { text: string; } export default defineComponent({ name: "BSlotDemo", setup() { return () => ( <> <ASlotDemo> 我是: BSlotDemo </ASlotDemo> <ASlotDemo> </ASlotDemo> <ASlotDemo v-slots={{ default: () => <div>slots使用方式1</div>, header: () => <span>header1</span>, }}/> <ASlotDemo> {{ default: () => <div>slots使用方式2</div>, header: () => <span>header2</span>, }} </ASlotDemo> <ASlotDemo v-slots={{ default: () => <div>范围插槽使用</div>, header: () => <span>范围插槽header</span>, footer: (value: IFooterSlotData) => <span>获取范围插槽的值: {value.text}</span>, }}/> </> ) } })

emits

在父组件使用时,必须 on + 事件名(事件名第一个字母必须大写)

// AEmitsDemo.jsx import {defineComponent} from 'vue'; export default defineComponent({ name: "AEmitsDemo", emits: ['click', 'getDate'], setup(props, {emit}) { const click = () => { console.log('点击++++++++') emit("click") } return () => ( <> <div onClick={click}>点击</div> <div onClick={() => emit("getDate", 10)}>获取数据</div> </> ) } }) // BEmitsDemo.jsx import {defineComponent} from 'vue'; import AEmitsDemo from "@/components/emits/AEmitsDemo"; export default defineComponent({ name: "BEmitsDemo", setup() { const click = () => { console.log('点击---------') } const getData = (value: number) => { console.log(value); } return () => <AEmitsDemo onClick={click} onGetData={getData}/> } })

源码: https://github.com/NikolasSky/vue3-tsx

本文作者:nikolas
本文链接:https://www.cnblogs.com/plum-nikolas/archive/2021/01/29/14344782.html 

 

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_10113