Vue 3 基础语法与组件详解:从文本插值到事件修饰符

46 阅读7分钟

 引言

想让网页“活”起来?Vue 就像一位魔法指挥家,只需几行代码,就能让数据跳舞、按钮说话、列表自动排队!本文带你 Vue 学习实验室,从一行插值到复杂事件修饰符,拆解9个真实组件,手把手揭开 Vue 3 的神秘面纱——无需魔法杖,只需一颗好奇的心!

本文将结合多个 Vue 3 单文件组件(SFC)的完整代码,系统讲解 Vue 的核心语法和常用功能,包括 文本插值、属性绑定、条件渲染、列表遍历、双向数据绑定、事件处理、修饰符 等。


一、文本插值与属性绑定(Test1.vue)

<script setup>
// 定义变量
const msg = 'hello vue'
// 变量的值是html代码
const msg2 = '<button>点击我</button>'
const ida = 'd1'
const obj = {
  id: 'd2',
  class: 'c',
  style: 'color: green;'
}
</script>

<template>
  <!-- 双大括号可以调用js中的变量 -->
  <div>{{ msg }}</div>
  <!-- 双大括号不能调用html标签,需要使用v-html指令 -->
  <div>{{ msg2 }}</div>
  <!-- 如果希望使用html标签,需要使用v-html指令 -->
  <div v-html="msg2"></div>v
  <div v-bind:id="ida">属性绑定</div>
  <div :id="ida">属性绑定的缩写,不用写v-bind</div>
  <!-- 如果希望给一个标签绑定多个属性,则属性形成一个对象即可 -->
  <div v-bind="obj">{{msg}}</div>
</template>

<style>
#d1 {
  color: red;
}
.c {
  font-size: 30px;
}
</style>

讲解:

  • {{ }} 插值语法:用于在模板中动态显示 JavaScript 表达式的值。例如 {{ msg }} 会渲染为 hello vue

  • v-html 指令:用于渲染包含 HTML 标签的字符串。注意:存在 XSS 风险,仅用于可信内容。

  • v-bind 属性绑定

    • 完整写法:v-bind:id="ida"
    • 缩写::id="ida"
    • 对象批量绑定:v-bind="obj" 会将 obj 中的每个键值对作为 DOM 属性绑定(如 id="d2"class="c"、内联样式等)。
  • 响应式无关:此处变量未使用 ref(),因此不具备响应性(但 <script setup> 中若配合模板使用,Vue 会自动追踪依赖,实际仍可更新;不过推荐显式使用 ref 保证一致性)。


二、条件渲染(Test2.vue)

<style></style>
<template>
  <h2>条件指令学习</h2>
  <!-- 条件指令 v-if v-else-if v-else -->
  <div v-if="msg==='A'"> A </div>
  <div v-else-if="msg==='B'"> B </div>
  <div v-else> 既不是A也不是B </div>
  <button @click="fun1"> 切换 </button>
  <!-- 显示隐藏指令 v-show ,控制元素的显现和隐藏,元素不会消失只是改变样式-->
  <div v-show="msg==='A'"> 我是A </div>
</template>

<script setup>
var msg = 'B'
</script>

⚠️ 注意:此代码中 fun1 函数未定义,实际运行会报错。应补充如下逻辑,此处只做示范用

讲解:

  • v-if / v-else-if / v-else

    • 条件性渲染:根据表达式真假决定是否创建/销毁 DOM 元素。
    • 适用于切换频率低的场景。
  • v-show

    • 通过设置 display: none 控制显隐,DOM 始终存在
    • 适用于频繁切换的场景。
  • 关键区别

    • v-if 是“真正的条件渲染”,有更高的切换开销;
    • v-show 有更高的初始渲染开销,但切换更快。

三、列表渲染(Test3.vue)

<style>
h3 {color: red;}
h4 {color: green;}
#name {color: blue;}
#id {color: pink;}
</style>

<template>
  <h3>列表学习</h3>

  <ul>
    <h4>遍历数组</h4>
    <li v-for="stu in arr">
      姓名:{{stu.name}},学号:{{stu.id}}
    </li>
  </ul>

  <ul>
    <h4>遍历数组的同时获取索引</h4>
    <li v-for="(value,index) in names">
      {{index + 1}} . {{value}}
    </li>
  </ul>

  <ul>
    <h4>遍历对象数组</h4>
    <li v-for="value in user">
      {{value}}
    </li>
  </ul>

  <ul>
    <h4>遍历对象数组的同时获取属性名和属性值</h4>
    <li v-for="(value,key) in user">
      {{key}} : {{value}}
    </li>
  </ul>

  <ul>
    <h4>遍历对象数组的同时获取属性名、属性值和索引</h4>
    <li v-for="(value,key,index) in user">
      {{ index+1 }} . {{ key }} : {{ value }}
    </li>
  </ul>

  <ul>
    <h4>给每个属性写不同的样式</h4>
    <template v-for="stu in arr" >
      <li id="name">{{stu.name}}</li>
      <li id="id">{{stu.id}}</li>
    </template>
  </ul>

  <ul>
    <h4>根据属性值判断是否显示</h4>
    <li v-for="attr in user">
      {{ attr }}
    </li>
    <li v-if="user.isVIP">VIP:{{user.name}}</li>
    <li v-else>普通用户:{{user.name}}</li>
  </ul>
</template>

<script setup>
const arr = [
  { name:'Agiao', id:'2023213413', },
  { name:'李四', id:'2023213414', },
  { name:'王五', id:'2023213415', }
]
const names = ['Agiao','李四','王五']
const user = {
  name:'Agiao',
  password:'123456',
  gender:'女',
  isVIP:true
}
</script>

讲解:

  • v-for 遍历数组

    • (item, index) in itemsitem 是元素,index 是下标(从 0 开始)。
  • v-for 遍历对象

    • (value, key, index) in object:依次获取值、键名、索引。
  • <template v-for>

    • 渲染多个元素而不引入额外 DOM 节点(类似 React 的 Fragment)。
  • 注意事项

    • 遍历对象时,顺序由 Object.keys() 决定(ES2015+ 保证插入顺序)。
    • 不应使用 id 作为重复元素的 ID(如 #name 多次出现),这违反 HTML 规范。应改用 class 或动态 :id

四、双向数据绑定(Input1.vue)

<style setup>
h2 { color: red; }
.input-box{ width: 300px; height: 100px; }
</style>

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

const message = ref("hello vue")
const selected = ref('男')
const selectedColors = ref(['红色'])
const yes = ref('同意协议')
const no = ref('不同意协议')
const checked = ref(yes.value)
const selectedOption = ref('')
const selectedOption1 = ref('')
const city = [
  {text: '北京',value: 'bj'},
  {text: '杭州',value: 'hz'},
  {text: '武汉',value: 'wh'},
  {text: '深圳',value: 'sz'},
]
</script>

<template>
  <h2>双向数据绑定学习</h2>
  <p>文本框的值是:{{ message }}</p>
  <div><input class="input-box" type="text" v-model="message" placeholder="请输入内容"></div>
  <div><textarea class="input-box" v-model="message" placeholder="请输入多行内容"></textarea></div>

  <p>你的选择是:{{ selected }}</p>
  <input type="radio" v-model="selected" name="gender" value="男"><input type="radio" v-model="selected" name="gender" value="女"><p>你喜欢的颜色是:{{ selectedColors }}</p>
  <input type="checkbox" v-model="selectedColors" value="红色"> 红色
  <input type="checkbox" v-model="selectedColors" value="绿色"> 绿色
  <input type="checkbox" v-model="selectedColors" value="蓝色"> 蓝色
  <ul>
    <li v-for="color in selectedColors">{{ color }}</li>
  </ul>

  <p> 是否同意协议:{{ checked }}
    <input type="checkbox" v-model="checked" :true-value="yes" :false-value="no"> {{ checked }}
  </p>

  <p>
    你的工作地点是:
    <select v-model="selectedOption">
      <option value="北京">北京</option>
      <option value="杭州">杭州</option>
      <option value="武汉">武汉</option>
      <option value="深圳">深圳</option>
    </select>
    你选择的是:{{ selectedOption }}
  </p>

  <p>
    你的工作地点是:
    <select v-model="selectedOption1">
      <option v-for="item in city" :value="item.value">{{ item.text }}</option>
    </select>
    你选择的是:{{ selectedOption1 }}
  </p>
</template>

讲解:

  • v-model 实现双向绑定

    • 自动同步表单控件的值与响应式变量。
  • 不同类型表单元素的绑定行为

    • 文本框/文本域:绑定 value 属性和 input 事件。

    • 单选按钮v-model 的值等于被选中按钮的 value

    • 复选框

      • 单个:绑定布尔值;
      • 多个:绑定数组,包含所有被选中的 value
    • 下拉选择框:绑定选中项的 value

  • true-value / false-value

    • 自定义复选框在勾选/未勾选时的值(需用 : 绑定响应式变量)。

五、v-model 修饰符(Input2.vue)

<style>
h2{color: red;}
input{ height: 30px; width: 300px; }
</style>

<script setup>
import { ref } from 'vue'
const msglazy = ref('')
const msgtrim = ref('')
const msgnumber = ref('')
</script>

<template>
  <h2>修饰符学习组件 lazy trim number</h2>

  <p>lazy: {{ msglazy }}</p>
  <input type="text" v-model.lazy="msglazy" placeholder="请输入内容lazy">

  <p>trim: {{ msgtrim }}</p>
  <input type="text" v-model.trim="msgtrim" placeholder="请输入内容trim">

  <p>number: {{ msgnumber }}</p>
  <input type="text" v-model.number="msgnumber" placeholder="请输入内容number">
</template>

讲解:

  • .lazy:将 input 事件改为 change 事件(失焦时才更新)。

  • .trim:自动去除输入首尾空格。

  • .number

    • 尝试将输入转为数字(使用 parseFloat);
    • 若无法转换(如 "abc"),则保留原字符串;
    • 若部分可转(如 "123abc"),则返回 123

六、事件处理与修饰符(Fun1.vue & Fun2.vue)

Fun1.vue:基础事件

<style> h1 { color: red; }</style>
<template>
  <h1>函数学习组件</h1>
  <button v-on:click="count++">自增</button>
  <p>v-on当前计数:{{count}}</p>
  <button @click="count++">自增</button>
  <p>@当前计数:{{count}}</p>
  <button @click="add()">自增</button>
  <button @click="add">方法事件自增</button>
</template>

<script setup>
import { ref } from 'vue';
const count = ref(0)
function add() {
  count.value++
}
</script>
  • 内联处理器@click="count++",适合简单逻辑。
  • 方法处理器@click="add",适合复杂逻辑(注意:add()add 在无参时效果相同)。
  • ref 响应式:必须通过 .value 修改(但在模板中可直接使用 count)。

Fun2.vue:事件修饰符

<!-- 片段 -->
<button @click.once="fun1">事件修饰符once,事件只触发一次</button>
<div @contextmenu.prevent="fun1">禁止右键菜单</div>
<div @contextmenu="fun2">阻止默认行为(需手动调用 preventDefault)</div>
  • .once:事件只触发一次。
  • .prevent:自动调用 event.preventDefault()
  • .stop:阻止事件冒泡(示例中未启用,但已注释说明)。

七、按键与系统修饰符(Fun3.vue)

<textarea 
  @keydown.esc="clearText"
  @keydown.up="up"
  @keydown.down="down"
  @keydown.left="left"
  @keydown.right="right">
</textarea>

<div id="div2" @click.ctrl="fun1">按 Ctrl + 点击变黄</div>
  • 按键修饰符.enter.esc.up 等,简化键盘事件判断。
  • 系统修饰符.ctrl.alt.shift.meta,用于组合键。
  • 注意:代码中 window.onkeydown 使用了错误的 KeyCode(应为 keyCodecode),且逻辑与局部函数重复,实际应统一处理。

八、自定义指令(HighLight.vue)

<!-- 当前代码中 v-highLight 未定义,故无效 -->
<div v-highLight>这是一个div,会被高亮显示</div>
  • 自定义指令:可用于封装 DOM 操作(如聚焦、高亮)。
  • 正确做法:取消注释 const vHighLight = { mounted(el) { ... } },或全局注册。

结语

本文通过 9 个真实组件代码,全面覆盖了 Vue 3 的核心语法:

功能对应文件
文本插值、属性绑定Test1.vue
条件渲染Test2.vue
列表渲染Test3.vue
双向绑定(基础)Input1.vue
v-model 修饰符Input2.vue
事件处理Fun1.vue
事件修饰符Fun2.vue
按键/系统修饰符Fun3.vue
自定义指令(待完善)HighLight.vue

Vue 的魅力,不在于炫技,而在于用最简洁的语法解决最真实的交互问题。通过这组由浅入深的组件实践,我们不仅掌握了指令、绑定与响应式的核心逻辑,更体会到“声明式开发”的优雅与高效。愿你在构建下一个应用时,也能像这些代码一样:清晰、灵动、恰到好处。

完整项目仓库:Vue-pro: Vue学习——Gitee