标签中的ref属性

之前说过了 ref() 函数,现在说的标签中的 ref 属性 和 ref() 函数也存在一定关联。

2、

标签中的 ref 属性分为两种情况:

  • 用在普通DOM标签上,获取的是DOM节点。

  • 用在组件标签上,获取的是组件实例对象

Vue2 中标签上的 ref 属性

在Vue2 中, 当在 普通 DOM 元素上使用 ref 时,可以直接通过 this.$refs 拿到这个 DOM元素以及 DOM 元素中的某些值(value、innerHTML 等),例如:

<template>
  <input type="text" ref="input"> <br><br>
  <button @click="showDOM">获取DOM节点</button>
  <button @click="showValue">获取DOM节点内容</button>
</template>

<script>
export default {
  name: "App",
  methods: {
    showDOM() {
      console.log(this.$refs.input);
    },
    showValue() {
      console.log(this.$refs.input.value);
    }
  }
}
</script>

Vue2 中的组件上的 ref 属性

ref 属性也可以用在组件上,获取的是组件的实例对象

<template>
  <Child ref='Child'/>
  <button @click="showDOM">获取组件实例</button> <br>
</template>

<script>
import Child from './components/Child.vue';
export default {
  name: "App",
  methods: {
    showDOM() {
      console.log(this.$refs.Child);
    },
  },
  components: { Child }
}
</script>

Vue3 中【 标签 】上的 ref 属性 +【 setup() 函数

 在模板中的使用方式和 Vue2 一致,直接当做标签属性使用即可

<template>
  <h2 ref="title">父组件内容</h2> <br>
  <button @click="showDOM">获取DOM节点</button> <br>
</template>

但是,在 setup() 函数中的使用方式存在差异。

首先 需要通过 ref() 函数来创建一个空的 ref 对象。

然后通过变量接收,且该变量名称需要与 DOM 标签上的 ref 属性值相同。

<script>
import {ref} from 'vue'
export default {
  name: "App",
  setup(props, context) {
    // 通过 ref() 函数创建一个空的 ref 对象,
    // 且通过与DOM元素上ref属性值一致的 title 作为变量接收 
    let title = ref()

    function showDOM() {
      console.log(title.value);
    }

    return {
      title,
      showDOM,
    }
  },
}
</script>

展示效果:拿到了完整的DOM节点

Vue3 中【 组件标签 】上的 ref 属性 + 【 setup() 函数

在父组件中引入子组件,然后在子组件标签上添加 ref 属性。在 setup() 函数中同样通过 与 ref 属性值相同的变量名接收空的 ref 对象

<template>
  <Child ref="child"/>
  <button @click="showCompoment">获取组件实例</button>
</template>

<script>
import Child from './components/Child.vue';
import {ref} from 'vue'
export default {
  name: "App",
  setup() {
    
    let child = ref()

    function showCompoment() {
      console.log(child.value);
    }

    return {
      child,
      showCompoment
    }
  },
  components: { Child }
}
</script>

然后在子组件中 通过 ref() 定义几个响应式数据,但是没有使用,也没有返回。按照Vue2 的情况,此时在父组件中是可以访问到子组件中的数据的,但是通过打印,我们发现什么都没拿到。

<template>
  <div>
    这是子组件
  </div>
</template>

<script>
import { ref } from 'vue'
export default {
  name: 'ChildComponent',
  setup() {
    let name = ref('al')
    let age = ref(29)
    return {}
  }
}
</script>

展示效果

此时我们将数据通过 return 返回。

setup() {
  let name = ref('al')
  let age = ref(29)

  return {
    name,age
  }
}

此时会发现,在父组件中能拿到返回出去的值了。

这说明了两点

  • ref 获取的是组件实例:通过 ref 属性获取的是子组件的实例对象

  • 访问公开的数据:只能访问子组件通过 setup 返回的、被公开的响应式数据或方法。子组件中的私有状态或未返回的数据是无法直接访问的。

于此同时,还有一种方式可以对外暴露数据,那就是 setup() 函数中接收的第二个参数 context。该参数是一个对象,对象中有一个属性为 expose。该属性是一个方法,接收一个对象,对象内部则是向外暴露的指定数据或方法。

setup(props, context) {
  let name = ref("al");
  let age = ref(29);
  function text() { }

  // 通过 context.expose 向外暴露指定的属性或方法
  context.expose({ text });
    
  // 返回值为空
  return { name, age };
},

 父组件中接收到了 子组件中暴露的指定数据和方法。但是对于 return 返回出去的方法或数据并没有接收到

Vue3 中【 组件标签 】上的 ref 属性 + 【 <script setup> 】

在 setup() 函数中,我们可以通过 return 来返回数据暴露给父组件,也可以通过 expose() 向外暴露指定的属性和方法。那么在 <script setup> 中没有 context.expose(),也不能通过 return 返回,此时又该怎么办呢?

Vue3 提供了一个新的 宏方法 -- defineExpose() ,可以在 <script setup> 】模式中向外暴露指定的数据或方法。

子组件:定义三个数据和方法,但是并没有显式的 return 返回

<template>
  <div>这是子组件</div>
</template>

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

let name = ref("al");
let age = ref(29);
function text() { }

</script>

父组件中获取子组件中的数据

<template>
  <Child ref="child"/>
  <button @click="showCompoment">获取组件实例</button>
</template>

<script>
import Child from './components/Child.vue';
import {ref} from 'vue'
export default {
  name: "App",
  setup() {
    let child = ref()
    
    function showCompoment() {
      console.log(child.value,'child');
    }

    return {
      child,
      showCompoment
    }
  },
  components: { Child }
}
</script>

展示效果:获取为空,数据或方法都没有获取到

通过 defineExpose() 向外暴露指定的数据或方法

<script setup lang="ts">
import { ref ,defineExpose} from "vue";

let name = ref("al");
let age = ref(29);
function text() { }

defineExpose({ name, age, text });

</script>

展示效果:父组件获取到了子组件指定暴露的数据和方法

总结

1、在标签中添加 ref 属性的同时,需要在 脚本中 通过 ref() 函数定义一个容器来放置 给ref属性打上标签的DOM或组件实例,且接收的变量需要 与 标签中的ref 属性值相同。

2、标签中的 ref 属性允许在一个特定的 DOM 元素或子组件实例被挂载后,获得对它的直接引用。可能存在的情况是,在挂载之前,ref() 函数已经执行,此时获取的引用则是undefined,在挂载之后,Vue 底层会自动找到对应的 ref() 与 经过ref 标记的DOM或组件,并赋值给 Value属性。

3、在Vue2 中,通过 this.$refs.xx 的方式,是可以直接获取组件实例对象上的任意方法或属性的,但是 Vue3 中禁止了这一情况。取而代之的是通过指定暴露的方式像父组件暴露数据或方法,这是因为 按照Vue3 的指定暴露方法,可以降低耦合度,增强组件封装性。

4、Vue3 中 存在两种情况,一种是 setup() 函数,一种是<script setup>,在这两种情况中对外暴露指定数据或方法的逻辑代码不一致。

  • setup() 函数:setup函数接收两个对象参数(props,context),context对象中存在 expose 方法,该方法接收一个空值或一个对象。若为空,则表示不对外暴露任意数据方法,若为对象,则表示只对外暴露对象内部属性或方法。
  • <script setup>:通过 新的 API defineExpose() 来指定对外暴露的数据或方法。 

5、父组件只能访问子组件通过 setup 返回的、被公开的响应式数据或方法。子组件中的私有状态或未返回的数据是无法直接访问的。( 如果没有指定暴露数据,则 setup()函数中 return 出去的数据 父组件都能接受到。如果指定了暴露数据,父组件则只能接收到指定暴露的数据,return中的其他方法不能接收 )

6、<script setup> 中的代码会在编译时,生成一个 setup() 函数,将<script setup> 中的脚本经过编译后塞到 setup() 函数中。

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Vue 3 ,`ref` 是一个新的响应式 API,用于在模板引用一个元素或组件,并可以在 JavaScript 代码访问该元素或组件的属性和方法。 在模板,可以使用 `ref` 指令来创建一个 `ref` 对象,并将其绑定到一个元素或组件上。例如: ```html <template> <div> <input type="text" ref="inputRef" /> <button @click="handleClick">Click Me</button> </div> </template> <script> import { ref } from 'vue'; export default { setup() { const inputRef = ref(null); function handleClick() { inputRef.value.focus(); } return { inputRef, handleClick, }; }, }; </script> ``` 在这个例子,我们使用 `ref` 指令将 `input` 元素绑定到 `inputRef` 变量上。在 `setup` 函数,我们使用 `ref` 函数创建了一个 `ref` 对象,并将其初始值设置为 `null`。然后,我们在 `handleClick` 函数访问了 `inputRef.value`,并调用了 `focus` 方法,以便将焦点设置到 `input` 元素上。 需要注意的是,在 Vue 3 ,`ref` 不再返回一个对象,而是返回一个包含 `value` 属性的普通 JavaScript 对象。因此,在访问 `ref` 对象的属性和方法时,需要使用 `.value` 来访问其值。 另外,在 Vue 3 ,`ref` 还可以用于引用组件,例如: ```html <template> <div> <MyComponent ref="myComponentRef" /> <button @click="handleClick">Click Me</button> </div> </template> <script> import { ref } from 'vue'; import MyComponent from './MyComponent.vue'; export default { components: { MyComponent, }, setup() { const myComponentRef = ref(null); function handleClick() { myComponentRef.value.someMethod(); } return { myComponentRef, handleClick, }; }, }; </script> ``` 在这个例子,我们使用 `ref` 指令将 `MyComponent` 组件绑定到 `myComponentRef` 变量上。在 `setup` 函数,我们使用 `ref` 函数创建了一个 `ref` 对象,并将其初始值设置为 `null`。然后,我们在 `handleClick` 函数访问了 `myComponentRef.value`,并调用了 `someMethod` 方法,以便调用 `MyComponent` 组件的某个方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值