青少年编程与数学 02-006 前端开发框架VUE 15课题、模板引用

青少年编程与数学 02-006 前端开发框架VUE 15课题、模板引用

课题摘要:本文介绍了Vue中的模板引用(Template Refs),它允许访问DOM元素或子组件实例以进行交互。模板引用通过ref属性创建,并在组件渲染完成后可访问。文章讨论了模板引用的用途,包括DOM操作、子组件访问、焦点管理和媒体播放控制。示例代码展示了如何通过模板引用操作输入框,包括聚焦和获取值。注意事项包括模板引用的渲染时机、条件渲染和列表渲染中的使用限制。文章还介绍了useTemplateRef()方法,用于在组合式API中获取模板引用。最后,提供了一个项目示例,展示了如何使用模板引用操作DOM元素。


一、模板引用

在Vue中,模板引用(Template Refs)是一种特殊的属性(ref),用于给元素或子组件注册引用信息。通过模板引用,你可以访问DOM元素或子组件实例,以便直接与它们进行交互。

以下是模板引用的一些常见用途:

  1. 访问DOM元素:获取DOM元素的引用,以便进行原生DOM操作,如获取元素的尺寸、位置或执行动画。

  2. 访问子组件实例:获取子组件的实例,以便调用其方法或访问其数据。

  3. 焦点管理:控制输入框或其他可聚焦元素的焦点。

  4. 媒体播放控制:控制视频或音频元素的播放。

使用模板引用

在Vue模板中,你可以通过ref属性为元素或子组件添加引用:

html 复制代码
<template>
  <input ref="inputRef" />
  <button @click="focusInput">Focus Input</button>
</template>

<script setup>
import { ref } from 'vue';

const inputRef = ref(null);

function focusInput() {
  inputRef.value.focus();
}
</script>

在这个例子中,inputRef是一个模板引用,它引用了模板中的<input>元素。通过inputRef.value,我们可以直接访问这个DOM元素,并调用其focus方法。

组件中的模板引用

你也可以在组件中使用模板引用来访问子组件实例:

html 复制代码
<template>
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const childRef = ref(null);

// 调用子组件的方法
function callChildMethod() {
  childRef.value.someMethod();
}
</script>

在这个例子中,childRef引用了ChildComponent的实例,你可以通过childRef.value来访问子组件的属性和方法。

注意事项

  • 模板引用在组件渲染完成后才可访问,即在mounted生命周期钩子之后。
  • 模板引用不会触发组件的重新渲染。
  • 如果元素或子组件被条件渲染(如v-if、v-show)或循环渲染(如v-for),则需要确保在访问引用时它们是存在的。

模板引用提供了一种直接与DOM元素或子组件实例交互的方式,使得你可以执行一些Vue响应式系统之外的操作。

二、使用限制

模板引用(Template Refs)在Vue中是一个非常有用的功能,但它也有一些限制和注意事项:

  1. 渲染时机:

    • 模板引用在组件渲染完成后才可用。这意味着你不能在setup函数或生命周期钩子beforeMount中访问它们,因为在这些阶段DOM还未渲染完成。
  2. 条件渲染:

    • 如果一个元素被v-if条件渲染,那么在条件为false时,该元素的引用将为null。你需要确保在条件为true时再访问引用。
  3. 列表渲染:

    • 当使用v-for时,每个循环项都会有一个模板引用,但你需要通过函数或具名插槽来访问它们,因为它们不是简单地附加到循环项的上下文。
  4. 动态组件和v-if:

    • 如果一个组件被包裹在v-if中,或者是一个动态组件,那么它的模板引用可能在组件切换时发生变化,因为旧的组件实例会被销毁,而新的组件实例会被创建。
  5. 响应式:

    • 模板引用本身不是响应式的,它们只是对DOM元素或子组件实例的普通引用。如果你需要响应式地监控引用的变化,你需要使用watch或watchEffect来观察ref的变化。
  6. 跨组件通信:

    • 模板引用不能直接用于跨组件通信。如果你需要访问另一个组件的内部状态或方法,你应该使用props、emit或provide/inject。
  7. 全局方法:

    • Vue没有提供全局方法来访问所有模板引用,你需要在每个组件内部单独声明和管理它们。
  8. 样式和类绑定:

    • 模板引用不会影响元素的样式或类绑定,它们只是提供了对DOM元素的直接访问。
  9. 限制性:

    • 模板引用主要用于直接操作DOM,这与Vue的声明式渲染原则相违背。因此,应该谨慎使用,并尽可能使用Vue的声明式API来处理。
  10. 代码组织:

    • 过度使用模板引用可能会导致代码难以维护,因为它使得组件之间的耦合更加紧密,且容易出错。
  11. SSR限制:

    • 在服务器端渲染(SSR)的应用中,模板引用在服务器端不可用,因为服务器端没有DOM。
  12. 类型检查:

    • 如果你使用TypeScript,可能需要为模板引用提供额外的类型注解,以确保类型安全。

使用模板引用时,应该遵循Vue的最佳实践,尽可能保持代码的声明性和可维护性。在大多数情况下,Vue的响应式系统和组件通信机制应该足以处理应用的状态和交互,而无需直接操作DOM。

三、访问模板引用

要在组合式 API 中获取引用,我们可以使用辅助函数 useTemplateRef() :(新方法)

vue

vue 复制代码
<script setup>
import { useTemplateRef, onMounted } from 'vue'

// 第一个参数必须与模板中的 ref 值匹配
const input = useTemplateRef('my-input')

onMounted(() => {
  input.value.focus()
})
</script>

<template>
  <input ref="my-input" />
</template>

在使用 TypeScript 时,Vue 的 IDE 支持和 vue-tsc 将根据匹配的 ref attribute 所用的元素或组件自动推断 inputRef.value 的类型。
3.5 前的用法

复制代码
复制代码

注意,你只可以在组件挂载后 才能访问模板引用。如果你想在模板中的表达式上访问 input,在初次渲染时会是 null。这是因为在初次渲染前这个元素还不存在呢!

如果你需要侦听一个模板引用 ref 的变化,确保考虑到其值为 null 的情况:

js

javascript 复制代码
watchEffect(() => {
  if (input.value) {
    input.value.focus()
  } else {
    // 此时还未挂载,或此元素已经被卸载(例如通过 v-if 控制)
  }
})

四、v-for 中的模板引用

需要 v3.2.25 及以上版本。

当在 v-for 中使用模板引用时,对应的 ref 中包含的值是一个数组,它将在元素被挂载后包含对应整个列表的所有元素:

vue

vue 复制代码
<script setup>
import { ref, useTemplateRef, onMounted } from 'vue'

const list = ref([
  /* ... */
])

const itemRefs = useTemplateRef('items')

onMounted(() => console.log(itemRefs.value))
</script>

<template>
  <ul>
    <li v-for="item in list" ref="items">
      {{ item }}
    </li>
  </ul>
</template>

应该注意的是,ref 数组并不保证与源数组相同的顺序。

五、应用示例

好的,下面是一个使用Vue 3和Vite创建的项目示例,这个项目将展示如何使用模板引用来操作DOM元素。

步骤 1:创建Vite项目

首先,确保你已经安装了Node.js和npm/yarn。然后,使用以下命令创建一个新的Vite项目:

bash 复制代码
# 使用npm
npm create vite@latest my-template-refs-vue-app -- --template vue

# 或者使用yarn
yarn create vite my-template-refs-vue-app --template vue

进入项目目录:

bash 复制代码
cd my-template-refs-vue-app

步骤 2:安装Vue 3

确保项目使用的是Vue 3:

bash 复制代码
npm install vue@next

步骤 3:创建模板引用组件

在src目录下创建一个新文件TemplateRefsComponent.vue。

TemplateRefsComponent.vue:

html 复制代码
<template>
  <div>
    <h1>Template Refs Example</h1>
    <!-- 使用ref属性为input元素创建模板引用 -->
    <input ref="inputRef" placeholder="Type something..." />
    <!-- 使用模板引用调用focus方法 -->
    <button @click="focusInput">Focus Input</button>
    <!-- 使用模板引用获取input的值 -->
    <button @click="printInputValue">Print Input Value</button>
    <!-- 显示input的值 -->
    <p>Input Value: {{ inputValue }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// 创建一个响应式变量来存储input的值
const inputValue = ref('');

// 创建模板引用,指向input元素
const inputRef = ref(null);

// 定义一个方法,使用模板引用来聚焦input元素
function focusInput() {
  inputRef.value.focus();
}

// 定义一个方法,使用模板引用来获取input的值,并更新inputValue响应式变量
function printInputValue() {
  inputValue.value = inputRef.value.value;
}
</script>

<style scoped>
button {
  margin: 5px;
}
</style>

步骤 4:在App.vue中使用TemplateRefsComponent

编辑src/App.vue文件,引入并使用TemplateRefsComponent:

html 复制代码
<template>
  <div id="app">
    <template-refs-component />
  </div>
</template>

<script setup>
import TemplateRefsComponent from './components/TemplateRefsComponent.vue';
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

步骤 5:运行项目

使用以下命令启动开发服务器:

bash 复制代码
npm run dev

# 或者使用yarn
yarn dev

现在,你可以在浏览器中访问http://localhost:3000来查看你的应用。你可以通过点击"Focus Input"按钮来聚焦到输入框,点击"Print Input Value"按钮来打印输入框的值。

项目说明

这个项目包含了一个TemplateRefsComponent.vue组件,它展示了如何使用模板引用来操作DOM元素。在这个组件中:

  • 我们为<input>元素创建了一个模板引用inputRef。
  • 我们定义了两个按钮,一个用于聚焦到输入框,另一个用于打印输入框的值。
  • 我们使用模板引用inputRef.value.focus()来聚焦输入框。
  • 我们使用模板引用inputRef.value.value来获取输入框的值,并更新响应式变量inputValue。

通过这个项目,你可以了解如何在Vue中使用模板引用来直接操作DOM元素。这是一个基本的示例,你可以根据需要进行扩展和修改。

相关推荐
数据掘金1 小时前
小程序埋点方案的埋点文档怎么自动生成?
前端
deli0071 小时前
cron 表达式为什么总跑错?10 个场景实测,下次执行时间一眼看懂
前端
Me是狗头1 小时前
化学实验室 HTML(联网可用)
经验分享·青少年编程·html5
代码猎人1 小时前
前端怎么优化页面性能
前端
代码猎人1 小时前
前端怎么配合后端完成数据对接
前端
lexiangqicheng1 小时前
Docker的沙箱机制是怎样的?
前端·javascript
燕落南枝2 小时前
HTML 表格标签与 AI 合并单元格实战指南
前端·人工智能·html
zyseo82 小时前
谷歌SEO 内链地图脚本:Python 画出权重分发,揪出孤岛页
java·前端·python
ClickHouseDB3 小时前
ClickHouse .NET 驱动程序新特性:从 1.0 到 1.3 的演进之路
java·前端·windows