我要做的是一个菜单效果,是用的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 + props
h('div', {})
// type + omit props + children
// Omit props does NOT support named slots
h('div', []) // array
h('div', 'foo') // text
h('div', h('br')) // vnode
h(Component, () => {}) // default slot
// type + props + children
h('div', {}, []) // array
h('div', {}, 'foo') // text
h('div', {}, h('br')) // vnode
h(Component, {}, () => {}) // default slot
h(Component, {}, {}) // named slots
// named slots without props requires explicit `null` to avoid ambiguity
h(Component, null, {})
更多关于你学习的知识
https://vue3js.cn/global/h.html
关于 vue3 中的 render 方法,你可能不知道这些
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。