SSF0SSF0
首页
前端
  • Node
  • Go
  • C#
  • MySql
  • Bash
  • Git
  • Docker
  • VuePress
  • CI/CD
  • 服务器
  • 网站
  • 学习资料
  • 软件
Timeline
Github
标签
分类
首页
前端
  • Node
  • Go
  • C#
  • MySql
  • Bash
  • Git
  • Docker
  • VuePress
  • CI/CD
  • 服务器
  • 网站
  • 学习资料
  • 软件
Timeline
Github
标签
分类
  • HTML

    • html1
    • html2
  • CSS

    • Flex 布局常见问题与解决方案
  • JavaScript

    • 数据类型及引用问题
    • 处理 Blob 类型文件下载问题总结
    • localStorage 与 sessionStorage 区别
    • JavaScript 中的 script 标签问题详解
    • JavaScript 中的`this`指向问题详解
    • SessionStorage踩坑记录:它真的能"只设置一次"吗?
    • 动态加载 JS 脚本方法对比
    • 浏览器页面关闭场景下的数据上报
  • es6

    • Promise
    • es6 模块导出方式全解析
  • Vue2

    • created VS mounted 发起异步请求
    • vue2-2
  • Vue3

    • Vite + Vue3 修改 element-plus 源码
    • Vue v-if 与 v-show
    • Vue3 ref 获取组件
    • Vue3 路由传参
    • 父子组件与组件里 Hooks 加载顺序
    • 第三方组件传入参数TS提示
    • Vue3 Props 在 Hooks 中的响应性处理
    • Vue Router 的两种历史模式及部署配置详解
    • 在Vue 3项目中顺利集成Tailwind CSS的完整指南
    • Vue 3 深度选择器:deep()完全指南
  • Electron

    • 快速构建 electron + vue3 项目
  • TS

    • TS 泛型
    • 记录模板使用断言的问题
    • type 与 interface
  • WebPack

    • Webpack 介绍
  • Vite

    • Vite CLI 常见命令
    • vite 与 webpack 比较
  • 项目工程

    • 前端代码风格
    • Vue3 项目规范
    • npm 镜像问题
    • 包管理工具
    • 使用 engines 限制开发环境依赖
    • 打包与shell交互指定模式
    • 使用 pnpm 构建 Monorepo 实战指南
    • pnpm 修改依赖源码打包报错
  • 记录一下小程序
  • 控制浏览器正确保存网站账号密码的技巧

Vue3 ref 获取组件

在使用 Vue 3 Composition API 的过程中,你可能会注意到,有时我们可以在 hooks(组合函数)里直接通过 ref 拿到某些组件的实例,例如 el-form;但对于自定义组件或部分第三方组件,却必须先在模板中定义好 ref,才能在 hooks 中正常访问到它。为什么会有这样的差别呢?

在 hooks 中可以直接 获取 el-form

以下示例展示了我们如何在 hooks 中直接使用 el-form 的 ref:

// useMyHook.ts
import { ref } from 'vue'
import type { FormInstance } from 'element-plus' // 仅用于类型提示

export function useMyHook() {
  // 直接定义 el-form 的 ref
  const formRef = ref<FormInstance>()

  // ... 这里可以对 formRef 进行逻辑操作(校验表单、重置表单等)

  return { formRef }
}

然后在组件中:

<template>
  <el-form ref="formRef">
    <!-- 表单内容 -->
  </el-form>
</template>

<script setup lang="ts">
import { useMyHook } from "./hooks";
const { formRef } = useMyHook();
</script>

这样做之所以可行,是因为像 el-form 这样的第三方组件本身只需要一个最简化的实例引用,对 Vue 模板编译的依赖较小。它通过 Vue 的底层机制允许在外部直接使用 ref 即可拿到组件实例。

在 hooks 中无法直接获取自定义组件

与之相对,对于自定义组件或部分第三方组件(例如本例的 ServiceTelContent),我们不能直接在 hooks 中尝试获取它们的 ref。下面是一个示例:

// 试图在 hooks 中直接定义自定义组件 ref
// 这样通常不会成功
const serviceTelContentRef = ref<ServiceTelContent>()

这种写法无法拿到组件实例,因为自定义组件的 ref 依赖于 Vue 的模板编译系统。换言之,Vue 需要先解析和渲染模板,才能为 ref 所对应的自定义组件实例建立引用关系。

正确使用方式

如下所示,我们需要在组件的模板中先定义 ref,然后再把该 ref 传给我们的 hooks。这么做才能确保模板编译完成后,钩子函数拿到的是真实的组件实例。

<!-- 组件中 -->
<template>
  <el-form ref="formRef">
    <!-- ✅ 可以在 hooks 中直接定义和使用 -->
    <!-- 其他内容 -->
  </el-form>

  <ServiceTelContent ref="serviceTelContentRef" />
  <!-- ❌ 如果在 hooks 中直接定义,就无法拿到实例 -->
</template>

<script setup lang="ts">
import { ref } from "vue";
import { useMyHook } from "./hooks";

// el-form 的 ref 可以直接在 hooks 中定义,并在此处使用
const { formRef } = useMyHook();

// 自定义组件的 ref 必须先在组件本身定义,然后再传入 hooks
const serviceTelContentRef = ref(null);
useMyHook(serviceTelContentRef);
</script>

Vue 的设计初衷

Vue 之所以在自定义组件的 ref 获取上带有这层"模板编译依赖",是为了:

  1. 保障组件之间的隔离性:自定义组件彼此之间更独立,外部无法直接在组合函数中拿到它们的实例。

  2. 提高可维护性:通过模板编译建立组件引用关系,逻辑更加明确,组件和逻辑之间的依赖更加直观。

  3. 避免过度对内部实现的依赖:如果所有组件都能像内置组件一样直接通过 ref 获取,可能会导致组件间耦合过高。

总结

  • 一些内置组件或第三方组件(如 el-form)不依赖 Vue 的模板编译即可建立 ref,并在 hooks 中直接拿到组件实例。

  • 自定义组件(如 ServiceTelContent)需要先在模板编译中为组件实例标记 ref,然后才能在 hooks 中对其进行访问。

  • 这是一种平衡的设计,既能保证在编写公共逻辑时使用 hooks,也能保持组件自身的独立性(需在模板内先定义 ref)。这样就更好地符合 Vue 的设计理念。

通过以上方式,我们既能复用逻辑(在 hooks 里编写各种操作),也能保持组件自身的独立性(需在模板内先定义 ref)。这样就更好地符合 Vue 的设计理念。

最后更新时间:
贡献者: 何风顺
上一页
Vue v-if 与 v-show
下一页
Vue3 路由传参