vue3中h函数的使用

news2024/11/24 18:31:01

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.js

import { 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?.component
    return 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?.component
    console.log(slots);
    return h(
        components[name], 
        { 
            msg: '通过props传的msg',
            onFoo: (value)=> {
                console.log(value);
            },
        },
        slots.default()
    )
}

使用作用域插槽的话:

const component = (props,{slots}) => {
    let name  =  props?.component
    return 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?.component
    console.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?.component
    console.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.coloradmin.cn/o/1849744.html

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

相关文章

XMLXXE实体注入

XML&XXE实体注入 原理 XML被设计为传输和存储数据&#xff0c;XML文档结构包括XML声明、DTD文档类型定义&#xff08;可选&#xff09;、文档元素&#xff0c;其焦点是数据的内容&#xff0c;其把数据从HTML分离&#xff0c;是独立于软件和硬件的信息传输工具。等同于JSO…

h5兼容问题 复制粘贴移动端无法粘贴复制内容

const selectText (textbox, startIndex, stopIndex) > {if (textbox.createTextRange) {//ieconst range textbox.createTextRange();range.collapse(true);range.moveStart(character, startIndex);//起始光标range.moveEnd(character, stopIndex - startIndex);//结束光…

Web渗透:XSS-DOM-based XSS

DOM-based XSS&#xff08;基于DOM的跨站脚本攻击&#xff09;是一种XSS攻击类型&#xff0c;其特点是恶意脚本通过操作文档对象模型&#xff08;DOM&#xff09;直接在客户端执行&#xff0c;而无需经过服务器的处理。这种攻击主要利用客户端JavaScript代码中的漏洞&#xff0…

如何利用数据仓库进行业务分析:一名大数据工程师的视角

在大数据时代&#xff0c;数据的有效利用对企业的成功至关重要。 本文将基于上面的流程图&#xff0c;详细介绍如何利用数据仓库进行业务分析&#xff0c;并提供实际的例子和代码演示&#xff0c;以帮助读者更好地理解和应用相关技术。 数据仓库的基本流程 上图展示了一个典…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验6 生成树协议STP的功能

一、实验目的 1.验证以太网交换机生成树协议的功能&#xff1b; 2.理解网络环路对网络的负面效应&#xff1b; 3.理解生成树协议的作用。 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实…

【2024最新精简版】网络_Linux操作系统面试篇

文章目录 简述 tcp 和 udp的区别&#xff1f;get 和 post 请求有哪些区别&#xff1f;常用HTTP请求方式有哪些 ?进程跟线程的区别&#xff1f;僵尸进程&#xff1f;IO的多路复用&#xff1f;虚拟内存什么是OSI模型说一说HTTP协议说一说HTTPS协议HTTPS协议和HTTP协议有什么区别…

使用阿里开源的Spring Cloud Alibaba AI开发第一个大模型应用

背景 前段时间看到Spring推出了SpringAI&#xff0c;可以方便快速的接入ChatGPT等国外的大模型&#xff0c;现在阿里巴巴也紧追脚步推出了Spring Cloud Alibaba AI&#xff0c;Spring Cloud Alibaba AI 目前基于 Spring AI 0.8.1 版本 API 完成通义系列大模型的接入。通义接入…

PHP发送HTML邮件的步骤?设置模板的技巧?

PHP发送HTML邮件怎么设置模板&#xff1f;如何用PHP群发邮件&#xff1f; PHP提供了强大的功能来发送HTML格式的电子邮件&#xff0c;这在需要发送格式化内容的邮件时特别有用。AokSend将详细介绍PHP发送HTML邮件的步骤&#xff0c;涵盖了必要的准备工作和实际操作过程。 PHP…

离线源码编译安装zabbix-agent

文章目录 1&#xff0c;先进zabbix官网下载zabbix的源码包2&#xff0c;把这个zabix源码包上传到需要安装的目标机器上去3&#xff0c;编译安装3.1 &#xff0c;解压软件包得到一个zabbix-5.0.42的文件夹3.2&#xff0c;进入/vdb/zabbix-5.0.42文件夹&#xff0c;依次执行命令 …

STM32单片机USART串口收发数据包

文章目录 1. 串口通信 1.1 串口初始化 1.2 库函数 2. 串口收发HEX数据包 2.1 Serial.c 2.2 Serial.h 2.3 main.c 3. 串口收发文本数据包 3.1 Serial.c 3.2 Serial.h 3.3 main.c​​​​​​​ 1. 串口通信 对于串口通信的详细​​​​​​​解析可以看下面这篇文章…

锂磷硫(LPS)属于硫化物固态电解质 Li7P3S11是代表性产品

锂磷硫&#xff08;LPS&#xff09;属于硫化物固态电解质 Li7P3S11是代表性产品 锂磷硫&#xff08;LPS&#xff09;&#xff0c;为非晶态材料&#xff0c;是硫化物固态电解质代表性产品之一&#xff0c;具有热稳定性好、成本较低等优点&#xff0c;在固态电解质中离子电导率较…

C#实现边缘锐化(图像处理)

在 C# 中进行图像的边缘锐化&#xff0c;可以通过卷积滤波器实现。边缘锐化的基本思想是通过卷积核&#xff08;也称为滤波器或掩模&#xff09;来增强图像中的边缘。我们可以使用一个简单的锐化核&#xff0c;例如&#xff1a; [ 0, -1, 0][-1, 5, -1][ 0, -1, 0]这个卷积核…

【Deep Learning】Meta-Learning:训练训练神经网络的神经网络

元学习&#xff1a;训练训练神经网络的神经网络 本文基于清华大学《深度学习》第12节《Beyond Supervised Learning》的内容撰写&#xff0c;既是课堂笔记&#xff0c;亦是作者的一些理解。 1 Meta-Learning 在经典监督学习中&#xff0c;给定训练数据 { ( x i , y i ) } i \{…

javaSE字符串学习笔记

API和API帮助文档 API API(Application Programming Interface)&#xff1a;应用程序编程接口简单理解&#xff1a;API酒啊别人已经写好的东西&#xff0c;我们不需要自己编写&#xff0c;直接使用即可。 API这个术语在编程圈中非常常见.我第一次接触API这个词语是在大一下。老…

【会议征稿,IEEE出版】第三届机器人、人工智能与智能控制国际会议(RAIIC 2024,7月5-7)

第三届机器人、人工智能与智能控制国际会议&#xff08;RAIIC 2024&#xff09;将于2024年7月5-7日中国绵阳举行。 RAIIC 2024是汇聚业界和学术界的顶级论坛&#xff0c;会议将邀请国内外著名专家就以传播机器人、人工智能与智能控制领域的技术进步、研究成果和应用做专题报告…

vs工程添加属性表

一、简介 1、 vs工程属性表以&#xff08;.props&#xff09;为后缀 2、 作用&#xff1a;当多个工程需要配置很多相同的属性配置时方便同步&#xff0c;比如多个工程需要链接相同的头文件&#xff0c;库文件&#xff0c;输出路径&#xff0c;中间目录等 3、本章内容测试环境&a…

Web渗透-SSRF服务端请求伪造

SSRF&#xff08;Server-Side Request Forgery&#xff0c;服务器端请求伪造&#xff09;是一种由攻击者利用漏洞服务器发送恶意请求的攻击方式。SSRF漏洞通常出现在服务器端的web应用中&#xff0c;应用允许用户提供的输入被服务器用来发起请求&#xff0c;而没有对输入进行充…

数据结构:为什么说链表是顺序表的升级版(c语言实现)

前言&#xff1a; 我们在之前的几篇文章中详细的讲解了顺序表的特点&#xff0c;增删改查操作和动态顺序表的优点&#xff0c;并使用顺序表的底层结构实现了通讯录项目&#xff0c;似乎顺序表是一个非常完美的数据结构&#xff0c;它可以实现按照需求实现增删查改&#xff0c;对…

换电脑后导入git本地仓库记录

导入本地仓库tig记录 换了新电脑&#xff0c;将旧电脑的数据盘查到新的笔记本之后发现&#xff0c;使用pycharm 读取不到本地的git提交记录了&#xff0c;我没有将本地git上传到远程仓库的习惯&#xff0c;这可抓马了&#xff0c;硬盘插回去的话也太麻烦了。试了 vscode 提示设…

冲击2024年CSDN博客之星TOP1:CSDN文章质量分查询在哪里?

文章目录 一&#xff0c;2023年博客之星规则1&#xff0c;不高的入围门槛2&#xff0c;[CSDN博文质量分测评地址](https://www.csdn.net/qc) 二&#xff0c;高分秘籍1&#xff0c;要有目录2&#xff0c;文章长度要足够&#xff0c;我的经验是汉字加代码至少1000字。3&#xff0…