likes
comments
collection
share

你会用JS进行DOM操作,Vue3呢?

作者站长头像
站长
· 阅读数 23

前言

在Vue3框架的精彩世界时,ref是连接Vue响应式系统与底层DOM结构的桥梁。在Vue框架内应用ref特性,显著增强了代码的清晰度和可维护性,因为它明确指明了组件内部哪些元素或组件实例将被操作。回顾JavaScript中的DOM操作,在原生JS中,我们通常通过document.getElementById, document.querySelector等方法来选取页面上的DOM元素,随后直接调用这些元素的属性或方法来修改它们的状态。

例如,改变一个元素的文本内容可以这样做:

let element = document.getElementById('myElement');
element.textContent = '新的内容';

这种方法直接而有效,但在复杂的单页应用(SPA)中容易导致代码难以维护,尤其是当DOM结构频繁变动时。下面我将为大家介绍在Vue3如何使用功能更加强大且灵活的ref来实现DOM操作。

1. ref的基本使用

在Vue中,你可以通过在模板中定义ref属性,然后在组件的setup()函数中通过refs对象访问这些DOM元素。

<template>
  <div>
    <p ref="myParagraph">原始内容</p>
  </div>
</template>

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

onMounted(() => {
  // 使用ref获取DOM元素
  const myParagraph = ref(null);

  // 确保DOM已挂载后操作
  if (myParagraph.value) {
    myParagraph.value.textContent = '通过Vue ref修改的内容';
  }
});
</script>

在该组件成功挂载之后,p标签中的内容将会被替换。

错误的使用示范

在使用ref访问DOM时,尝试在Vue组件的setup函数外部或在不恰当的生命周期阶段访问通过ref定义的DOM元素。

<template>
  <div ref="exampleRef">Hello Vue!</div>
</template>

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

const exampleRef = ref(null);

// 尝试在setup函数内部立即访问DOM,但此时DOM还未挂载
console.log(exampleRef.value); // 输出: null,因为此时DOM还没被挂载

// 或者错误地在一个定时器中尝试访问,即使在mounted之后,但未确保DOM访问时机
setTimeout(() => {
  console.log(exampleRef.value); // 可能输出null,取决于定时器执行时机与DOM挂载完成的相对时间
}, 1000);
</script>

在这段错误的使用ref的示范中我们可以看到,ref访问DOM元素时并不能立即访问,必须要等待DOM成功挂载之后再进行访问,否则会报错。

2. ref的应用场景

获取多个子元素的DOM引用

在Vue3,如果需要通过父容器的ref遍历其下的多个子元素获取DOM引用,通常是使用v-for循环生成一组DOM元素,然后定义一个父容器的ref,并通过它来遍历获取内部由v-for生成的DOM元素的引用:

<template>
  <div ref="parentContainer">
    <div v-for="(item, index) in items" :key="index" :ref="setChildRef">
      {{ item }}
    </div>
  </div>
</template>

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

// 假设items是你的数据源
const items = ref(['Item 1', 'Item 2', 'Item 3'])

// 定义一个方法来收集子元素的引用
const childRefs = ref([]) as any // 类型断言,根据实际类型调整
const setChildRef = (el: HTMLElement | undefined) => {
  if (el) {
    childRefs.value.push(el)
  }
}

// 父容器的ref
const parentContainer = ref(null)

onMounted(() => {
  // 在组件挂载完成后,可以通过parentContainer.value直接访问父容器的DOM
  console.log('Parent Container:', parentContainer.value)

  // 遍历并操作子元素的DOM引用
  childRefs.value.forEach((childRef, index) => {
    console.log(`Child ${index + 1} DOM Element:`, childRef)
    // 这里可以对每个childRef执行DOM操作,例如设置样式等
  })
})
</script>

在这个例子中,setChildRef 方法会在每个循环生成的元素上被调用,并将DOM元素的引用收集到childRefs数组中。然后在onMounted生命周期钩子中,你可以遍历childRefs数组,对每个子元素的DOM进行操作。注意,使用:ref结合一个方法时,需要在方法名前加上冒号(`:》来表示这是一个动态绑定。

收集DOM引用

在Vue中,使用:ref属性可以将DOM元素或者子组件的实例绑定到父组件的this.$refs对象上。如果:ref用在循环中,绑定的元素或组件实例会自动收集到一个数组中。下面是一个具体的实例,演示如何将一组由v-for生成的按钮的DOM引用存储到一个数组里:

<template>
  <div>
    <button v-for="(item, index) in items" :key="index" :ref="`button-${index}`">
      Button {{ item }}
    </button>
    <button @click="handleClick">点击我获取按钮引用</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [1, 2, 3, 4, 5], // 假设这是你的数据列表
    };
  },
  methods: {
    handleClick() {
      // 使用this.$refs获取所有按钮的引用
      console.log(this.$refs['button']);

      // 如果你想对这些按钮做些什么,比如改变第一个按钮的文字颜色
      // 注意:实际操作中应确保DOM操作的安全性,这里仅为示例
      this.$refs['button'][0].style.color = 'red';
    },
  },
};
</script>

在这个例子中,每个按钮都有一个动态的:ref属性,形式为button-index,这样在Vue实例的{index},这样在Vue实例的index,这样在Vue实例的refs对象中,就会创建一个名为button的数组,数组中的每个元素分别对应一个按钮的DOM引用。点击“点击我获取按钮引用”的按钮时,handleClick方法会被调用,展示或操作这些按钮的引用。

总结

ref的优势

  1. 响应式友好:Vue的ref与Vue的响应式系统紧密结合,这意味着当引用的DOM元素发生变化时,Vue能自动处理相关的更新逻辑。
  2. 代码清晰:通过在模板中明确标注ref,提高了代码的可读性和维护性,团队成员可以快速定位和理解哪些元素会被操作。
  3. 生命周期集成:Vue提供了如onMounted等生命周期钩子,确保DOM操作在合适的时机执行,避免了未挂载元素的访问错误。
  4. 组件化思维:与Vue的组件体系完美融合,使得在组件间传递和操作DOM引用变得更加自然和高效。

本篇文章就到此为止啦,希望通过这篇文章能对你理解Vue3中使用ref进行DOM操作有所帮助,本人水平有限难免会有纰漏,欢迎大家指正。如觉得这篇文章对你有帮助的话,欢迎点赞收藏加关注,感谢支持🌹🌹。

你会用JS进行DOM操作,Vue3呢?

转载自:https://juejin.cn/post/7386514632726134818
评论
请登录