vue3中h函数的使用

h函数是用于创建一个 vnodes ,它既可以用于创建原生元素,也可以创建组件,其渲染后的效果等同于使用模版语言来进行创建。

h函数的传参如下:

// 完整参数签名
function h(type: string | Component,props?: object | null,children?: Children | Slot | Slots
): VNode// 省略 props
function h(type: string | Component, children?: Children | Slot): VNode

第一个参数既可以是一个字符串 (用于原生元素) 也可以是一个 Vue 组件定义。第二个参数是要传递的 prop,第三个参数是子节点。

1、创建原生元素:

<script setup>
import { ref, h } from 'vue'const message = ref('在div里面渲染的值')
const comp = h('div',{style: {color: 'red'},onclick: ()=> {console.log('点击了原生元素div');}},message.value
)
</script><template><component :is="comp" />
</template>

这里给 div 传的 props 里有样式 style 和 事件 click ,在页面上的显示和点击了元素后效果和在模版语言中定义是一样的:

需要注意的是,我们这里的 comp 是一个 vnodes ,而 setup 函数并不是响应式的环境,所以当我们在 setup 函数中调用 h 函数来获取 vnodes 时,并没有绑定 message !只有在 render 函数 中执行才会绑定,所以我们可以定义一个h函数来返回给 comp,在渲染时,让component来帮我们调用。可以通过在 2s 后改变 message 的值来对比两种情况下页面渲染的变化:

const message = ref('在div里面渲染的值')
// 这样不会更新 message 的值
// const comp = h(
//   'div',
//   {
//     style: {
//       color: 'red'
//     },
//     onclick: ()=> {
//       console.log('点击了原生元素div');
//     }
//   },
//   message.value
// )// 这样可以更新 message 的值
const comp = () => h('div',{style: {color: 'red'},onclick: ()=> {console.log('点击了原生元素div');}},message.value
)setTimeout(()=> {message.value = '2s后更新了在div里面渲染的值'
}, 2000)

2、创建组件

这里使用的是一个批量注册的方式导入 HelloWorld 组件,Comp 是一个全局组件

全局组件的定义如下:

// component.jsimport { h } from 'vue'const modules = import.meta.glob('../components/*.vue')const components = {}
for(const path in modules) {const module = await modules[path]()const componentName = path.replace(/.*\/(.*)\.vue/, '$1')components[componentName] = module.default
}
const component = (props,{slots}) => {let name  =  props?.componentreturn h(components[name], { msg: '通过props传的msg',onFoo: (value)=> {console.log(value);},},slots)
}export default component

页面上导入是这样的:

容易混淆的地方是,Comp 是一个全局组件,通过传参 HelloWorld 渲染的才是 HelloWorld 组件,相当于外面套了一层,这里的 slots 其实是 Comp 组件的 slots , slots 传进了 HelloWorld 组件里,使用 HelloWolrd 组件里预留的插槽渲染的

<Comp component="HelloWorld">我是 Comp 组件的默认插槽<template #header><div>我是 Comp 组件的 header 插槽</div></template></Comp>

HelloWorld 组件中定义的:

<template><div><div>{{msg}}</div><div style="color: red">{{valueInProps}}</div><slot></slot><slot name="header" valueInSlot="我是 header 插槽里面的值"><div>我是 header 插槽里面的默认值,外部没有定义的话就是显示这个</div></slot></div>
</template>

那么 slots 里面到底是什么呢,我们直接打印一下看看:

我们可以看到 slots 其实是一个对象,键是插槽的名字,值其实就是一个 渲染函数 h(),

也可以这样写:

const component = (props,{slots}) => {let name  =  props?.componentconsole.log(slots);return h(components[name], { msg: '通过props传的msg',onFoo: (value)=> {console.log(value);},},slots.default())
}

使用作用域插槽的话:

const component = (props,{slots}) => {let name  =  props?.componentreturn h(components[name], { msg: '通过props传的msg',onFoo: (value)=> {console.log(value);},},slots.default('我是作用域插槽传的值'))
}<Comp component="HelloWorld"><template #default="scope"><div>{{scope}}</div></template></Comp>

如果我们不想帮 Comp 组件渲染的话,也可以自己来写:

const component = (props,{slots}) => {let name  =  props?.componentconsole.log(slots);return h(components[name], { msg: '通过props传的msg',onFoo: (value)=> {console.log(value);},},{default: ()=> h('div', '我是 HelloWorld 组件的默认插槽里面的值'),header: ()=> h('div', '我是 HelloWorld 组件的 header 插槽里面的值'),})
}

如果我们想渲染预留插槽里面的值(即作用域插槽),可以这样传:

<slot name="header" valueInSlot="我是 header 插槽里面的值"><div>我是 header 插槽里面的默认值,外部没有定义的话就是显示这个</div>
</slot>
const component = (props,{slots}) => {let name  =  props?.componentconsole.log(slots);return h(components[name], { msg: '通过props传的msg',onFoo: (value)=> {console.log(value);},},{default: ()=> h('div', '我是 HelloWorld 组件的默认插槽里面的值'),header: ({valueInSlot})=> h('div', '我是 HelloWorld 组件的 header 插槽里面的值,后面是预留插槽的值传递:'+valueInSlot),})
}

页面上的显示效果:

还有两个比较好理解的点,这里也补充一下:

在组件中传值,我们知道是用 props 来进行传递,所以在子组件中也是用 defineProps 来 接收值,而子组件想要传值给父组件的话,注意如果是传 foo 函数,则要用 onFoo 接受,例子如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/360827.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python笔记 文件的写,追加,备份操作

一、文件的写操作 案例演示&#xff1a; # 1.打开文件 f open(python.txt,w)# 2.文件写入 f.write(hello world)# 3.内容刷新 f.flush() 注意&#xff1a; 直接调用write&#xff0c;内容并为真正的写入文件&#xff0c;二十会积攒在程序的内存中&#xff0c;称之为缓冲区…

百度智能云千帆推出大模型普惠计划,0成本切换

百度智能云千帆推出大模型普惠计划&#xff0c;0成本切换至国内调用量第一的大模型平台。场景更丰富、模型更全面、工具链更完整易用、更安全可靠&#xff01; 即日起为新注册企业用户提供&#xff1a; 0元调用&#xff1a; 文心旗舰模型首次免费&#xff0c;赠送ERNIE3.5旗舰模…

PDF编辑软件pdf转word工具Acrobat DC百度云盘分享

如大家所了解的&#xff0c;Adobe Acrobat DC是一款高级PDF文档编辑和管理软件&#xff0c;它整合了创建、编辑、共享和签署PDF文件的强大功能。这款软件为用户提供了一系列高效的工具&#xff0c;使得处理PDF文件变得异常简单&#xff0c;大幅提升办公效率。 Acrobat DC软件核…

【Linux】性能分析器 perf 详解(一)

1、简介 perf 是由 Linux 官方提供的系统性能分析工具 。它包含两部分: perf_events ,Linux 内核中的一个子系统perf 命令,用户空间的应用程序内核子系统 perf_events 提供了性能计数器(hardware performance counters)和性能事件的支持,它以事件驱动型的方式工作,通过…

HTTP性能测试工具 —— wrk!

wrk性能测试工具详解 wrk是一款轻量级但功能强大的HTTP基准测试工具&#xff0c;主要用于在单机多核CPU环境下对HTTP服务进行性能测试。它通过利用系统自带的高性能I/O机制&#xff08;如epoll、kqueue等&#xff09;&#xff0c;结合多线程和事件模式&#xff0c;能够产生大量…

JavaWeb——MySQL:DDL

目录 3.DQL&#xff1a;查询 3.5 分页查询 ​编辑 总结&#xff1a; 3. DQL&#xff1a;查询 查询是使用最多、最频繁的操作&#xff0c;因为前面的修改以及删除&#xff0c;一般会交给数据库专业的人员&#xff0c;对于非数据库专业人员来说&#xff0c;老板一般会放心的…

[DALL·E 2] Hierarchical Text-Conditional Image Generation with CLIP Latents

1、目的 CLIP DDPM进行text-to-image生成 2、数据 (x, y)&#xff0c;x为图像&#xff0c;y为相应的captions&#xff1b;设定和为CLIP的image和text embeddings 3、方法 1&#xff09;CLIP 学习图像和文本的embedding&#xff1b;在训练prior和decoder时固定该部分参数 2&a…

使用npm报npm ERR code EPERMnpm ERR syscall rename错误

使用npm install初始化时报错&#xff0c; 解决结果是&#xff1a;node版本不对&#xff0c;切换node版本

基于 Redis 实现秒杀资格判断,提升并发性能

在互联网电商平台上&#xff0c;秒杀活动往往会吸引大量用户同时抢购&#xff0c;如何高效地处理高并发请求&#xff0c;保证用户体验&#xff0c;是一个重要的技术挑战。本文将介绍如何基于 Redis 实现秒杀资格的判断&#xff0c;提高并发性能。 基本思路 秒杀活动的核心流程…

规则引擎-Aviator 表达式校验是否成立

目录 介绍特性使用更多文献支持 介绍 Aviator是一个轻量级、高性能的Java表达式执行引擎&#xff0c;它动态地将表达式编译成字节码并运行。 特性 支持绝大多数运算操作符&#xff0c;包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(~)、三元表达式(?:…

申请专利前需要了解的步骤

申请专利前需要了解的步骤 在创新日益成为推动社会进步的重要动力的今天&#xff0c;专利的申请与保护显得尤为重要。然而&#xff0c;对于许多初次接触专利申请的人来说&#xff0c;这个过程可能会显得复杂而繁琐。 一、明确创新内容并评估其可专利性 在申请专利前&#xff…

vue3前后端开发:响应式对象不能直接成为前后端数据传输的对象

如图所示&#xff1a;前端控制台打印显示数据是没问题的&#xff0c;后端却显示没有接收到相应数据&#xff0c;但是后端的确接收到了一组空数据 直接说原因&#xff1a;这种情况唯一的原因是没有按正确格式传递参数。每个人写错的格式各有不同&#xff0c;我只是说明一下我在…

Python+Pytest+Allure+Yaml接口自动化测试框架详解

PythonPytestAllureYaml接口自动化测试框架详解 编撰人&#xff1a;CesareCheung 更新时间&#xff1a;2024.06.20 一、技术栈 PythonPytestAllureYaml 版本要求&#xff1a;Python3.7.0,Pytest7.4.4,Allure2.18.1,PyYaml6.0 二、环境配置 1、安装python3.7&#xff0c;并配置…

[Redis]事务

Redis事务 Redis 事务提供了一种将多个命令请求打包的功能。然后&#xff0c;再按顺序执行打包的所有命令&#xff0c;并且不会被中途打断。 但是&#xff0c;事务中的每条命令都会与 Redis 服务器进行网络交互&#xff0c;比较浪费资源 所以&#xff0c;日常开发中不建议使…

小区业主管理系统

摘 要 随着城市化进程的加速和人口的不断增加&#xff0c;小区的数量也在不断增加。小区作为城市居民居住的主要场所&#xff0c;其管理工作也变得越来越重要。传统的小区业主管理方式存在诸多问题&#xff0c;如信息传递不畅、业务处理效率低下等。因此&#xff0c;开发一个高…

搜维尔科技:「研讨会」惯性动捕技术在工效学领域应用研讨会

Movella将于7月2日&#xff08;周二&#xff09;下午2点举行主题为惯性动捕技术在工效学领域应用的研讨会。来自Movella的伙伴赋能经理Jeffrey Muller作为嘉宾出席&#xff0c;届时主讲人将为大家带来Xsens惯性动捕技术在工效学领域的应用分享。同时&#xff0c;研讨会还邀请多…

高频面试题基本总结回顾1(含笔试高频算法整理)

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…

从零开始做题:修猫

修猫 1 题目 2 解题 2.1 使用Stegslove分析图片 (base) ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc] └─$ java -jar Stegsolve.jar 2.2 analyse -frame browser 2.3 得到flag DASCTF{818ca3a840e768da7d5fcdeaedd5012f}

基于Java微信小程序校园订餐系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

springcloud-gateway 路由加载流程

问题 Spring Cloud Gateway版本是2.2.9.RELEASE&#xff0c;原本项目中依赖服务自动发现来自动配置路由到微服务的&#xff0c;但是发现将spring.cloud.gateway.discovery.locator.enabledfalse 启动之后Gateway依然会将所有微服务自动注册到路由中&#xff0c;百思不得其解&a…