在Vue3.0+ts中如何使用h函数

简介: 在Vue3.0+ts中如何使用h函数

直接用模板编写



<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模板

image.png


扩展



你的组件可能有更多的插槽,写上插槽名字即可

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, {})


相关文章
|
3月前
|
JavaScript
vue 函数化组件
vue 函数化组件
|
3月前
|
JavaScript
typeScript基础(3)_ts函数默认值和可选参数
本文介绍了在TypeScript中如何使用函数的默认值和可选参数。展示了如何为函数参数指定默认值,使得在调用函数时可以省略某些参数,以及如何定义可选参数。
182 2
|
2月前
|
前端开发 JavaScript 开发者
|
1月前
Vue3 项目的 setup 函数
【10月更文挑战第23天】setup` 函数是 Vue3 中非常重要的一个概念,掌握它的使用方法对于开发高效、灵活的 Vue3 组件至关重要。通过不断的实践和探索,你将能够更好地利用 `setup` 函数来构建优秀的 Vue3 项目。
|
2月前
|
JavaScript API
vue3知识点:ref函数
vue3知识点:ref函数
36 2
|
2月前
|
JavaScript API
vue3知识点:自定义hook函数
vue3知识点:自定义hook函数
28 2
|
2月前
|
API
vue3知识点:reactive函数
vue3知识点:reactive函数
29 1
|
2月前
|
JavaScript
|
2月前
|
JavaScript
vue 组件中的 data 为什么是一个函数 ?
【10月更文挑战第8天】 在 Vue 组件中,`data` 被定义为一个函数而非普通对象,以确保每个组件实例拥有独立的数据空间,避免数据混乱。这种方式还支持数据的响应式更新、组件的继承与扩展,并有助于避免潜在问题,提升应用的可靠性和性能。
24 2
|
2月前
|
JavaScript 开发者
Vue Render函数
【10月更文挑战第11天】 Vue 的 Render 函数提供了一种强大而灵活的方法来创建虚拟 DOM 节点,使开发者能够更精细地控制组件的构建过程。通过 `createElement` 参数,可以动态生成各种元素和组件,实现复杂逻辑和高级定制。尽管使用 Render 函数需要更多代码和对虚拟 DOM 的深入理解,但它在处理复杂场景时展现出巨大的优势。
19 2