热门搜索 :
考研考公
您的当前位置:首页正文

详细解释 Vue 中的 h 函数和 render 函数:

来源:伴沃教育

Vue中的h函数和render函数是Vue中非常重要的函数,对Vue有着不可以或缺的作用,接下来让我们了解一下!

// 1. h 函数的基本使用
/**
 * h 函数是 createVNode 的别名,用于创建虚拟 DOM 节点(VNode)
 * h 函数参数:
 * - type: 标签名/组件
 * - props: 属性对象(可选)
 * - children: 子节点(可选)
 */

// 1.1 创建简单元素
const vnode = h('div', { class: 'test' }, 'Hello')

// 1.2 创建带子元素的节点
const vnode2 = h('div', { class: 'parent' }, [
    h('span', null, 'Child 1'),
    h('span', null, 'Child 2')
])

// 1.3 创建组件
const MyComponent = {
    props: ['title'],
    setup(props) {
        return () => h('h1', null, props.title)
    }
}

const vnode3 = h(MyComponent, {
    title: 'Hello',
    onClick: () => console.log('clicked')
})

// 2. render 函数的使用
/**
 * render 函数用于将虚拟 DOM 渲染为真实 DOM
 * 参数:
 * - vnode: 要渲染的虚拟节点
 * - container: 容器元素
 */

// 2.1 基本用法
import { h, render } from 'vue'

const vnode = h('div', { class: 'test' }, 'Hello')
render(vnode, document.body)

// 2.2 动态渲染
function updateUI(text) {
    const newVNode = h('div', null, text)
    render(newVNode, document.body)
}

// 2.3 清除渲染
render(null, document.body)  // 清除容器内容

// 3. 实际应用示例

// 3.1 创建消息提示组件
const createMessage = (type, content) => {
    // 创建容器
    const container = document.createElement('div')
    document.body.appendChild(container)
    
    // 创建消息组件的 VNode
    const vnode = h('div', {
        class: `message message-${type}`,
        style: {
            position: 'fixed',
            top: '20px',
            left: '50%',
            transform: 'translateX(-50%)'
        }
    }, [
        // 图标
        h('i', { class: `icon-${type}` }),
        // 文本内容
        h('span', null, content)
    ])
    
    // 渲染到容器
    render(vnode, container)
    
    // 定时清除
    setTimeout(() => {
        render(null, container)
        container.remove()
    }, 3000)
}

// 3.2 创建弹窗组件
const createModal = (options) => {
    const container = document.createElement('div')
    document.body.appendChild(container)
    
    const close = () => {
        render(null, container)
        container.remove()
    }
    
    const vnode = h('div', {
        class: 'modal-wrapper',
        onClick: (e) => {
            if (e.target === e.currentTarget) close()
        }
    }, [
        h('div', { class: 'modal' }, [
            // 标题
            h('h2', null, options.title),
            // 内容
            h('div', { class: 'content' }, options.content),
            // 按钮
            h('div', { class: 'footer' }, [
                h('button', {
                    onClick: () => {
                        options.onConfirm?.()
                        close()
                    }
                }, '确定'),
                h('button', {
                    onClick: close
                }, '取消')
            ])
        ])
    ])
    
    render(vnode, container)
    
    return {
        close
    }
}

// 4. 高级用法

// 4.1 条件渲染
const conditionalRender = (condition) => {
    return h('div', null, [
        condition 
            ? h('p', null, '条件为真')
            : h('p', null, '条件为假')
    ])
}

// 4.2 列表渲染
const listRender = (items) => {
    return h('ul', null, 
        items.map(item => h('li', { key: item.id }, item.text))
    )
}

// 4.3 插槽的使用
const withSlots = (slots) => {
    return h('div', { class: 'container' }, [
        h('header', null, slots.header?.()),
        h('main', null, slots.default?.()),
        h('footer', null, slots.footer?.())
    ])
}

// 4.4 组件通信
const Parent = {
    setup() {
        const count = ref(0)
        return () => h(Child, {
            count: count.value,
            onIncrement: () => count.value++
        })
    }
}

const Child = {
    props: ['count'],
    emits: ['increment'],
    setup(props, { emit }) {
        return () => h('button', {
            onClick: () => emit('increment')
        }, `Count: ${props.count}`)
    }
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Top