React和Vue中暴露子组件的属性和方法给父组件用,并且控制子组件暴露的颗粒度的做法

news2024/12/14 17:41:01

React

在 React 中,forwardRef 是一种高级技术,它允许你将 ref 从父组件传递到子组件,从而直接访问子组件的 DOM 节点或公开的方法。这对于需要操作子组件内部状态或 DOM 的场景非常有用。为了使子组件能够暴露其属性和方法给父组件,通常会结合 useImperativeHandle Hook 使用 forwardRef

如何使用 forwardRefuseImperativeHandle

  1. 创建一个带有 forwardRef 的子组件:

    • 使用 React.forwardRef 来创建一个接受 ref 参数的组件。
  2. 使用 useImperativeHandle 定义要暴露的方法和属性:

    • 在子组件中使用 useImperativeHandle 来定义哪些方法或属性应该通过 ref 暴露出去。
  3. 在父组件中使用 ref 来访问子组件的公开接口:

    • 创建一个 ref 并将其传递给子组件,然后通过这个 ref 访问子组件暴露的方法或属性。

示例代码

子组件 (ChildComponent.js)
import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  // 定义要暴露的方法
  useImperativeHandle(ref, () => ({
    focusInput: () => {
      inputRef.current.focus();
      console.log('子组件的输入框获得了焦点');
    },
    getInputValue: () => inputRef.current.value,
  }));

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="这是子组件的输入框" />
    </div>
  );
});

export default ChildComponent;
父组件 (ParentComponent.js)
import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  const childComponentRef = useRef(null);

  const handleFocus = () => {
    if (childComponentRef.current) {
      childComponentRef.current.focusInput();
    }
  };

  const handleGetValue = () => {
    if (childComponentRef.current) {
      const value = childComponentRef.current.getInputValue();
      console.log('子组件的输入值:', value);
    }
  };

  return (
    <div>
      <ChildComponent ref={childComponentRef} />
      <button onClick={handleFocus}>让子组件的输入框获得焦点</button>
      <button onClick={handleGetValue}>获取子组件的输入值</button>
    </div>
  );
};

export default ParentComponent;

解释

  • 子组件 (ChildComponent.js):

    • 使用 forwardRef 创建了一个接受 ref 参数的组件。
    • 使用 useImperativeHandle 定义了 focusInputgetInputValue 方法,并将它们绑定到传入的 ref 上。这意味着父组件可以通过 ref 访问这些方法。
  • 父组件 (ParentComponent.js):

    • 创建了一个 ref (childComponentRef) 并将其传递给 ChildComponent
    • 提供了两个按钮,分别用于调用子组件的 focusInputgetInputValue 方法。

这种方法确保了父组件可以安全地与子组件进行交互,同时保持良好的封装性。通过 useImperativeHandle,你可以精确控制哪些方法或属性是公开的,而不会意外地暴露不必要的实现细节。

Vue

当你通过 ref 获取到子组件的根 DOM 元素后,你可以使用标准的 DOM API 来访问或操作该元素及其子元素。如果你想要访问 <p> 标签,可以通过多种方式实现,具体取决于你想要进行的操作。

访问子元素的方法

  1. 使用 querySelectorquerySelectorAll:

    • 这些方法允许你根据选择器(如标签名、类名、ID 等)来查找特定的子元素。
  2. 遍历子节点:

    • 你可以使用 childrenchildNodes 或其他类似属性来遍历子节点。
  3. 直接访问特定子元素:

    • 如果你知道子元素的具体位置,可以直接通过 firstElementChildlastElementChild 等属性访问。

示例代码

假设你想在父组件中访问并打印子组件中的 <p> 标签的内容,可以按照以下方式修改你的代码:

子组件 (ChildComponent.vue)
<template>
  <div ref="root">
    <p id="content">这是子组件的内容</p>
  </div>
</template>

<script setup>
import { defineExpose, ref } from 'vue';

const root = ref(null);

// 使用 defineExpose 显式暴露给父组件的方法或属性
defineExpose({
  getRootEl: () => root.value,
});
</script>
父组件 (ParentComponent.vue)
<template>
  <ChildComponent ref="childComponent" />
  <button @click="handleClick">点击我</button>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const childComponent = ref(null);

const handleClick = () => {
  if (childComponent.value) {
    // 调用子组件的公开方法来获取 DOM 引用
    const el = childComponent.value.getRootEl();
    
    // 使用 querySelector 查找 <p> 标签
    const pElement = el.querySelector('p#content');
    console.log('子组件的 <p> 内容:', pElement?.textContent);
  }
};
</script>

解释

  • 子组件 (ChildComponent.vue):

    • 我们为 <p> 标签添加了一个 id="content",以便更容易地通过 querySelector 查找它。
  • 父组件 (ParentComponent.vue):

    • handleClick 方法中,我们首先调用 getRootEl 获取子组件的根元素。
    • 然后,使用 querySelector 方法通过 ID 选择器查找 <p> 标签,并打印其文本内容。这里使用了可选链操作符 (?.) 来安全处理可能为 null 的情况。

这种方法确保了你能够以一种安全且可控的方式访问子组件内部的特定 DOM 元素。请记住,尽量减少对 DOM 的直接操作,除非确实有必要。保持尽可能多的逻辑在 Vue 的响应式系统内,这样可以使应用更加高效和易于维护。

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

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

相关文章

Launcher启动流程

Launcher启动流程分2个阶段&#xff1a; AMS systemReady() 会启动一个临时Activity&#xff1a;com.android.settings.FallbackHome&#xff0c;如下流程等到用户解锁成功后&#xff0c;FallbackHome轮询到有可用的RealHome包&#xff0c;会销毁掉自己&#xff0c;AMS发现没有…

苹果据悉与博通合作开发AI芯片,台积电先进制程将再迎大单

12月13日消息&#xff0c;苹果有意投入自研AI芯片&#xff0c;与博通共同开发&#xff0c;以台积电3纳米制程生产&#xff0c;2026年量产。法人看好&#xff0c;苹果自研AI芯片开发完成后&#xff0c;投片力度可期&#xff0c;台积电先进制程将再迎来大单。据了解&#xff0c;苹…

【含开题报告+文档+PPT+源码】基于微信小程序的点餐系统的设计与实现

开题报告 随着互联网技术的日益成熟和消费者生活水平与需求层次的显著提升&#xff0c;外卖点餐平台在中国市场上迅速兴起并深深植根于民众日常生活的各个角落。这类平台的核心在于构建了一个基于互联网的强大订餐服务系统&#xff0c;它无缝整合了餐饮商户资源与广大消费者的…

【老白学 Java】数字格式化

数字格式化 文章来源&#xff1a;《Head First Java》修炼感悟。 很多时候需要对数字或日期进行格式化操作&#xff0c;来达到某些输出效果。Java 的 Formatter 类提供了很多扩展性功能用于字符串的格式化&#xff0c;只要调用 String 静态方法 format() &#xff0c;传入参数…

IIS部署程序https是访问出现403或ERR_HTTP2_PROTOCOL_ERROR

一、说明 在windows server 2016中的IIS程序池里部署一套系统&#xff0c;通过https访问站点&#xff0c;同时考虑到安全问题以及防攻击等行为&#xff0c;就用上了WAF云盾功能&#xff0c;能有效的抵挡部分攻击&#xff0c;加强网站的安全性和健壮性。 应用系统一直能够正常…

丸美更名的科技底色

文丨白念云 在当今全球化与科技飞速发展的时代&#xff0c;化妆品行业正历经深刻变革。合成生物学、基因编辑等前沿技术的崛起&#xff0c;重塑着行业生态&#xff0c;开辟出崭新的市场空间。中国作为全球第二大化妆品消费市场&#xff0c;在消费者对品质生活的强烈渴望以及国家…

基于STM32的火灾烟雾报警器设计开题报告

开题报告 题目&#xff1a;基于STM32的火灾烟雾报警器Proteus仿真设计 一、研究背景与意义 随着现代城市化进程的加快&#xff0c;火灾安全问题日益凸显&#xff0c;火灾的早期预警对于减少人员伤亡和财产损失至关重要。传统的火灾报警系统往往依赖于烟雾或温度的单一检测&a…

Docker的镜像

目录 1. 镜像是什么&#xff1f;&#xff1f;2. 镜像命令详解2.1 镜像命令清单2.2 docker rmi命令2.3 docker save命令2.4 docker load命令2.5 docker history命令2.6 docker import命令2.7 docker image prune命令2.8 docker build命令 3. 镜像的操作4. 离线迁移镜像5. 镜像存…

【AIGC】ChatGPT保护指令:高效提升GPTs提示词与知识库文件的安全性

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;前言&#x1f4af;新建未加保护指令的GPTs测试获取GPTs的提示词Prompt指令与知识库文件 &#x1f4af;给GPTs添加保护指令方法一方法二方法三方法四 &#x1f4af;增强GPT…

算法分析与设计之分治算法

文章目录 前言一、分治算法divide and conquer1.1 分治定义1.2 分治法的复杂性分析&#xff1a;递归方程1.2.1 主定理1.2.2 递归树法1.2.3 迭代法 二、典型例题2.1 Mergesort2.2 Counting Inversions2.3 棋盘覆盖2.4 最大和数组2.5 Closest Pair of Points2.6 Karatsuba算法&am…

Verilog实现图像处理的行缓存Line Buffer

在图像处理中&#xff0c;难免会遇到对图像进行卷积或者模板的局部处理&#xff0c;例如ISP中的一些算法&#xff0c;很大部分都需要一个窗口&#xff0c;在实时视频处理中&#xff0c;可以利用行缓存Line buffer可以暂存几行数据&#xff0c;然后同时输出每行中的对应列的像素…

String【Redis对象篇】

&#x1f3c6; 作者简介&#xff1a;席万里 ⚡ 个人网站&#xff1a;https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜&#xff0c;同时略懂Vue与React前端技术&#xff0c;也了解一点微信小程序开发。 &#x1f37b; 对计算机充满兴趣&#xff0c;愿意并且希望学习更多的技…

Microsemi Libero SoC免费许可证申请指南(Microchip官网2024最新方法)

点击如下链接&#xff1a; https://www.microchip.com/en-us/products/fpgas-and-plds/fpga-and-soc-design-tools/fpga/licensing 点击右侧&#xff0c;请求免费的License 如果提示登录&#xff0c;请先登录Microchip账号。 点击Request Free License。 选项一年免费的Li…

动态规划子序列问题系列一>最长递增子序列的个数

题目&#xff1a; 解析&#xff1a; 这里求最长递增子序列的长度&#xff0c;请看这篇博客&#xff1a;动态规划子序列问题系列一&#xff1e;最长递增子序列-CSDN博客 这里主要运用&#xff1a;一个小贪心状态转移方程的分析方法完成该题 代码&#xff1a; public int fi…

每天40分玩转Django:Django视图和URL

Django视图和URL 一、课程概述 学习项目具体内容预计用时视图基础函数视图、类视图、视图装饰器90分钟URL配置URL模式、路由系统、命名URL60分钟请求处理请求对象、响应对象、中间件90分钟 二、视图基础 2.1 函数视图 # blog/views.py from django.shortcuts import render…

token失效重新存储发起请求

import axios from axios import { MessageBox, Message } from element-ui import store from /store import Router from /router import { getCookie, setToken, setCookie } from ./auth// 因为后端环境区分v1 v2 剔除测试盛传的环境配置&#xff0c;并添加统一前缀 const …

悬赏任务源码(悬赏发布web+APP+小程序)开发附源码

悬赏任务源码是指一个软件或网站的源代码&#xff0c;用于实现悬赏任务的功能。悬赏任务是指发布方提供一定的奖励&#xff0c;希望能够找到解决特定问题或完成特定任务的人。悬赏任务源码通常包括任务发布、任务接受、任务完成和奖励发放等功能的实现。搭建悬赏任务源码是一个…

【一本通】虫洞

【一本通】虫洞 C语言代码C代码JAVA代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边&#xff0c;并可以使你返回到过去的一个时刻&#xff08;相对你进入虫洞之…

Linux之条件变量,信号量,生产者消费者模型

Linux之条件变量&#xff0c;信号量&#xff0c;生产消费者模型&#xff0c;日志以及线程池 一.条件变量1.1条件变量的概念1.2条件变量的接口 二.信号量2.1信号量的重新认识2.2信号量的接口 三.生产者消费者模型3.1生产者消费者模型的概念3.2基于阻塞队列的生产者消费者模型3.3…

如何写出优秀的单元测试?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 写出优秀的单元测试需要考虑以下几个方面&#xff1a; 1. 测试用例设计 测试用例应该覆盖被测试代码的不同场景和边界情况&#xff0c;以尽可能发现潜在的问题。…