Vue3中操作dom的四种方式,建议收藏!!!

avatar
作者
筋斗云
阅读量:0

文章目录


前言

最近主管提出了许多优化用户体验的要求,其中很多涉及 dom 操作。本文将 Vue3 中常见的 dom 操作总结了一下。觉得文章不错、或对自己开发有所帮助,欢迎点赞收藏!


一、通过 ref 拿到 dom 的引用

<template>     <div class="ref-container">         <div ref="sectionRef" class="ref-section"></div>     </div> </template>  <script lang="ts" setup> import { ref } from 'vue' const sectionRef = ref() </script> 

通过对 div 元素添加 ref 属性,为了获取到这个元素,我们声明了一个与 ref 属性名称相同的变量,然后通过 [变量名].value 的形式即可获取该 div 元素。

适用场景

  • 单一 dom 元素或者个数较少的场景

示例代码

<template>     <div class="ref-container">         <p>通过 ref 直接拿到 dom</p>         <div ref="sectionRef" class="ref-section"></div>         <button @click="action" class="btn">变高</button>     </div> </template>  <script lang="ts" setup> import { ref } from 'vue' const sectionRef = ref() let height = 100;  const action= () => {     height += 50;     sectionRef.value.style = `height: ${height}px`; } </script>  <style lang="scss" scoped> .demo1-container {     width: 100%;     height: 100%;      .ref-section {         width: 200px;         height: 100px;         background-color: pink;         transition: all .5s ease-in-out;     }      .btn {         width: 200px;         height: 50px;         background-color: gray;         color: #fff;         margin-top: 100px;     } } </style> 

二、通过父容器的 ref 遍历拿到 dom 引用

通过对父元素添加 ref 属性,并声明一个与 ref 属性名称相同的变量 list,此时通过 list.value 会获得包含子元素的 dom 对象。此时可以通过 list.value.children[index] 的形式获取子元素 dom

<template>     <div class="ref-container">         <div ref="list" class="list-section">             <div @click="higherAction(index)" class="list-item" v-for="(item, index) in state.list" :key="index">                 <span>{{item}}</span>             </div>         </div>     </div> </template>  <script lang="ts" setup> import { ref, reactive } from 'vue' const list = ref() 

适用场景

  • 通过 v-for 循环生成的固定数量元素的场景。

示例代码

<template>     <div class="ref-container">         <p>通过父容器遍历拿到dom</p>         <div ref="list" class="list-section">             <div @click="higherAction(index)" class="list-item" v-for="(item, index) in state.list" :key="index">                 <span>{{item}}</span>             </div>         </div>     </div> </template>  <script lang="ts" setup> import { ref, reactive } from 'vue' const list = ref() const state = reactive({     list: [1, 2, 3, 4, 5, 6, 7, 8] })  const higherAction = (index: number) => {     let height = listRef.value.children[index].style.height ? listRef.value.children[index].style.height : '20px';     height = Number(height.replace('px', ''));     listRef.value.children[index].style = `height: ${height + 20}px`; } </script>  <style lang="scss" scoped> .demo2-container {     width: 100%;     height: 100%;      .list-section {         width: 200px;         .list-item {             width: 200px;             height: 20px;             background-color: pink;             color: #333;             transition: all .5s ease-in-out;             display: flex;             justify-content: center;             align-items: center;         }     } } </style> 

三、通过子组件 emit 传递 ref

通过对子组件添加 ref 属性,并声明一个与 ref 属性名称相同的变量 childRef,此时通过 emitchildRef.value 作为一个 dom 引用传递出去。

<template>     <div ref="childRef" @click="cellAction" class="cell-item">         <span>{{item}}</span>     </div> </template>  <script lang="ts" setup> import { ref } from 'vue'  const props = defineProps({     item: Number }) const emit = defineEmits(['cellTap']); const childRef = ref(); const cellAction = () => {     emit('cellTap', childRef.value); } </script> 

适用场景

  • 多个页面都可能有操作组件 dom 的场景

示例代码

<template>     <div ref="childRef" @click="cellAction" class="cell-item">         <span>{{item}}</span>     </div> </template>  <script lang="ts" setup> import { ref } from 'vue'  const props = defineProps({     item: Number }) const emit = defineEmits(['cellTap']); const childRef = ref() const cellAction = () => {     emit('cellTap', childRef.value); } </script>  <style lang="scss" scoped> .cell-item {     width: 200px;     height: 20px;     background-color: pink;     color: #333;     transition: all .5s ease-in-out;     display: flex;     justify-content: center;     align-items: center; } </style> 
<template>     <div class="ref-container">         <p>通过子组件emit传递ref</p>         <div class="list-section">             <Cell :item="item" @cellTap="cellTapHandler" v-for="(item, index) in state.list" :key="index">             </Cell>         </div>     </div> </template>  <script lang="ts" setup> import { reactive } from 'vue' import Cell from '@/components/Cell.vue' const state = reactive({     list: [1, 2, 3, 4, 5, 6, 7],     refList: [] as Array<any> })  const cellTapHandler = (el: any) => {     let height = el.style.height ? el.style.height : '20px';     height = Number(height.replace('px', ''));     el.style = `height: ${height + 20}px`; } </script>  <style lang="scss" scoped> .demo2-container {     width: 100%;     height: 100%;      .list-section {         width: 200px;     } } </style> 

四、通过 :ref 将 dom 引用放到数组中

通过 :ref 循环调用 setRefAction 方法,该方法会默认接收一个 el 参数,这个参数就是我们需要获取的 div 元素。

<template>     <div class="ref-container">         <div class="list-section">             <div :ref="setRefAction" @click="higherAction(index)" class="list-item" v-for="(item, index) in state.list" :key="index">                 <span>{{item}}</span>             </div>         </div>     </div> </template>  <script lang="ts" setup> import { reactive } from 'vue'  const state = reactive({     list: [1, 2, 3, 4, 5, 6, 7],     refList: [] as Array<any> })  const setRefAction = (el: any) => {     state.refList.push(el); } </script> 

此时可以通过 state.refList[index] 的形式获取子元素 dom

适用场景

  • 通过 v-for 循环生成的不固定数量或者多种元素的场景。

示例代码

<template>     <div class="ref-container">         <p>通过:ref将dom引用放到数组中</p>         <div class="list-section">             <div :ref="setRefAction" @click="higherAction(index)" class="list-item" v-for="(item, index) in state.list" :key="index">                 <span>{{item}}</span>             </div>         </div>     </div> </template>  <script lang="ts" setup> import { reactive } from 'vue'  const state = reactive({     list: [1, 2, 3, 4, 5, 6, 7],     refList: [] as Array<any> })  const higherAction = (index: number) => {     let height = state.refList[index].style.height ? state.refList[index].style.height : '20px';     height = Number(height.replace('px', ''));     state.refList[index].style = `height: ${height + 20}px`;     console.log(state.refList[index]); }  const setRefAction = (el: any) => {     state.refList.push(el); } </script>  <style lang="scss" scoped> .demo2-container {     width: 100%;     height: 100%;      .list-section {         width: 200px;         .list-item {             width: 200px;             height: 20px;             background-color: pink;             color: #333;             transition: all .5s ease-in-out;             display: flex;             justify-content: center;             align-items: center;         }     } } </style> 

总结

经过了不断探索终于完成了,事后想了一下还是自己的本事不到家,以后还是需要不断提升自己的能力 ~ ~ ~

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!