使用vue3的函数式组件定义一个加载elementPlus的下拉框

定义

import { createVNode, h,  markRaw, reactive, resolveComponent, SetupContext, VNode } from 'vue'
// px 方法用来增加 px 使用的
interface StyleItemPropType {
    label: string
    className?: string
    contentClassName?: string
    isLine?: boolean
}

export const StyleItem = <T extends StyleItemPropType, E extends Partial<SetupContext>> (props: T, ctx: E): VNode => {
	// 如果需要使用自定义指令,则使用 withDirectives 将其包裹则可以返回一个包含自定义指令的 vNode
	/**
	 * withDirectives(h('input', [[resolveDirective('指令名称'), 'value参数', 'arg参数']]))
	 */
    return h('div', { class: `style-item ${ props.className ?? '' }`.trim() }, [
        h('div', { class: 'label', innerText: props.label }),
        h('div', { class: `content ${ props.contentClassName ?? '' }`.trim() }, ctx.slots)
    ])
}

interface SelectPxPropType {
    modelValue: string
}

export const SelectPx = <T extends SelectPxPropType, E extends Partial<SetupContext>> (props: T, ctx: E): VNode => {

    const options: Array<string> = markRaw(['10px', '20px', '30px', '40px', '50px'])

    return createVNode(resolveComponent('el-select'), {
        modelValue: props.modelValue,
        clearable: true,
        filterable: true,
        class: 'style-class',
        // 属性可以直接使用
        filterMethod: (value: string): void => {
            !options.includes(value) && ctx.emit?.('update:modelValue', value)
        },
        // 事件需要使用 on 前缀
        onVisibleChange: () => {
            props.modelValue && !options.includes(props.modelValue) && ctx.emit?.('update:modelValue', px(props.modelValue))
        },
        // 用于进行双向绑定
        'onUpdate:modelValue': (value: string): void => {
            ctx.emit?.('update:modelValue', value)
        },
    }, {
	    // 使用默认插槽的方式。不使用默认插槽会导致报错:
	    // warning Non-function value encountered for default slot. Prefer function slots for better performance. 
        default: () => options.map((option: string) =>
            createVNode(resolveComponent('el-option'), {
                label: option,
                value: option,
                valueKey: option
            }))
    })
}

使用

<template>
	<StyleItem label="文本" className="bottom-border">
		这里可以随便填写内容,会被渲染到 .content div 中        
    </StyleItem>
    <!-- 下拉框 -->
	<SelectPx v-model="value"></SelectPx>
</template>

// 导入
import { StyleItem, SelectPx } from '@mixins/useStyleAttr'

// 使用
export default defineComponent({
	....
	// 注册组件
	components: {
		StyleItem,
		SelectPx,
	}
})

你可能感兴趣的:(vue.js,javascript,前端,typescript)