Skip to content
YK Blog
Go back

后端视角学前端(二):Vue 核心概念

上篇讲了前端生态全貌,这篇深入 Vue 的核心概念。所有示例来自真实项目。


1. 响应式系统

Vue 最核心的能力:改了数据,UI 自动更新。

三个基本构件:

// ref — 创建响应式变量
const count = ref(0)
count.value++  // UI 自动更新

// computed — 自动计算(依赖变了就重算)
const double = computed(() => count.value * 2)

// watch — 监听变化后执行副作用
watch(count, (newVal) => {
  console.log('count 变了:', newVal)
})

后端类比ref 像数据库字段,computed 像视图(View),watch 像触发器(Trigger)。

实际场景:用户选了”张三” → filterAddedBy 变了 → filteredAccounts(computed)自动重算 → 下拉列表 UI 自动更新。整条链路是自动的。


2. 组件化

页面拆成独立的小块,像搭积木。

AccountsPage(容器)
  ├── ArticlesTab(文章列表)
  │     ├── Pagination(分页器)
  │     └── ArticleListItem(文章卡片)
  └── AccountManageTab(数据来源)
        └── Pagination(分页器)

组件通信只有三种方式:

方式方向适用场景
props父 → 子传配置给子组件
emit子 → 父子组件通知父组件
Store任意 → 任意跨组件/跨页面共享数据
<!-- 父组件传 props -->
<Pagination :total="100" :page="1" />

<!-- 子组件发 emit -->
<button @click="$emit('change', 2)">下一页</button>

黄金法则:能用 props/emit 解决的,不用 Store。Store 是”大炮”,父子通信用”小刀”就够。


3. Composition API

Vue 3 的核心写法,按功能而非类型组织代码。

Options API(Vue 2) — 按类型分:data 一块、methods 一块、computed 一块,搜索相关的代码散落各处。

Composition API(Vue 3) — 按功能聚合,封装成可复用函数:

// composables/useArticleSearch.ts
export function useArticleSearch() {
  const filterAddedBy = ref('')
  const filterAccountId = ref('')

  const filteredAccounts = computed(() => {
    if (!filterAddedBy.value) return store.accounts
    return store.accounts.filter(a => a.added_by === filterAddedBy.value)
  })

  function doSearch() { /* ... */ }

  return { filterAddedBy, filterAccountId, filteredAccounts, doSearch }
}

组件里一行调用就能用:

const { filterAddedBy, filteredAccounts, doSearch } = useArticleSearch()

后端类比:Composable ≈ Python 的 Service 类,封装一组相关的业务逻辑。


4. 单文件组件(SFC)

一个 .vue 文件包含三部分:

<script setup lang="ts">
// 逻辑
const count = ref(0)
</script>

<template>
  <!-- UI -->
  <button @click="count++">{{ count }}</button>
</template>

<style scoped>
/* 样式(只作用于当前组件) */
button { color: blue; }
</style>

逻辑、UI、样式放一起,开发体验好。用 Tailwind 后 <style> 块通常省略。


5. 生命周期

组件从创建到销毁经历的阶段,只需记住两个:

钩子时机用途
onMounted组件渲染完成调 API 加载数据
onUnmounted组件被销毁清理定时器、关闭连接
onMounted(async () => {
  await store.load()              // 页面加载好了,拿数据
})

onUnmounted(() => {
  eventSource?.close()            // 离开页面,关闭 SSE 连接
})

后端类比onMounted@app.on_event("startup")onUnmounted@app.on_event("shutdown")


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

v-ifv-show
false 时组件销毁,移出 DOM组件还在,CSS 隐藏
true 时重新创建取消隐藏
状态保留不保留保留

选择依据:频繁切换用 v-show(避免反复创建销毁),很少切换用 v-if(减少初始渲染量)。

Tab 页切换用 v-show——切走再切回来,之前的筛选条件还在。


7. 双向绑定:v-model

输入框和变量自动双向同步:

<input v-model="searchQuery" />
<!-- 等价于 -->
<input :value="searchQuery" @input="searchQuery = $event.target.value" />

用户输入 → 变量更新 → 用到变量的 computed/watch 自动触发 → UI 更新。


8. 虚拟 DOM

Vue 不直接操作真实页面。数据变了 → 先在 JS 对象(虚拟 DOM)上算出差异 → 只把变化的部分更新到真实页面。

旧虚拟 DOM:[文章A, 文章B(未读), 文章C]
新虚拟 DOM:[文章A, 文章B(已读), 文章C]
                         ↑ 只有这里变了

Diff 结果:只改文章 B 的 class → 一行 DOM 操作搞定

好处:避免整个列表重建,性能好。Vue 3 还做了编译时优化——静态节点标记后跳过 diff。



Previous Post
后端视角学前端(三):Vue 工程实战
Next Post
后端视角学前端(一):生态全景