标签的ref属性

标签的ref属性

当我们想要获取一个标签对应的 DOM 元素的时候在 JavaScript 中,我们通过 document.getElementById() 来借助类选择器的写法获取,但是在 Vue 中,我们的 DOM 元素是挂载在同一个网页上的,这些名称难免会重复,所以需要别的方式去获取,给标签添加ref属性正好可以解决这个问题。

使用

加在Html标签

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

    let myRef = ref(); 

    function changeH1() {
      console.log(myRef.value);
    }
</script>

<template>
  <div class="class">
    <h1 ref="myRef">标签ref</h1>
    <br>
    <button @click="changeH1">获取h1标签值</button>
  </div>  
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>

只需要在对应标签里面加入 ref 属性,然后在 script 标签里面定义即可。

加在组件上

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

    let myRef = ref(); 
    let car = ref();

    function changeH1() {
      console.log(myRef.value);
    }

    function getCar() {
      console.log(car.value);
    }
</script>

<template>
  <div class="class">
    <h1 ref="myRef">标签ref</h1>
    <br>
    <button @click="changeH1">获取h1标签值</button>
    <br>
    <button @click="getCar">获取Car组件的值</button>
  </div>
  <Car ref="car" />
  
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>
<script lang="ts" setup name="Car">
    import { ref, defineExpose } from 'vue'

    let brand = ref("奔驰")
    let price = ref(30)

    function changePrice() {
      price.value += 10
    }  

    function changeBrand() {
      brand.value = "宝马"
    }

    // 向外暴露brand和price
    defineExpose({ brand, price })
</script>

<template>
  <div class="class">
    <h2>品牌:{{ brand }}</h2>
    <h2>价格:{{ price }}万</h2>
    <button @click="changePrice">点击价格+10</button>
    <br/>
    <button @click="changeBrand">修改品牌</button>
  </div>
</template>

<style scoped>
  .class {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      height: 100%; /* 使内容占满整个高度 */
      color: rgb(214, 12, 12);
      font-size: 20px;
  }

  button {
      background-color: blue;
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 5px;
      cursor: pointer;
      margin-top: 10px;
  }
</style>

在这里插入图片描述

<think>好的,我现在需要解决用户关于Vue3的ref属性的问题。用户之前询问过el-table组件和图标显示的问题,现在转向了Vue3的ref属性。我需要详细解释ref的用法、原理以及常见问题,并提供相关代码示例。首先,我应该回顾Vue3中ref的基本用法,包括如何创建响应式数据,以及在模板和脚本中的使用方式。用户可能对ref和reactive的区别有疑问,需要明确两者适用场景的不同。同时,模板引用(即使用ref属性获取DOM元素或组件实例)也是一个重点,要说明在组合式API和选项式API中的不同写法。接下来,要考虑用户可能遇到的问题,比如为什么DOM引用有时是null,或者如何正确使用组件的方法。需要解释在生命周期钩子中访问引用的时机,以及如何通过nextTick确保DOM更新后的正确访问。此外,用户可能对ref和shallowRef的区别不太清楚,需要对比说明两者的使用场景。同时,TypeScript的支持也是一个重要点,特别是如何通过泛型来指定引用的类型,避免类型错误。在代码示例方面,应该涵盖基本使用、模板引用、组件方法调用、forwardRef的使用,以及TypeScript的例子。每个示例要简洁明了,突出关键点,并注释说明注意事项。最后,提出的相关问题需要覆盖ref的常见疑问,如与reactive的区别、模板引用的使用、shallowRef的作用以及TypeScript处理,确保用户能进一步深入学习相关知识点。</think>以下是关于Vue3 ref属性的详细解析: ### 一、ref的核心作用 Vue3的ref用于创建响应式数据引用,主要处理以下场景: ```vue <script setup> import { ref } from 'vue' // 基本类型响应式 const count = ref(0) // 引用类型响应式 const user = ref({ name: '张三' }) // 模板引用 const inputRef = ref(null) </script> ``` ### 二、实现原理 1. **响应式转换**: - 通过`new Proxy()`实现数据劫持 - 对基本类型进行对象包装(value属性) - 自动触发依赖追踪和更新 2. **模板引用**: ```vue <template> <input ref="inputRef"> <child-component ref="childRef"></child-component> </template> <script setup> const inputRef = ref(null) // 获取DOM元素 const childRef = ref(null) // 获取组件实例 </script> ``` ### 三、典型使用场景 #### 场景1:基本类型响应式 ```vue <script setup> const count = ref(0) const increment = () => count.value++ // 必须使用.value </script> <template> <button @click="increment">{{ count }}</button> </template> ``` #### 场景2:DOM元素引用 ```vue <template> <input ref="myInput"> <button @click="focusInput">聚焦输入框</button> </template> <script setup> const myInput = ref(null) const focusInput = () => { myInput.value?.focus() // 安全访问 } </script> ``` #### 场景3:组件方法调用 ```vue <!-- 子组件 --> <script setup> defineExpose({ showMessage: () => console.log('Hello from child') }) </script> <!-- 父组件 --> <template> <child ref="childRef"></child> </template> <script setup> const childRef = ref(null) childRef.value?.showMessage() </script> ``` ### 四、特殊用法 #### 1. 响应式对象解构 ```vue <script setup> const state = ref({ x: 1, y: 2 }) // 保持响应性 const { x, y } = toRefs(state.value) </script> ``` #### 2. 配合forwardRef ```vue <!-- 子组件 --> <script setup> import { forwardRef } from 'vue' const props = defineProps({ msg: String }) defineExpose({ customMethod: () => {} }) </script> <template> <div ref="forwardRef">{{ msg }}</div> </template> ``` ### 五、常见问题解决方案 #### 问题1:为什么ref.value有时是null? ```vue <script setup> const el = ref(null) onMounted(() => { // 正确访问时机 console.log(el.value) // 此时DOM已挂载 }) </script> ``` #### 问题2:如何响应式更新对象? ```vue <script setup> const obj = ref({ a: 1 }) // 正确方式 obj.value = { ...obj.value, b: 2 } // 错误方式:不会触发更新 obj.value.b = 2 </script> ``` ### 六、TypeScript支持 ```typescript // 类型声明 const inputRef = ref<HTMLInputElement | null>(null) const user = ref<{ name: string }>({ name: '' }) ``` ### 实现原理细节 1. **引用包装**:通过`{ value: ... }`对象包装原始值 2. **依赖收集**:在getter中收集依赖 3. **触发更新**:在setter中触发副作用函数 4. **模板特殊处理**:编译器自动解套模板中的ref
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值