• Vue3中如何使用ref获取元素节点全面解析


    Vue2 中的 ref

    <template>
      <div id="app">
        <div ref="hello">小猪课堂</div>
      </div>
    </template>
    <script>
    export default {
      mounted() {
        console.log(this.$refs.hello); // 
    小猪课堂
    }, }; </script>

    Vue3 中 ref 访问元素

    <template>
      <div ref="hello">小猪课堂</div>
    </template>
    <script setup lang="ts">
    import { onMounted, ref } from "vue";
    const hello = ref<any>(null);
    onMounted(() => {
      console.log(hello.value); // 
    小猪课堂
    }); </script>

    运行结果:
    在这里插入图片描述
    注意点:
    1.变量名称必须要与 ref 命名的属性名称一致。
    2.通过 hello.value 的形式获取 DOM 元素。
    3.必须要在 DOM 渲染完成后才可以获取 hello.value,否则就是 null。

    v-for 中使用 ref

    <template>
      <div ref="hello">小猪课堂</div>
      <ul>
        <li v-for="item in 10" ref="itemRefs">
          {{item}} - 小猪课堂
        </li>
      </ul>
    </template>
    <script setup lang="ts">
    import { onMounted, ref } from "vue";
    
    
    const itemRefs = ref<any>([]);
    onMounted(() => {
      console.log(itemRefs.value);
    });
    </script>
    

    运行的结果:
    在这里插入图片描述注意点:我们似乎没办法区分哪个 li 标签哪个 ref,除此之外,我们的 itemRefs 数组不能够保证与原数组顺序相同,即与 list 原数组中的元素一一对应。

    :ref 绑定函数
    ref 属性接收的是一个 setHelloRef 函数,该函数会默认接收一个 el 参数,这个参数就是我们需要获取的 div 元素。假如需求中我们采用这种方式的话,那么完全可以把 el 保存到一个变量中去,供后面使用。

    <template> 
      <div :ref="setHelloRef">小猪课堂</div>
    </template>
    <script setup lang="ts">
    import { ComponentPublicInstance, HTMLAttributes } from "vue";
    
    
    const setHelloRef = (el: HTMLElement | ComponentPublicInstance | HTMLAttributes) => {
      console.log(el); // 
    小猪课堂
    }; </script>

    v-for的更改后使用:方法1

    <template>
      <ul>
        <li v-for="item in 10" :ref="(el) => setItemRefs(el, item)">
          {{ item }} - 小猪课堂
        </li>
      </ul>
    </template>
    <script setup lang="ts">
    import { ComponentPublicInstance, HTMLAttributes, onMounted } from "vue";
    let itemRefs: Array<any> = [];
    const setItemRefs = (el: HTMLElement | ComponentPublicInstance | HTMLAttributes, item:number) => {
      if(el) {
        itemRefs.push({
          id: item,
          el,
        });
      }
    }
    onMounted(() => {
      console.log(itemRefs);
    });
    </script>
    

    运行的结果:
    在这里插入图片描述
    这种形式既让我们的操作性变得更大,还解决了 v-for 循环是 ref 数组与原数组顺序不对应的问题。

    v-for的更改后使用:方法2

    <template>
       <div ref='getDivDom' v-for="item in list" :data-id="item.id"></div> 
    </template>
    <script setup>
    import { ref} from 'vue'
    const divDomList = ref(new Map());
    
    const getDivDom = el=>{
        if(el){
            divDomList.set(el.dataset['id'],el) 
        }
    }
    
    // const el =divDomList.get(id) // 根据list数据中的id值 获取对应的dom元素 
    

    组件上使用 ref

    <template>
      <child ref="childRef"></child>
    </template>
    <script setup lang="ts">
    import { onMounted, ref } from "vue";
    import child from "./child.vue";
    const childRef = ref<any>(null);
    onMounted(() => {
      console.log(childRef.value); // child 组件实例
      console.log(childRef.value.message); // undefined
    });
    </script>
    
    <template>
      <div>{{ message }}</div>
    </template>
    <script lang="ts" setup>
    import { ref } from "vue";
    const message = ref<string>("我是子组件");
    const onChange = () => {};
    </script>
    

    运行的结果
    在这里插入图片描述

    childRef.value.message 为 undefined,这也是与 Vue2 的不同之处。在 Vue3 中,使用 ref 获取子组件时,如果想要获取子组件的数据或者方法,子组件可以通过defineExpose 方法暴露数据。

    改进组件上使用 ref的写法
    修改子组件代码:

    <template>
      <div>{{ message }}</div>
    </template>
    <script lang="ts" setup>
    import { ref } from "vue";
    
    
    const message = ref<string>("我是子组件");
    const onChange = () => {
      console.log("我是子组件方法")
    };
    defineExpose({
      message,
      onChange
    });
    </script>
    

    父组件再次获取:

    const childRef = ref<any>(null);
    onMounted(() => {
      console.log(childRef.value); // child 组件实例
      console.log(childRef.value.message); // 我是子组件
      childRef.value.onChange(); // 我是子组件方法
    });
    

    运行的结果:
    在这里插入图片描述

  • 相关阅读:
    前端vue实现圣杯布局【flex布局、浮动布局】
    完美指南|如何使用 ODBC 进行无代理 Oracle 数据库监控?
    2-8.基金客户服务
    计算机网络——TCP与UDP
    CF464E The Classic Problem
    JDY蓝牙注意事项
    DDL相关操作
    05.jvm常量池02
    DC-DC100V降压芯片,12V2A/5V2A降压型转换器,优势替代ETA1801
    编写汽车零部件开发问题分析报告培训与报告内容检查单
  • 原文地址:https://blog.csdn.net/zyf13671493506/article/details/127089780