02 Vue 3 单文件组件与模板语法
2026/8/7 16:29:41 网站建设 项目流程

Vue 3 单文件组件与模板语法

一、单文件组件是什么

Vue 项目通常使用.vue单文件组件。一个组件可以把结构、逻辑和样式放在同一个文件中:

<template> <div class="page"> <h1>{{ title }}</h1> </div> </template> <script setup lang="ts"> const title = 'Vue 3 页面'; </script> <style scoped> .page { padding: 24px; } </style>

三个部分分别承担:

<template> 页面结构 <script setup> 状态、函数和业务逻辑 <style scoped> 当前组件样式

二、<script setup>的作用

Vue 3 中常见写法是:

<script setup lang="ts">

其中:

  • setup表示使用组合式 API 的简化语法;
  • lang="ts"表示脚本使用 TypeScript;
  • 在脚本中声明的变量和函数,可以直接在模板中使用。

例如:

<template> <button @click="increase">{{ count }}</button> </template> <script setup lang="ts"> import { ref } from 'vue'; const count = ref(0); function increase() { count.value += 1; } </script>

不需要再手动编写return { count, increase }

三、插值表达式{{ }}

模板中使用双大括号显示数据:

<h1>{{ title }}</h1> <p>当前炉次:{{ heatId }}</p>

插值中可以使用简单表达式:

<p>{{ heatId || '--' }}</p> <p>{{ isRealtime ? '实时模式' : '回放模式' }}</p> <p>{{ warnings.length }}</p>

也可以调用格式化函数:

<strong>{{ formatTemperature(temperature) }}</strong>

但不建议在模板中编写过于复杂的逻辑。复杂结果应优先放到computed中。

四、可选链与默认值

接口数据在页面首次渲染时可能还没有返回。下面的写法可以避免读取空对象时报错:

<strong>{{ heatMeta?.converter_no || '--' }}</strong>

其中:

  • ?.表示对象存在时才继续读取;
  • || '--'表示前面的值为空时显示占位内容。

需要注意,||会把0、空字符串和false也视为假值。只想处理nullundefined时,可以使用??

{{ value ?? '--' }}

五、条件渲染

1.v-if

<div v-if="loading">正在加载...</div>

条件为真时才创建该 DOM。

2.v-else

<div v-if="loading">正在加载...</div> <div v-else>加载完成</div>

v-else必须紧跟在v-ifv-else-if后面。

3.v-else-if

<el-tag v-if="risk === 'critical'" type="danger">严重</el-tag> <el-tag v-else-if="risk === 'warning'" type="warning">预警</el-tag> <el-tag v-else type="success">正常</el-tag>

4.v-show

<div v-show="visible">控制面板</div>

v-show不会销毁 DOM,只会改变 CSS 的display

选择建议:

切换频繁 → v-show 条件很少变化或内容较重 → v-if

六、列表渲染v-for

<div v-for="signal in signalCards" :key="signal.code"> <span>{{ signal.label }}</span> <strong>{{ signal.value }}</strong> </div>

这里的含义是:

遍历 signalCards ↓ 每次取出一个 signal ↓ 为它生成一组 DOM

也可以同时得到索引:

<li v-for="(item, index) in list" :key="item.id"> {{ index + 1 }}. {{ item.name }} </li>

为什么需要:key

Vue 在更新列表时,需要判断哪些节点被增加、删除或移动。稳定的 Key 可以帮助 Vue 正确复用 DOM。

推荐:

:key="item.id"

谨慎使用:

:key="index"

当列表发生排序、插入或删除时,索引并不稳定。

七、属性绑定v-bind

普通 HTML 属性是固定字符串:

<button disabled="true">按钮</button>

需要绑定 JavaScript 数据时使用v-bind

<el-button v-bind:loading="loading">刷新</el-button>

简写为:

<el-button :loading="loading">刷新</el-button>

动态类名

对象写法:

<div :class="{ active: isActive, disabled: isDisabled }"></div>

数组写法:

<div :class="[riskClass, { lightweight: lowPerformance }]"></div>

动态样式

<div :style="{ left: positionX + 'px', top: positionY + 'px' }"></div>

也可以绑定完整对象:

<div :style="labelStyles[item.key]"></div>

八、事件绑定v-on

<el-button @click="loadData">刷新</el-button>

@clickv-on:click的简写。

常见事件包括:

<input @input="handleInput" /> <select @change="handleChange"></select> <div @dblclick="handleDoubleClick"></div> <div @wheel="handleWheel"></div>

获取事件对象

<button @click="handleClick($event)">点击</button>
functionhandleClick(event:MouseEvent){console.log(event.clientX,event.clientY);}

传递自定义参数

<button @click="setMode('realtime')">实时模式</button>

九、双向绑定v-model

v-model常用于表单和交互组件:

<input v-model="keyword" /> <el-switch v-model="autoRotate" /> <el-slider v-model="opacity" /> <el-select v-model="playbackSpeed" />

例如:

<template> <input v-model="name" /> <p>输入内容:{{ name }}</p> </template> <script setup lang="ts"> import { ref } from 'vue'; const name = ref(''); </script>

用户修改输入框时,name自动变化;代码修改name时,输入框也自动变化。

十、模板引用ref="..."

模板引用用于获得真实 DOM 或组件实例:

<div ref="containerRef" class="canvas-container"></div>
constcontainerRef=ref<HTMLElement>();

组件挂载后可以访问:

onMounted(()=>{console.log(containerRef.value);});

这在初始化 Three.js、图表库或视频播放器时非常常见。

需要区分两种ref

ref() 创建响应式状态 ref="containerRef" 在模板中记录 DOM 或组件引用

它们相关,但不是同一个使用场景。

十一、Element Plus 组件也是 Vue 组件

下面的标签不是浏览器原生 HTML:

<el-button /> <el-tag /> <el-alert /> <el-switch /> <el-slider />

它们由 Element Plus 提供,本质上仍然遵循 Vue 的属性绑定、事件和v-model规则:

<el-button type="primary" :loading="loading" @click="loadData" > 刷新 </el-button>

十二、一个完整的小案例

<template> <section class="monitor-panel"> <h2>{{ title }}</h2> <el-alert v-if="errorMessage" :title="errorMessage" type="warning" /> <div v-if="loading">数据加载中...</div> <div v-else> <div v-for="signal in signals" :key="signal.code" :class="['signal-card', { danger: signal.value > signal.limit }]" > <span>{{ signal.label }}</span> <strong>{{ signal.value }} {{ signal.unit }}</strong> </div> </div> <el-switch v-model="autoRefresh" active-text="自动刷新" /> <el-button :loading="loading" @click="loadSignals">刷新</el-button> </section> </template> <script setup lang="ts"> import { ref } from 'vue'; const title = '过程信号'; const loading = ref(false); const errorMessage = ref(''); const autoRefresh = ref(false); const signals = ref([ { code: 'TEMP', label: '温度', value: 1650, limit: 1700, unit: '°C' }, { code: 'FLOW', label: '氧流量', value: 18000, limit: 22000, unit: 'Nm³/h' } ]); function loadSignals() { loading.value = true; setTimeout(() => { loading.value = false; }, 500); } </script>

十三、常见误区

1. 在模板中编写大量业务逻辑

模板应以展示为主。复杂条件应放到computed或函数中。

2.v-for忘记稳定的 Key

列表更新时可能出现状态错位。

3. 把v-ifv-for放在同一个元素上

优先在计算属性中先过滤数据,或使用外层<template>分开处理。

4. 在组件尚未挂载时访问模板 DOM

模板引用通常需要在onMounted()后使用。

十四、本章小结

Vue 模板的核心思想是:

状态决定页面结构和属性 用户事件修改状态 状态变化后页面自动更新

下一章将进入 Vue 的核心:refreactivecomputed响应式数据。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询