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>

相关推荐
just小千3 分钟前
重学React(一):描述UI
前端·react.js·ui
fakaifa21 分钟前
【最新版】沃德代驾源码全开源+前端uniapp
前端·小程序·uni-app·开源·php·沃德代驾·代驾小程序
泯泷27 分钟前
【SHA-2系列】SHA256 前端安全算法 技术实践
javascript·安全·node.js
清羽_ls35 分钟前
leetcode-位运算
前端·算法·leetcode·位运算
李菠菜1 小时前
利用Nginx实现高性能的前端打点采集服务(支持GET和POST)
linux·前端·nginx
lilye661 小时前
精益数据分析(6/126):深入理解精益分析的核心要点
前端·人工智能·数据分析
Apifox1 小时前
Apifox 4月更新|Apifox在线文档支持LLMs.txt、评论支持使用@提及成员、支持为团队配置「IP 允许访问名单」
前端·后端·ai编程
Jolyne_1 小时前
搭建公司前端脚手架
前端·架构·前端框架
hang_bro1 小时前
el-tree的动态加载问题与解决
前端·javascript·vue.js
天天扭码1 小时前
一杯珍珠奶茶的时间吃透一道高频面试算法题——搜索二位矩阵Ⅱ
前端·算法·面试