Vue3 模板语法

目录

[一、插值语法 {{ }}](#一、插值语法 {{ }})

二、核心指令

三、动态属性绑定

四、事件修饰符

[五、条件渲染 vs 列表渲染总结](#五、条件渲染 vs 列表渲染总结)

六、最佳实践

[示例 1:插值语法 & 基础绑定](#示例 1:插值语法 & 基础绑定)

[示例 2:条件渲染](#示例 2:条件渲染)

[示例 3:列表渲染](#示例 3:列表渲染)

[示例 4:事件处理](#示例 4:事件处理)

[示例 5:动态绑定](#示例 5:动态绑定)

[示例 6:双向绑定](#示例 6:双向绑定)

[示例 7:综合实践](#示例 7:综合实践)


一、插值语法 {``{ }}

  • 作用:将数据绑定到 DOM 文本内容。

  • 特性

    • 支持 JavaScript 表达式(如 {``{ count + 1 }}),但不支持语句(如 if)。

    • 自动响应数据变化(数据驱动视图)。

  • 示例

    html 复制代码
    <p>{{ message }}</p>
    <p>{{ user.name }}</p>

二、核心指令

  1. 条件渲染:v-if vs v-show

    • v-if

      • 根据条件销毁或创建元素

      • 适用于切换频率低的场景(如初始化渲染)。

      • 支持 v-elsev-else-if

    • v-show

      • 通过 CSS display 控制显示/隐藏。

      • 适用于频繁切换的场景(如选项卡)。

    • 示例

      html 复制代码
      <div v-if="isVisible">v-if 内容</div>
      <div v-show="isActive">v-show 内容</div>
  2. 列表渲染:v-for

    • 作用:遍历数组或对象生成列表。

    • key 的作用

      • 唯一标识:帮助 Vue 跟踪节点身份,优化复用逻辑。

      • 避免问题:防止列表更新时出现错乱(如状态保留问题)。

    • 最佳实践

      • 使用唯一 ID (如 :key="item.id")。

      • 避免用 index 作为 key(除非列表静态且无排序)。

    • 示例

      html 复制代码
      <ul>
        <li v-for="item in items" :key="item.id">{{ item.name }}</li>
      </ul>
  3. 属性绑定:v-bind(简写 :

    • 动态属性 :将数据绑定到 HTML 属性(如 idclass)。

    • 示例

      html 复制代码
      <img :src="imageUrl" />
      <div :class="{ active: isActive }"></div>
  4. 事件绑定:v-on(简写 @

    • 监听事件:如点击、输入等。

    • 示例

      html 复制代码
      <button @click="handleClick">点击</button>
  5. 双向绑定:v-model

    • 作用 :表单输入与数据的双向同步(语法糖 = :value + @input)。

    • 示例

      html 复制代码
      <input v-model="message" />

三、动态属性绑定

  1. 动态 Class(:class

    • 对象语法:按条件添加类名。

      html 复制代码
      <div :class="{ active: isActive, 'text-danger': hasError }"></div>
    • 数组语法:绑定多个类名。

      html 复制代码
      <div :class="[activeClass, errorClass]"></div>
  2. 动态 Style(:style

    • 对象语法:绑定样式对象。

      html 复制代码
      <div :style="{ color: textColor, fontSize: size + 'px' }"></div>
    • 数组语法:组合多个样式对象。

      html 复制代码
      <div :style="[baseStyles, overrideStyles]"></div>

四、事件修饰符

  • 常用修饰符

    • .stop:阻止事件冒泡(等价于 event.stopPropagation())。

    • .prevent:阻止默认行为(等价于 event.preventDefault())。

    • .once:事件只触发一次。

    • .self:仅当事件从元素自身触发时生效。

  • 示例

    html 复制代码
    <button @click.stop="handleClick">阻止冒泡</button>
    <form @submit.prevent="handleSubmit">阻止默认提交</form>
  • 按键修饰符:

按键别名:

Vue 为一些常用的按键提供了别名:

  • .enter
  • .tab
  • .delete (捕获"Delete"和"Backspace"两个按键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

系统按键修饰符:

你可以使用以下系统按键修饰符来触发鼠标或键盘事件监听器,只有当按键被按下时才会触发。

  • .ctrl
  • .alt
  • .shift
  • .meta
html 复制代码
<!-- 仅在 key 为 Enter 时调用 submit -->
<input @keyup.enter="submit" />

<!-- Alt + Enter --> 
<input @keyup.alt.enter="clear" />
<!-- Ctrl + 点击 --> 
<div @click.ctrl="doSomething">Do something</div> 

五、条件渲染 vs 列表渲染总结

特性 v-if v-show v-for(需 key
渲染方式 条件为假时销毁元素 始终渲染,切换 CSS 动态生成列表项
性能 初始渲染开销低 切换开销低 列表变化时依赖 key 优化
适用场景 不频繁切换的条件 频繁显示/隐藏 动态列表数据

六、最佳实践

  1. v-forkey

    • 始终使用唯一标识(如数据库 ID)。

    • 避免 index,除非列表简单且无状态。

  2. v-ifv-for 优先级

    • 避免在同一个元素上同时使用(Vue3 中 v-if 优先级更高)。

    • 使用 <template> 包裹解决:

      html 复制代码
      <template v-for="item in items" :key="item.id">
        <div v-if="item.isVisible">{{ item.name }}</div>
      </template>
  3. 事件处理

    • 复杂逻辑应封装到方法中,避免内联表达式。

示例 1:插值语法 & 基础绑定

html 复制代码
<template>
  <!-- 文本插值 -->
  <p>{{ message }}</p>
  
  <!-- JavaScript 表达式 -->
  <p>{{ count + 1 }}</p>
  
  <!-- 属性绑定 -->
  <a :href="'https://vuejs.org'">官网链接</a>
</template>

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

const message = ref('Hello Vue3!')
const count = ref(0)
</script>

示例 2:条件渲染

html 复制代码
<template>
  <!-- v-if 链式判断 -->
  <div>
    <p v-if="score >= 90">优秀</p>
    <p v-else-if="score >= 60">合格</p>
    <p v-else>不合格</p>
  </div>

  <!-- v-show 切换 -->
  <button @click="showA = !showA">切换显示</button>
  <div v-show="showA">显示/隐藏内容</div>
</template>

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

const showA = ref(true)
const score = ref(85)
</script>

示例 3:列表渲染

html 复制代码
<template>
  <!-- 带 key 的列表渲染 -->
  <ul>
    <li 
      v-for="(item, index) in books" 
      :key="item.id"
    >
      {{ index + 1 }}. {{ item.title }}
    </li>
  </ul>

  <!-- 动态添加项 -->
  <input v-model="newBook">
  <button @click="books.push({ 
    id: Date.now(), 
    title: newBook 
  })">添加书籍</button>
</template>

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

const books = ref([
  { id: 'b1', title: 'Vue3 入门' },
  { id: 'b2', title: 'TypeScript 进阶' }
])

const newBook = ref('')
</script>

示例 4:事件处理

html 复制代码
<template>
  <!-- 内联事件处理 -->
  <button @click="handleClick('按钮点击')">点击事件</button>

  <!-- 事件修饰符 -->
  <div @click.self="console.log('父元素点击')">
    <button @click.stop="console.log('子元素点击')">
      阻止冒泡
    </button>
  </div>

  <!-- 按键修饰符 -->
  <input 
    @keyup.enter="console.log('回车按下')" 
    @keyup.esc="console.log('ESC 按下')"
  >
</template>

<script setup>
function handleClick(msg) {
  alert(msg)
}

function handleKeyup(e) {
  console.log('按键码:', e.keyCode)
}
</script>

示例 5:动态绑定

html 复制代码
<template>
  <!-- 动态 class (对象语法) -->
  <div :class="{ active: isActive, 'text-danger': false }">
    动态类名
  </div>

  <!-- 动态 style (数组语法) -->
  <div :style="[
    { color: errorColor }, 
    styleObject
  ]">
    动态样式
  </div>
</template>

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

const isActive = ref(true)
const errorColor = ref('red')
const styleObject = ref({
  fontSize: '20px',
  fontWeight: 'bold'
})
</script>

示例 6:双向绑定

html 复制代码
<template>
  <!-- 文本输入 -->
  <input v-model="text" placeholder="输入内容">

  <!-- 复选框 -->
  <input type="checkbox" v-model="checked">

  <!-- 单选按钮 -->
  <select v-model="selectedOption">
    <option value="A">选项A</option>
    <option value="B">选项B</option>
  </select>
</template>

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

const text = ref('')
const checked = ref(false)
const selectedOption = ref('A')
</script>

示例 7:综合实践

html 复制代码
<template>
  <!-- 条件渲染 + 列表渲染 -->
  <div v-if="activeTodos.length > 0">
    <h3>待办事项 ({{ activeTodos.length }})</h3>
    <ul>
      <li 
        v-for="todo in activeTodos" 
        :key="todo.id"
        :class="{ completed: todo.done }"
      >
        {{ todo.text }}
        <button @click="todo.done = true">完成</button>
      </li>
    </ul>
  </div>
  <p v-else>全部任务已完成!🎉</p>

  <!-- 双向绑定 + 事件修饰符 -->
  <form @submit.prevent="addTodo">
    <input 
      v-model.trim="newTodo" 
      @keyup.enter="addTodo"
    >
    <button type="submit">添加</button>
  </form>
</template>

<script setup>
import { ref, computed } from 'vue'

const todos = ref([
  { id: 1, text: '学习 Vue3', done: true },
  { id: 2, text: '掌握组合式API', done: false }
])

const newTodo = ref('')

const activeTodos = computed(() => 
  todos.value.filter(t => !t.done)
)

function addTodo() {
  if (newTodo.value.trim()) {
    todos.value.push({
      id: Date.now(),
      text: newTodo.value,
      done: false
    })
    newTodo.value = ''
  }
}
</script>

相关推荐
不爱吃糖的程序媛1 分钟前
浅谈前端架构设计与工程化
前端·前端架构设计
BillKu1 小时前
Vue3 Element Plus 对话框加载实现
javascript·vue.js·elementui
郝YH是人间理想2 小时前
系统架构设计师案例分析题——web篇
前端·软件工程
Evaporator Core2 小时前
深入探索:Core Web Vitals 进阶优化与新兴指标
前端·windows
初遇你时动了情2 小时前
html js 原生实现web组件、web公共组件、template模版插槽
前端·javascript·html
QQ2740287563 小时前
Soundness Gitpod 部署教程
linux·运维·服务器·前端·chrome·web3
前端小崔3 小时前
从零开始学习three.js(18):一文详解three.js中的着色器Shader
前端·javascript·学习·3d·webgl·数据可视化·着色器
哎呦你好3 小时前
HTML 表格与div深度解析区别及常见误区
前端·html
运维@小兵3 小时前
vue配置子路由,实现点击左侧菜单,内容区域显示不同的内容
前端·javascript·vue.js
koiy.cc4 小时前
记录:echarts实现tooltip的某个数据常显和恢复
前端·echarts