Vue 3 Render函数中插槽的定义与使用及API变更详解

作者:模板散步

时间:2026-10-25

浏览:539

本文详解Vue 3中Render函数如何定义和使用插槽,对比Vue 2中slots对象结构的差异。重点解析h函数需从全局导入、render函数签名变化以及VNode属性扁平化处理,帮助开发者平滑迁移至Vue 3的渲染机制。

文章目录

在Vue 3的Render函数中,插槽的定义与使用方式发生了显著变化,理解这些机制对于编写底层组件至关重要。

Vue 3中的this.slots对象结构与Vue 2存在本质区别,这直接影响了对插槽内容的访问方式。

在Vue 3中,this.slots是一个包含函数属性的对象,其类型为{ [name: string]: (…args: any[]) => Array | undefined }。这意味着每个具名插槽的内容都必须通过调用对应的函数来获取,例如名为foo的插槽,其分发内容需通过this.slots.foo()调用返回。

相比之下,Vue 2中this.slots是一个{ [name: string]: ?Array }类型的对象,直接通过this.slots.foo即可访问v-slot:foo的内容。而在Vue 2中,与Vue 3的this.$slots作用相似的是this.scopedSlots。

定义插槽时,需要明确如何访问静态内容。

使用this.$slots.[插槽名]可以访问一个返回VNode数组的函数,该函数用于获取静态插槽的内容。

const BlogPost = defineComponent({
  render(){
    return h('div', [
      h('h1',this.$slots.header&&this.$slots.header()||'默认header插槽'),
      h('p',this.$slots.default&&this.$slots.default({message:'我是作用域插槽的message'})||'默认default插槽'),
      h('h4',this.$slots.footer&&this.$slots.footer()||'默认footer插槽'),
    ])
  }
})

// 以上代码相当于以下的template
<template>
	<div>
		<h1>
			<slot name="header">默认header插槽</slot>
		</h1>
		<p>
			<slot>默认default插槽</slot>
		</p>
		<h4>
			<slot name="footer">默认footer插槽</slot>
		</h4>
	</div>
</template>

在定义包含插槽的组件时,需正确使用插槽传递内容。

在h函数的第三个参数中,可以使用{ [name: string]: (…args: any[]) => Array | undefined }形式的对象来定义组件的具体插槽内容,从而灵活控制插槽的行为。

const BlogPostWrapper = defineComponent({
  render(){
    return h('div',
             {style:'background:skyblue'},
             h(
                  BlogPost,
                   null,
                   {
                  header(props){
                    return '我是传进的header插槽内容'
                  },
                    default(props){
                    // 这里的props就是作用域插槽的插槽prop
                    return 'BlogPostWrapper的default插槽内容::>>'+props.message
                  },
                  footer(props){
                    return '我是传进的footer插槽内容'
                  }
                }
            )
          )
      }
})
// 相当于template
<template>
    <div>
        <BlogPost>
            <tempalte #header>'我是传进的header插槽内容'</tempalte>
            <tempalte #default="props">
                {{'BlogPostWrapper的default插槽内容::>>'+props.message}}
            </tempalte>
            <tempalte #footer>我是传进的footer插槽内容</tempalte>
        </BlogPost>
    </div>
</template>

Vue 3的Render函数API进行了一些重要变动,了解这些变化有助于避免兼容性问题。

面对陌生的Render function API,使用<template>的用户无需担心,这些改动主要影响底层渲染逻辑。

从整体视角来看,主要变动包括以下几点:

  • h函数需要从全局导入,不再作为render函数的参数传递。
  • render函数的参数结构发生了改变,旨在保持常规组件和函数组件行为的一致性。
  • VNodes对象的属性结构实现了扁平化处理,简化了属性访问。

关于render函数的参数传递,不同版本间存在差异。

在Vue 2.x版本中,代码编写方式如下:

在Vue 2.x版本中,render函数会自动接收h函数(即createElement)作为参数:

export default {
    render(h) {
        return h('div');
    }
}

在Vue 3.x版本中,代码编写方式应调整为:

在Vue 3.x版本中,h函数需要手动从全局引入,不再由框架自动注入:

import { h } from 'vue';
 
export default {
    render() {
        return h('div');
    }
}

render函数的签名在Vue 3中发生了根本性变化。

在Vue 2.x版本中,render函数的写法如下:

如前所述,Vue 2.x的render函数会自动接收h作为其参数:

export default {
    render(h) {
        return h('div');
    }
}

在Vue 3.x版本中,render函数不再接收任何参数,其主要作用是在setup函数中使用。

在 Vue 3.x 版本中,render 函数不再接收任何参数,其主要作用是在 setup 函数中使用,以便方便获取作用域链中的响应式状态、各种函数以及传递给 setup 函数的参数。

import { h, reactive } from 'vue';
 
export default {
    setup(props, { slots, attrs, emit }) {
        const state = reactive({ count: 0 });
        
        function increment() {
            state.count++
        }
        
        // 返回一个 render 函数
        return () => {
            h(
                'div',
                { onClick: increment, },
                state.count,
            )
        }
    }
}

VNode的属性格式在Vue 3中进行了优化。

在Vue 2.x中,VNode属性的结构如下:

domProps是VNode属性中的一个嵌套列表,例如:

{
    class: ['button', 'confirm-button'],
    style: { color: 'red' },
    attrs: { id: 'confirm' },
    domProps: { innerHTML: '' },
    on: { click: confirmCreate },
    key: 'submit-button',
}

在Vue 3.x中,VNode属性的结构调整为:

在Vue 3版本中,VNode的所有属性均实现了扁平化处理,例如:

{
    class: ['button', 'confirm-button'],
    style: { color: 'red' },
    id: 'submit',
    innerHTML: '',
    onClick: confirmCreate,
    key: 'submit-button',
}

实际上,由于template模板更加直观易用,许多开发者较少直接使用render函数。

如需获取更多详细信息,可访问官方文档:v3.vuejs.org/guide/migration/render-function-api.html(目前尚无中文版)。

以上为个人经验总结,希望能为大家提供参考,也希望大家多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章