Vue.js 核心概念、模板语法、常用指令

0 阅读3分钟

1. Vue 是什么?

Vue.js 是一个用于构建用户界面的渐进式框架

  • 核心库:专注视图层(约40KB),提供数据驱动、组件系统等核心功能
  • 渐进式:可逐步集成路由、状态管理等扩展
  • 设计理念:通过简洁的API实现高效开发

渐进式框架实践路径

<!-- 阶段1:核心视图渲染 -->
<div id="app">{{ message }}</div>

<!-- 阶段2:添加组件系统 -->
<user-profile :user="currentUser"></user-profile>

<!-- 阶段3:集成路由 -->
<router-link to="/dashboard">控制台</router-link>

<!-- 阶段4:加入状态管理 -->
<script setup>
import { useCartStore } from '@/stores/cart'
</script>

2. data 属性深度解析

作用:声明组件的响应式数据
原理:Vue3 使用 Proxy 实现数据劫持,自动追踪依赖

export default {
  data() {
    return {
      // 基本类型(自动响应)
      count: 0,
      
      // 对象类型(嵌套属性自动响应)
      user: {
        name: '张三',
        address: {
          city: '北京'
        }
      },
      
      // 数组类型(需使用变异方法)
      items: ['苹果', '香蕉']
    }
  }
}

注意事项

  1. 必须使用函数返回新对象(避免组件复用数据共享)
  2. 新增属性需使用 this.$set() (Vue2) 或直接赋值 (Vue3)
  3. 数组修改需使用 push()/pop()/splice() 等变异方法

3. methods 全面指南

作用:定义可在模板中调用的方法

export default {
  data() { return { count: 0 } },
  methods: {
    // ✅ 标准函数 - this 指向组件实例
    increment() {
      this.count++
      console.log(this.$data) // 访问组件数据
    },
    
    // ✅ 带参数方法
    add(num) {
      this.count += num
    },
    
    // ❌ 错误:箭头函数导致 this 丢失
    decrement: () => {
      // 此处 this 为 undefined 或 window 对象
      this.count-- 
    }
  }
}

为什么 this 能访问 data?
Vue 在初始化时自动绑定 methods 的 this 上下文到组件实例


4. 模板语法:Mustache 插值

双大括号 {{ }} 支持所有 JavaScript 表达式

<div>
  <!-- 1. 基础文本绑定 -->
  <p>{{ message }}</p>
  
  <!-- 2. 表达式计算 -->
  <p>总价: ¥{{ (price * quantity).toFixed(2) }}</p>
  
  <!-- 3. 三元运算 -->
  <p>状态: {{ isActive ? '已激活' : '未激活' }}</p>
  
  <!-- 4. 方法调用 -->
  <p>倒序文本: {{ reverseString('Vue3') }}</p>
  
  <!-- 5. 受限使用:不能包含语句 -->
  <!-- ❌ 错误:{{ let x = 10 }} -->
  
  <!-- 6. 对象属性访问 -->
  <p>城市: {{ user.address.city }}</p>
</div>

5. 指令系统深度解析

指令是带有 v- 前缀的特殊属性,用于 DOM 动态操作

5.1 v-text 与 v-html
<!-- 文本内容绑定(等效于 {{}}) -->
<p v-text="rawText"></p>

<!-- 原始HTML渲染(慎用XSS风险) -->
<div v-html="htmlContent"></div>

<!-- 使用场景:渲染富文本编辑器内容 -->
<div v-html="sanitizedContent"></div>
5.2 v-show 与 v-if
<!-- v-show:CSS display 切换(适合频繁切换) -->
<div v-show="isLoggedIn">用户控制台</div>

<!-- v-if/v-else:条件渲染(适合不频繁切换) -->
<template v-if="score >= 90">
  <span class="gold">A+</span>
  <p>优秀!</p>
</template>
<div v-else-if="score >= 60">B</div>
<div v-else class="warning">C(需补考)</div>

<!-- 特殊场景:与 v-for 共用 -->
<template v-for="item in list">
  <li v-if="item.isVisible">{{ item.name }}</li>
</template>
5.3 v-for 循环指令
<!-- 数组遍历 -->
<ul>
  <li v-for="(item, index) in items" :key="item.id">
    {{ index + 1 }}. {{ item.name }}
  </li>
</ul>

<!-- 对象遍历 -->
<div v-for="(value, key) in userInfo" :key="key">
  {{ key }}: {{ value }}
</div>

<!-- 使用范围值 -->
<span v-for="n in 10">{{ n }} </span>

<!-- 注意事项 -->
<!-- ❌ 错误:缺少 key -->
<!-- ❌ 错误:v-for 和 v-if 同元素(Vue3允许但性能不佳) -->
5.4 v-on 事件绑定
<!-- 基础用法 -->
<button v-on:click="submitForm">提交</button>

<!-- 缩写语法 -->
<button @click="count += 1">+1</button>

<!-- 内联语句 -->
<button @click="showAlert('确认操作?')">提示</button>

<!-- 事件修饰符 -->
<form @submit.prevent="onSubmit">...</form>
<input @keyup.enter="search">
<div @click.self="closeModal">...</div>

<!-- 事件对象访问 -->
<button @click="handleClick($event)">按钮</button>

<!-- 修饰符串联 -->
<div @click.stop.prevent="doThis"></div>
5.5 v-bind 属性绑定
<!-- 基础绑定 -->
<img v-bind:src="imageUrl">

<!-- 缩写语法 -->
<img :src="dynamicPath">

<!-- Class 绑定 -->
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<div :class="[isActive ? 'active' : '', errorClass]"></div>

<!-- Style 绑定 -->
<div :style="{ color: activeColor, fontSize: size + 'px' }"></div>
<div :style="[baseStyles, overridingStyles]"></div>

<!-- 属性绑定 -->
<button :disabled="isProcessing">提交</button>
5.6 v-model 双向绑定
<!-- 文本输入 -->
<input v-model="username" placeholder="请输入用户名">

<!-- 多行文本 -->
<textarea v-model="description"></textarea>

<!-- 单个复选框 -->
<input type="checkbox" v-model="agree"> 同意协议

<!-- 多个复选框 -->
<input type="checkbox" value="vue" v-model="skills">
<input type="checkbox" value="react" v-model="skills">

<!-- 单选按钮 -->
<input type="radio" value="A" v-model="answer">

<!-- 下拉选择 -->
<select v-model="selectedCity">
  <option value="beijing">北京</option>
  <option value="shanghai">上海</option>
</select>

<!-- 修饰符 -->
<input v-model.lazy="searchQuery"> <!-- 失焦时更新 -->
<input v-model.number="age">      <!-- 自动转数字 -->
<input v-model.trim="email">      <!-- 自动去空格 -->
5.7 特殊指令
<!-- v-pre:跳过编译 -->
<div v-pre>{{ 原始模板内容 }}</div>

<!-- v-cloak:隐藏未编译模板 -->
<style>
  [v-cloak] { display: none }
</style>
<div v-cloak>{{ message }}</div>

<!-- v-once:单次渲染 -->
<footer v-once>© 2023 公司名称</footer>

<!-- 自定义指令(简例) -->
<p v-highlight="'yellow'">重点内容</p>

6. 指令综合应用案例

<div id="app">
  <!-- 搜索过滤 + 列表渲染 -->
  <input v-model="searchText" placeholder="搜索...">
  <ul>
    <li v-for="item in filteredList" 
        :key="item.id"
        :class="{ highlight: item.important }">
      {{ item.name }}
      <button @click.stop="deleteItem(item.id)">删除</button>
    </li>
  </ul>

  <!-- 表单验证 + 条件渲染 -->
  <form @submit.prevent="submitForm">
    <input v-model.trim="email" type="email">
    <p v-if="!emailValid" class="error">邮箱格式错误</p>
    
    <select v-model="department">
      <option v-for="dept in departments" :value="dept.id">
        {{ dept.name }}
      </option>
    </select>
    
    <button :disabled="!formValid">提交</button>
  </form>

  <!-- 动态样式 -->
  <div :style="{
    width: progress + '%',
    backgroundColor: progressColor
  }" class="progress-bar"></div>
</div>

关键概念对比表

指令/特性使用场景注意事项
v-show vs v-if频繁切换 vs 初始条件v-if 有更高切换开销
v-for key列表渲染必须使用唯一标识
v-model表单输入绑定修饰符改变更新时机
methods 函数事件处理/数据操作避免箭头函数
data 属性存储响应式数据复杂对象需深度响应
Mustache文本插值不支持语句