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.mzph.cn/diannao/34181.shtml

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

相关文章

Docker配置国内镜像加速-2

Docker 官方镜像仓库&#xff08;如 Docker Hub&#xff09;可能由于网络原因&#xff0c;在某些地区或网络环境下下载速度较慢。使用镜像加速可以从距离用户更近、网络条件更好的镜像服务器获取镜像&#xff0c;从而显著提高下载速度&#xff0c;节省时间。 1.测试是否安装 d…

探索Elastic Search:强大的开源搜索引擎,详解及使用

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 全文搜索属于最常见的需求&#xff0c;开源的 Elasticsearch &#xff08;以下简称 Elastic&#xff09;是目前全文搜索引…

三维点云目标识别对抗攻击研究综述

源自&#xff1a;电子与信息学报 作者&#xff1a;刘伟权 郑世均 郭宇 王程 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整文章 摘 要 当前&#xff0c;人工智能系统在诸多领域都取得了巨大的成功&#xff0c;其中深度学…

TensorRT-LLM加速框架的基本使用

TensorRT-LLM是英伟达发布的针对大模型的加速框架&#xff0c;TensorRT-LLM是TensorRT的延申。TensorRT-LLM的GitHub地址是 https://github.com/NVIDIA/TensorRT-LLM 这个框架在0.8版本有一个比较大的更新&#xff0c;原先的逻辑被统一了&#xff0c;所以早期的版本就不介绍了…

告别繁琐代码,迈向编程新境界—Java集合与泛型全面解析

在Java编程的征途中&#xff0c;集合&#xff08;Collection&#xff09;与泛型&#xff08;Generics&#xff09;是两大里程碑式的特性&#xff0c;它们不仅极大地提升了代码的灵活性和安全性&#xff0c;还帮助开发者简化了数据结构的处理逻辑&#xff0c;让编程之旅变得更加…

Hadoop 2.0 大家族(四)

目录 七、Flume&#xff08;一&#xff09;Flume简介&#xff08;二&#xff09;Flume入门 八、Mahout&#xff08;一&#xff09;Mahout简介&#xff08;二&#xff09;Mahout入门 七、Flume Flume是一个分布式高性能、高可靠的数据传输工具&#xff0c;它可用简单的方式将不同…

Langchain实战:构建高效的知识问答系统

引言 知识问答系统&#xff08;KQA&#xff09;是自然语言处理领域的核心技术之一&#xff0c;它能够帮助用户从大量数据中快速准确地检索到所需信息。知识问答系统成为了帮助个人和企业快速获取、筛选和处理信息的重要工具。它们在很多领域都发挥着重要作用&#xff0c;例如在…

《计算机英语》Unit 1 Computer Overview 计算机概述

期末试卷组成 1、选择20道 2、判断20道 3、词汇翻译&#xff08;单词词组&#xff0c;参照课后习题&#xff09; 4、翻译2道&#xff08;一道原题&#xff0c;参照作业&#xff09; SectionA About Computer 关于计算机 algorithm n. 算法 operate v.…

爬虫阶段思考

内容&#xff1a;写这篇文章是因为最近帮同学改了很多的爬虫代码&#xff0c;感触良多。 我用豆瓣为例&#xff0c;并不是不会用别的&#xff0c;而是这个我个人感觉最经典。然后还会写我遇到的一些问题以及解决方法。 首先&#xff0c;我们得先知道怎样爬取。我用的scrapy框…

护眼灯和普通台灯有什么区别?劣质护眼台灯宣传的三大套路

护眼灯和普通台灯有什么区别&#xff1f;围绕这一问题的讨论颇多。然而&#xff0c;真正体验过护眼台灯的人会深知&#xff0c;它与普通台灯之间的差异远非一般&#xff0c;涉及照明效果、色温调节、蓝光控制、闪烁问题及功能性设计等诸多层面。为了让更多人透彻理解这两者之间…

.locked勒索病毒详解 | 防御措施 | 恢复数据

引言 在数字化飞速发展的今天&#xff0c;我们享受着信息技术带来的便捷与高效&#xff0c;然而&#xff0c;网络安全问题也随之而来&#xff0c;且日益严重。其中&#xff0c;勒索病毒以其狡猾的传播方式和巨大的破坏性&#xff0c;成为了网络安全领域中的一大难题。.locked勒…

OpenAI Sora:我们来自混乱,我们也将回归混乱

最近&#xff0c;我开始深入了解并整理一些关于Sora这个人工智能模型的系列文章。我的目标是从两个角度深入探讨&#xff1a;一是Sora的技术细节&#xff0c;包括它的原理和功能&#xff1a;OpenAI Sora&#xff1a;距离黑客帝国仅一步之遥&#xff0c;二是Sora的应用前景&…

PPO代码理解

目录 # Finding the ratio (pi_theta / pi_theta__old): ratios torch.exp(logprobs - old_logprobs.detach()) advantages rewards - state_values.detach() surr1 ratios * advantages surr2 torch.clamp(ratios, 1-self.eps_clip, 1self.eps_clip) * advantages l…

【数据分析实战】—预测宠物收养状况数据分析

文章目录 数据集数据集描述特征用途注意 宠物收养预测环境准备探索数据帧数据预处理机器学习数据预处理&#xff1a;模型培训和评估&#xff1a;合奏学习&#xff1a; 添加底部名片获取数据集吧&#xff01; 数据集 数据集描述 宠物收养数据集提供了对各种因素的全面调查&…

【Linux】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统&#xff1f; 从严格意义上说&#xff0c;可将操作系统定义为一种软件&#xff0c;它控制计算机硬件资源&#xff0c;提供程序运行环境。我们通常将这种软件称为内核&#xff08;kerel)&#xff0c;因为它相对较小&#xff0c;而且位于环境的核心。 从广义上…

前端开发接单公司做到哪些点,客户才愿意把项目包给你。

作为前端外包接单公司&#xff0c;你知道客户选择和你合作都看中哪些因素吗&#xff1f;单纯是价格吗&#xff1f;未必&#xff0c;本位给大家列举7个要素&#xff0c;并对每个要素做了定位&#xff0c;大家查缺补漏吧。 作为前端外包接单公司&#xff0c;要吸引同行客户将前端…

【初阶数据结构】深入解析栈:探索底层逻辑

&#x1f525;引言 本篇将深入解析栈:探索底层逻辑&#xff0c;理解底层是如何实现并了解该接口实现的优缺点&#xff0c;以便于我们在编写程序灵活地使用该数据结构。 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1…

【Altium】打开原理图是空白的解决方法

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 打开画完的原理图&#xff0c;报错提示并且图纸为空白的解决方法 2、 问题场景 收到其他人画好的原理图&#xff0c;打开后提示报错&#xff1a;Load file error:值对于无符号的字节太大或太小。并且原理图显示为空…

java基于ssm+jsp 美食推荐管理系统

1前台首页功能模块 美食推荐管理系统&#xff0c;在系统首页可以查看首页、热门美食、美食教程、美食店铺、美食社区、美食资讯、我的、跳转到后台等内容&#xff0c;如图1所示。 图1前台首页功能界面图 用户注册&#xff0c;在注册页面可以填写用户名、密码、姓名、联系电话等…

【shell脚本速成】mysql备份脚本

文章目录 案例需求脚本应用场景&#xff1a;解决问题脚本思路实现代码 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &#x1f338;愿您在此停留的每一刻…