我要做的是一个菜单成果,是用的jsx语法,开发应用的是Vue3.0+ts开发的
间接用模板编写
<a-menu v-model:selectedKeys="selectedKeys" mode="inline" theme="light"> <a-menu-item key="1"> <pie-chart-outlined/> <span>工作台</span> </a-menu-item> <a-sub-menu key="sub3"> <template #title> <span> <desktop-outlined/> <span>系统配置</span> </span> </template> <a-sub-menu key="sub4" title="权限治理"> <a-menu-item key="7"> 菜单列表 </a-menu-item> </a-sub-menu> </a-sub-menu> <a-sub-menu key="sub2"> <template #title> <span> <user-outlined/> <span>User</span> </span> </template> <a-menu-item key="4">Bill</a-menu-item> </a-sub-menu></a-menu>
应用tsx编写
数据结构
const defaultMenu = [ { name: '首页', router: '/home', icon: 'HomeFilled', isShow: 1, id: 1 }, { name: '组件库', router: '', isShow: 1, id: 2, children: [ { name: 'Markdown编辑器', router: '/markdown', icon: 'HomeFilled', isShow: 1, id: 3, }, { name: '文件上传', router: '/fileUpload', icon: 'UploadOutlined', isShow: 1, id: 4, children:[ { name: '图片上传', router: '/fileUploadImg', icon: 'UploadOutlined', isShow: 1, id: 6, } ] }, ] }, { name: '对于', router: '/about', icon: 'UserOutlined', isShow: 1, id: 5, },]
import {computed, defineComponent, h, ref} from 'vue'import {useStore} from 'vuex'export default defineComponent({ name: 'yxs-menu-slider', setup() { const store = useStore(); const selectedKeys = ref<string[]>(['1']); // 设置默认选中 const menuList = computed(() => store.getters.menuList); // 等于上述的 defaultMenu 构造,我只不过放在了store return { selectedKeys, menuList } }, render(ctx: any) { const deepMenu = function (list: Array<any>) { let html = null; return list.filter((item: any) => item.isShow).map((item: any) => { if (item.children && item.children.length) { html = h( <a-sub-menu key={item.id}></a-sub-menu>, {}, { title: () => { // 插槽地位 title return <span>{item.name}</span> }, default: () => { // 默认内容 let children = item.children.map((todo: any) => { return <a-menu-item key={todo.id}>{todo.name}</a-menu-item> }) return children && deepMenu(item.children) // 递归 } } ) } else { html = h( <a-menu-item key={item.id}></a-menu-item>, {}, { default: () => { return <span>{item.name}</span> } } ) } return html; }) } const children = deepMenu(ctx.menuList); return ( <div class="yxs-menu-slider"> <a-menu v-model:selectedKeys={ctx.selectedKeys} mode="inline" theme="light"> {children} </a-menu> </div> ) }})
应用
注册调用即可
<template> <YxsMenuSlider/></template><script lang="ts"> import YxsMenuSlider from './components/menu/index.tsx' export default defineComponent({ name: 'Slider', components: { YxsMenuSlider } })</script>
成果如下
下面半截是模板,上面tsx模板
扩大
你的组件可能有更多的插槽,写上插槽名字即可
h(Comp, null, { default: () => 'default', foo: () => 'foo', bar: () => 'bar'})
留神这么写的时候,即使没有props,第二个参数也是必须的,因为h函数发现第二个参数如果是对象,那么默认其就是props,
更多写法请往下看,源码曾经帮我做好了很多兼容
解说
h语法
在讲之前先看h函数源码
// type 元素的类型// propsOrChildren 数据对象, 这里次要示意(props, attrs, dom props, class 和 style)// children 子节点也是一个any类型export function h(type: any, propsOrChildren?: any, children?: any): VNode { if (arguments.length === 2) { if (isObject(propsOrChildren) && !isArray(propsOrChildren)) { // single vnode without props if (isVNode(propsOrChildren)) { return createVNode(type, null, [propsOrChildren]) } // props without children return createVNode(type, propsOrChildren) } else { // omit props return createVNode(type, null, propsOrChildren) } } else { if (isVNode(children)) { children = [children] } return createVNode(type, propsOrChildren, children) }}
通过上述咱们就晓得,如何应用h函数,以及为什么能这么传参
h('div')// type + propsh('div', {})// type + omit props + children// Omit props does NOT support named slotsh('div', []) // arrayh('div', 'foo') // texth('div', h('br')) // vnodeh(Component, () => {}) // default slot// type + props + childrenh('div', {}, []) // arrayh('div', {}, 'foo') // texth('div', {}, h('br')) // vnodeh(Component, {}, () => {}) // default sloth(Component, {}, {}) // named slots// named slots without props requires explicit `null` to avoid ambiguityh(Component, null, {})
官网也说的有列子
更多对于你学习的常识
https://vue3js.cn/global/h.html
对于 vue3 中的 render 办法,你可能不晓得这些