Vue中四种操作dom方法保姆级讲解

 更新时间:2023年02月01日 09:37:07   作者:山山而川~xyj  
这篇文章主要介绍了Vue中四种操作dom方法,首先,在vue中强烈禁用原生与jquery来操作DOM元素。我们要充分的利用vue的优势:MVVM,在vue中程序员几乎不操作DOM,只需要维护好数据即可,vue给程序员提供ref引用,不调用api直接获取元素组件的使用

前言

最近主管提出了许多优化用户体验的要求,其中很多涉及 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>

到此这篇关于Vue中四种操作dom方法保姆级讲解的文章就介绍到这了,更多相关Vue操作dom内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue动态设置页面title的方法实例

    vue动态设置页面title的方法实例

    这篇文章主要给大家介绍了关于vue动态设置页面title的相关资料,文中通过实例代码结束的非常详细,对大家学习或者使用Vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • 解决vue前后端端口不一致的问题

    解决vue前后端端口不一致的问题

    这篇文章主要介绍了解决vue前后端端口不一致的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Vue简单实现原理详解

    Vue简单实现原理详解

    这篇文章主要介绍了Vue简单实现原理,结合实例形式详细分析了Vue实现原理与操作注意事项,需要的朋友可以参考下
    2020-05-05
  • vue实现简洁文件上传进度条功能

    vue实现简洁文件上传进度条功能

    这篇文章主要介绍了vue实现简洁文件上传进度条功能,实现原理是通过performance.now()获取动画的时间戳,用于创建流畅的动画,结合示例代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • vue项目使用axios封装request请求的过程

    vue项目使用axios封装request请求的过程

    这篇文章主要介绍了vue项目使用axios封装request请求,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • vue实现书籍购物车功能

    vue实现书籍购物车功能

    这篇文章主要为大家详细介绍了vue实现书籍购物车功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • vue简单练习 桌面时钟的实现代码实例

    vue简单练习 桌面时钟的实现代码实例

    这篇文章主要介绍了vue简单练习 桌面时钟的实现代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值的相关资料,需要的朋友可以参考下
    2019-09-09
  • 解决vite build打包后页面不能正常访问的情况

    解决vite build打包后页面不能正常访问的情况

    这篇文章主要介绍了解决Vite打包后直接使用浏览器打开,显示空白问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue.js element-ui tree树形控件改iview的方法

    vue.js element-ui tree树形控件改iview的方法

    这篇文章主要介绍了vue.js element-ui tree树形控件改iview的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • vue router导航守卫(router.beforeEach())的使用详解

    vue router导航守卫(router.beforeEach())的使用详解

    导航守卫主要用来通过跳转或取消的方式守卫导航。这篇文章主要介绍了vue-router导航守卫(router.beforeEach())的使用,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04

最新评论