主题
Vue 3 核心概念
一、Vue 是什么
Vue 是一个渐进式前端框架。核心思想一句话:数据驱动视图——你只管改数据,Vue 自动更新页面。
js
const app = Vue.createApp({
data() { return { count: 0 } }
})Vue 3 最大的变化是引入了组合式 API(Composition API),把相关逻辑聚合在一起,替代旧版"选项式 API"分散的写法。本教程全部采用组合式 API + <script setup>。
二、响应式:ref 与 reactive
ref(推荐,处理基本类型和对象)
vue
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
const product = ref({ name: '手机', price: 3999 })
function add() {
count.value++ // 修改 ref 必须加 .value(模板中自动解包)
product.value.price = 2999
}
</script>
<template>
<p>当前数量:{{ count }}</p>
<p>{{ product.name }} ¥{{ product.price }}</p>
<button @click="add">+1</button>
</template>reactive(只适用于对象/数组)
ts
import { reactive } from 'vue'
const state = reactive({ count: 0, list: [] as string[] })
state.count++ // 不用 .value经验法则:能用 ref 用 ref。reactive 在解构/展开时会丢失响应性,容易踩坑。
三、模板语法与指令
| 指令 | 作用 | 例子 |
|---|---|---|
| 双花括号 | 文本插值 | 把商品价格渲染到页面(见下方示例) |
v-if / v-else | 条件渲染 | <p v-if="stock > 0">有货</p> |
v-for | 列表渲染 | <li v-for="p in products" :key="p.id"> |
v-model | 表单双向绑定 | <input v-model="keyword" /> |
:属性 | 动态绑定属性 | :src="product.image" |
@click | 事件绑定 | <button @click="addCart(product)"> |
商品列表卡片,一行 v-for 全搞定:
vue
<div class="product-grid">
<div v-for="p in products" :key="p.id" class="card">
<img :src="p.image" :alt="p.name" />
<h3>{{ p.name }}</h3>
<p class="price">¥{{ p.price }}</p>
<button @click="addToCart(p)">加入购物车</button>
</div>
</div>四、计算属性与侦听器
ts
import { computed, watch } from 'vue'
// 计算属性:依赖变化才重算(有缓存)
const totalPrice = computed(() =>
cartItems.value.reduce((sum, item) => sum + item.price * item.count, 0)
)
// 侦听器:数据变化后做副作用
watch(keyword, (newVal) => {
console.log('搜索词变了:', newVal)
})五、组件通信
组件是 Vue 的基本单元。父子组件通过 props(父传子)和 emit(子传父)通信:
vue
<!-- 子组件 ProductCard.vue -->
<script setup lang="ts">
const props = defineProps<{ product: Product }>()
const emit = defineEmits<{ (e: 'add', id: number): void }>()
</script>
<template>
<div class="card">
<h3>{{ props.product.name }}</h3>
<button @click="emit('add', props.product.id)">加购</button>
</div>
</template>vue
<!-- 父组件 -->
<script setup lang="ts">
import ProductCard from './ProductCard.vue'
const products = ref<Product[]>([])
</script>
<template>
<ProductCard v-for="p in products" :key="p.id" :product="p"
@add="handleAdd" />
</template>六、生命周期
组件从创建到销毁的钩子,最常用两个:
ts
import { onMounted, onUnmounted } from 'vue'
onMounted(() => {
// 组件挂载后:发请求、初始化
fetchProducts()
})| 钩子 | 时机 |
|---|---|
onMounted | 组件挂载后(发请求的最佳位置) |
onBeforeUnmount | 销毁前(清理定时器/事件) |
七、完整小例子:商品列表页
vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface Product { id: number; name: string; price: number; stock: number }
const products = ref<Product[]>([])
const loading = ref(false)
async function fetchProducts() {
loading.value = true
try {
const res = await fetch('/api/product/list')
const data = await res.json()
products.value = data.data.records
} finally {
loading.value = false
}
}
onMounted(fetchProducts)
</script>
<template>
<div v-if="loading">加载中...</div>
<div class="grid">
<div v-for="p in products" :key="p.id">{{ p.name }} ¥{{ p.price }}</div>
</div>
</template>本章小结
记住四个关键词:ref(响应数据)、v-for(列表)、v-model(表单)、onMounted(发请求)。这四个占了商城前端八成代码。