Vue的ref的使用

举报
周杰伦本人 发表于 2025/01/22 16:34:03 2025/01/22
216 0 0
【摘要】 Vue的ref的使用问题:动态操作 DOM 元素假设你正在开发一个简单的页面,页面上有多个标题元素(h1、h2、h3),你希望通过按钮点击动态输出这些标题元素的内容。具体需求如下:页面上有三个标题元素:h1 显示“中国”h2 显示“贵州”h3 显示“贵阳”页面上有两个按钮:点击第一个按钮时,输出 h2 元素的内容。点击第二个按钮时,输出 h3 元素的内容。问题描述如何通过按钮点击动态获取并输...

Vue的ref的使用

问题:动态操作 DOM 元素

假设你正在开发一个简单的页面,页面上有多个标题元素(h1h2h3),你希望通过按钮点击动态输出这些标题元素的内容。具体需求如下:

  1. 页面上有三个标题元素:
  • h1 显示“中国”

  • h2 显示“贵州”

  • h3 显示“贵阳”

  1. 页面上有两个按钮:
  • 点击第一个按钮时,输出 h2 元素的内容。

  • 点击第二个按钮时,输出 h3 元素的内容。

问题描述

  • 如何通过按钮点击动态获取并输出 h2h3 的内容?

  • 如何避免使用传统的 idclass 来操作 DOM 元素,而是使用 Vue 3 提供的 ref 属性?

如果是id与其他页面的id重复了怎么办?


实现思路

这时候就需要ref了,id:在整个 HTML 文档中必须是唯一的,否则会导致冲突。而ref:在 Vue 组件的作用域内是唯一的,不会与其他组件冲突。

  1. 使用 ref 绑定 DOM 元素
  • h2h3 上分别绑定 ref,给它们打上标记。

  • 在按钮的点击事件中,通过 ref 获取对应的 DOM 元素并输出其内容。

  1. 组件化开发
  • 如果这些标题和按钮是一个组件的一部分,如何在父组件中访问子组件的内容?

代码实现

HTML 结构

HTML复制

<template>
  <div>
    <h1>中国</h1>
    <h2 ref="title2">贵州</h2>
    <h3 ref="title3">贵阳</h3>
    <button @click="showTitle2">点我输出 h2 元素</button>
    <button @click="showTitle3">点我输出 h3 元素</button>
  </div>
</template>

脚本逻辑

JavaScript复制

<script setup lang="ts">
import { ref } from 'vue';

const title2 = ref(null); // 用于存储 h2 元素的引用
const title3 = ref(null); // 用于存储 h3 元素的引用

const showTitle2 = () => {
  console.log(title2.value.textContent); // 输出 h2 的内容
};

const showTitle3 = () => {
  console.log(title3.value.textContent); // 输出 h3 的内容
};
</script>

运行效果

  • 点击“点我输出 h2 元素”按钮时,控制台会输出“贵州”。

  • 点击“点我输出 h3 元素”按钮时,控制台会输出“贵阳”。


详细讲解 ref 的用法和原理

一、ref 的基本用法

(一)绑定到普通 HTML 元素

ref 可以绑定到普通 HTML 元素上,例如 <div><h1><button> 等。通过 ref,你可以轻松地获取这些元素的引用。

HTML复制

<h2 ref="title2">北京</h2>

(二)访问 DOM 元素

setup 函数中,通过 ref 获取 DOM 元素的引用,并通过 .value 访问它。

JavaScript复制

const title2 = ref(null);

const showTitle2 = () => {
  console.log(title2.value.textContent); // 输出 h2 的内容
};

二、ref 用于组件实例

(一)绑定到组件实例

ref 也可以绑定到组件实例上。通过 ref,你可以获取组件实例的引用,并访问其方法和数据。

HTML复制

<Person ref="person" />

(二)访问组件实例

setup 函数中,通过 ref 获取组件实例的引用,并通过 .value 访问它。

JavaScript复制

const person = ref(null);

const showPerson = () => {
  console.log(person.value); // 输出 Person 组件实例
};

三、ref 的原理

(一)依赖收集

  • ref 被绑定到 DOM 元素或组件实例时,Vue 会自动将这些元素或实例收集为依赖项。

  • 在组件挂载时,Vue 会将这些依赖项存储在 refvalue 属性中。

(二)访问依赖

  • 通过 ref.value,你可以访问绑定的 DOM 元素或组件实例。

  • 如果绑定的是组件实例,你可以通过 ref.value 访问组件的 methodsdata 等属性。

(三)组件实例的保护

  • Vue 3 对组件实例的访问进行了保护,防止父组件直接访问子组件的内部状态。

  • 如果需要让父组件访问子组件的某些属性或方法,需要在子组件中使用 defineExpose 显式暴露。

子组件:使用 defineExpose 显式暴露需要被父组件访问的属性和方法。

父组件:通过 ref 绑定子组件实例,并访问子组件暴露的内容。

在 Vue 3 中,组件实例的保护机制是一个重要的特性,它防止父组件直接访问子组件的内部状态,从而确保组件的封装性和数据的安全性。如果需要让父组件访问子组件的某些属性或方法,必须在子组件中显式暴露这些内容。接下来,我们将通过一个实际例子来展示组件实例保护的机制。


组件实例保护的示例

1. 子组件 Person.vue

假设我们有一个子组件 Person.vue,它包含一些内部数据和方法。我们希望父组件能够访问其中的一部分数据和方法,但不是全部。

子组件代码

HTML复制

<template>
  <div>
    <h4>姓名:{{ name }}</h4>
    <h4>年龄:{{ age }}</h4>
    <button @click="sayHello">打招呼</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { defineExpose } from 'vue';

const name = ref('张三');
const age = ref(18);

const sayHello = () => {
  console.log(`你好,我叫${name.value},今年${age.value}岁了`);
};

// 显式暴露部分数据和方法
defineExpose({
  name, // 暴露姓名
  sayHello // 暴露打招呼的方法
});
</script>

2. 父组件

在父组件中,我们通过 ref 绑定子组件实例,并尝试访问子组件的属性和方法。

父组件代码

HTML复制

<template>
  <div>
    <Person ref="person" />
    <button @click="showName">显示姓名</button>
    <button @click="callSayHello">调用打招呼方法</button>
  </div>
</template>

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

const person = ref(null);

const showName = () => {
  console.log(person.value.name); // 访问子组件暴露的姓名
};

const callSayHello = () => {
  person.value.sayHello(); // 调用子组件暴露的方法
};
</script>

3. 运行效果

  • 点击“显示姓名”按钮

  • 控制台会输出子组件的 name 属性值,例如:“张三”。

  • 点击“调用打招呼方法”按钮

  • 控制台会输出子组件的 sayHello 方法的执行结果,例如:“你好,我叫张三,今年18岁了”


组件实例保护的作用体现了封装性和数据安全性,保护子组件的内部数据,防止被外部组件意外修改。

四、最佳实践

(一)普通 HTML 元素

  • 直接绑定 ref,访问 ref.value

HTML复制

<h2 ref="title2">北京</h2>

JavaScript复制

const title2 = ref(null);

const showTitle2 = () => {
  console.log(title2.value.textContent); // 输出 h2 的内容
};

(二)组件实例

  • 使用 defineExpose 显式暴露需要访问的属性和方法。

HTML复制

<Person ref="person" />

JavaScript复制

const person = ref(null);

const showPerson = () => {
  console.log(person.value); // 输出 Person 组件实例
};

五、总结

也就是说,如果你需要在 Vue 组件中动态操作 DOM 元素或组件实例,建议使用 ref。如果你需要在普通 HTML 中操作 DOM 元素,可以使用 id

通过上述问题和代码实现,你可以看到 ref 在动态操作 DOM 元素和组件实例时的简洁性和高效性。ref 自动追踪依赖项,无需显式指定,非常适合动态响应数据变化的场景。在实际开发中,你可以根据具体需求选择使用 ref,以实现更高效的数据监听和副作用管理。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。