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

ops/2024/12/22 14:09:17/

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.ppmy.cn/ops/144035.html

相关文章

【k8s集群应用】kubeadm1.20高可用部署(3master)

文章目录 Kubeadm - K8S1.20 - 高可用集群部署Kubernetes 环境准备1. 基础配置2. 修改主机名3. 修改 hosts 文件4. 时间同步5. Linux 资源限制6. 升级内核7. 调整内核参数8. 加载 ip_vs 模块 Kubernetes 集群部署在所有节点上安装 Docker在所有节点上安装 kubeadm、kubelet 和 …

SQLAlchemy 2.0 高级特性详解

SQLAlchemy 2.0 高级特性详解 一、关系运算符 any 与 has 1. any 方法 用于一对多关系中&#xff0c;检查集合中是否存在满足条件的元素。 from sqlalchemy import select# 示例&#xff1a;查找有任何价格大于100的商品的订单 stmt select(Order).where(Order.items.any(…

【WRF教程第3.1期】预处理系统 WPS 详解:以4.5版本为例

预处理系统 WPS 详解&#xff1a;以4.5版本为例 每个 WPS 程序的功能程序1&#xff1a;geogrid程序2&#xff1a;ungrib程序3&#xff1a;metgrid WPS运行&#xff08;Running the WPS&#xff09;步骤1&#xff1a;Define model domains with geogrid步骤2&#xff1a;Extract…

大数据-环保领域

在生态环境领域&#xff0c;我国正在加快建设布局合理、功能完善的生态环境监测网络&#xff0c;实现对环境质量、重点污染源、生态状况监测的全覆盖。建设生态环境大数据平台&#xff0c;提高环境综合分析、预警预测和协同监管能力&#xff0c;搭建面向社会公众和组织的数据开…

C# OpenCV机器视觉:图像分割(让照片中的物体各自“安家”!)

在一个无聊的周末&#xff0c;阿强决定去参加一个朋友的聚会。他兴奋地准备好相机&#xff0c;想要记录下这次难忘的时刻。然而&#xff0c;当他查看自己拍的照片时&#xff0c;发现每张照片都像是一幅混乱的拼图&#xff0c;物体之间的界限模糊不清&#xff0c;仿佛所有的东西…

代码随想录算法日记day16 | 513.找树左下角的值、112. 路径总和、106.从中序与后序遍历序列构造二叉树

原题链接&&讲解 222. 完全二叉树的节点个数 112. 路径总和 106.从中序与后序遍历序列构造二叉树 讲解>>代码随想录 222. 完全二叉树的节点个数 题目 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在…

MySQL数据库下载及安装教程

链接&#xff1a;MySQL数据库下载及安装教程&#xff08;最最新版&#xff09;_mysql下载安装-CSDN博客 亲测安装成功了&#x1f495; 把这个路径放到系统环境变量里头 MD!我这安到C盘去了&#xff0c;就很烦&#x1f92c;&#x1f621; 在CMD登录试一下 mysql -h localhos…

Flutter组合动画学习

如何使用动画控制器和动画来创建一个简单的动画效果。具体来说&#xff0c;它通过一个 AnimationController 来控制两个动画&#xff0c;一个用于旋转&#xff0c;一个用于绘制。 前置知识点学习 SingleTickerProviderStateMixin SingleTickerProviderStateMixin 是 Flutter …