Skip to content

Pinia 课程计划

课程概述

本课程将带你从零开始实现一个状态管理系统,理解 Pinia 的核心原理。

课程目标

  • 理解状态管理的原理
  • 掌握 Store 的定义和使用
  • 学习响应式状态和动作
  • 能够构建自己的状态管理库

课程结构

8 节课,每节 20-40 分钟,总时长约 90-120 分钟。


第 1 课:Pinia 简介

目标

  • 了解 Pinia 的背景
  • 理解状态管理的概念
  • 掌握 Pinia 的核心功能

内容

  1. Pinia 背景

    • 什么是 Pinia
    • 为什么需要状态管理
    • Pinia vs Vuex
  2. 核心概念

    • Store
    • State
    • Getters
    • Actions
  3. Pinia 的优势

    • TypeScript 支持
    • 模块化设计
    • 更简洁的 API

实践步骤

bash
# 1. 创建项目
mkdir pinia-course
cd pinia-course

# 2. 初始化项目
npm init -y

# 3. 安装 Vue
npm install vue --save

预期输出

✓ 项目初始化完成
✓ Vue 安装完成

总结

  • ✅ 理解了状态管理的概念
  • ✅ 掌握了核心功能
  • ✅ 了解了 Pinia 的优势

第 2 课:Store 定义

目标

  • 理解 Store 的原理
  • 实现 Store 定义
  • 学习 Store 配置

内容

  1. Store 定义

    • 什么是 Store
    • Store 结构
    • Store 配置
  2. 实现 Store

    • State 定义
    • Getter 定义
    • Action 定义
  3. 测试 Store

    • 单元测试
    • 集成测试

实践步骤

bash
# 1. 创建 Store
cat > src/store.js << 'EOF'
export function createStore(options) {
  const store = {
    id: options.id,
    state: options.state || {},
    getters: options.getters || {},
    actions: options.actions || {}
  }
  
  return store
}
EOF

# 2. 创建测试
cat > test/store.test.js << 'EOF'
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { createStore } from '../src/store.js'

describe('Store 测试', () => {
  it('应该创建 Store', () => {
    const store = createStore({
      id: 'main',
      state: { count: 0 }
    })
    assert.ok(store)
    assert.strictEqual(store.id, 'main')
  })
})
EOF

# 3. 运行测试
npm test

预期输出

✓ 应该创建 Store

总结

  • ✅ 实现了 Store 定义
  • ✅ 理解了 Store 结构
  • ✅ 掌握了 Store 配置

第 3 课:响应式状态

目标

  • 理解响应式状态的原理
  • 实现响应式状态
  • 学习状态订阅

内容

  1. 响应式状态

    • 什么是响应式
    • Proxy 原理
    • 依赖收集
  2. 实现响应式状态

    • Proxy 拦截
    • 状态更新
    • 依赖通知
  3. 测试响应式状态

    • 单元测试
    • 集成测试

实践步骤

bash
# 1. 创建响应式状态
cat > src/reactive.js << 'EOF'
export function reactive(obj) {
  const listeners = new Map()
  
  return new Proxy(obj, {
    get(target, key) {
      // 依赖收集
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      // 通知监听器
      notify(key, value)
      return true
    }
  })
  
  function notify(key, value) {
    const keyListeners = listeners.get(key) || []
    keyListeners.forEach(listener => listener(value))
  }
}
EOF

# 2. 创建测试
cat > test/reactive.test.js << 'EOF'
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { reactive } from '../src/reactive.js'

describe('响应式状态测试', () => {
  it('应该创建响应式对象', () => {
    const state = reactive({ count: 0 })
    assert.ok(state)
  })
  
  it('应该更新状态', () => {
    const state = reactive({ count: 0 })
    state.count = 1
    assert.strictEqual(state.count, 1)
  })
})
EOF

# 3. 运行测试
npm test

预期输出

✓ 应该创建响应式对象
✓ 应该更新状态

总结

  • ✅ 实现了响应式状态
  • ✅ 理解了 Proxy 原理
  • ✅ 掌握了状态订阅

第 4 课:Getters

目标

  • 理解 Getters 的原理
  • 实现 Getters
  • 学习计算属性

内容

  1. Getters

    • 什么是 Getters
    • Getter 原理
    • 缓存机制
  2. 实现 Getters

    • Getter 定义
    • 缓存实现
    • 依赖追踪
  3. 测试 Getters

    • 单元测试
    • 集成测试

实践步骤

bash
# 1. 创建 Getters
cat > src/getters.js << 'EOF'
export function createGetters(state, getters) {
  const computedGetters = {}
  
  for (const key in getters) {
    let cache = null
    let dirty = true
    
    computedGetters[key] = {
      get() {
        if (dirty) {
          cache = getters[key].call(state, state)
          dirty = false
        }
        return cache
      },
      set() {
        dirty = true
      }
    }
  }
  
  return computedGetters
}
EOF

# 2. 创建测试
cat > test/getters.test.js << 'EOF'
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { createGetters } from '../src/getters.js'

describe('Getters 测试', () => {
  it('应该创建 Getters', () => {
    const state = { count: 0 }
    const getters = {
      double: (state) => state.count * 2
    }
    
    const computedGetters = createGetters(state, getters)
    assert.ok(computedGetters)
  })
  
  it('应该计算 Getter', () => {
    const state = { count: 5 }
    const getters = {
      double: (state) => state.count * 2
    }
    
    const computedGetters = createGetters(state, getters)
    assert.strictEqual(computedGetters.double.get(), 10)
  })
})
EOF

# 3. 运行测试
npm test

预期输出

✓ 应该创建 Getters
✓ 应该计算 Getter

总结

  • ✅ 实现了 Getters
  • ✅ 理解了缓存机制
  • ✅ 掌握了计算属性

第 5 课:Actions

目标

  • 理解 Actions 的原理
  • 实现 Actions
  • 学习异步处理

内容

  1. Actions

    • 什么是 Actions
    • Action 原理
    • 异步处理
  2. 实现 Actions

    • Action 定义
    • 上下文绑定
    • 错误处理
  3. 测试 Actions

    • 单元测试
    • 集成测试

实践步骤

bash
# 1. 创建 Actions
cat > src/actions.js << 'EOF'
export function createActions(store, actions) {
  const boundActions = {}
  
  for (const key in actions) {
    boundActions[key] = async (...args) => {
      try {
        return await actions[key].call(store, ...args)
      } catch (error) {
        console.error(`Action ${key} failed:`, error)
        throw error
      }
    }
  }
  
  return boundActions
}
EOF

# 2. 创建测试
cat > test/actions.test.js << 'EOF'
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { createActions } from '../src/actions.js'

describe('Actions 测试', () => {
  it('应该创建 Actions', () => {
    const store = { state: { count: 0 } }
    const actions = {
      increment: function() {
        this.state.count++
      }
    }
    
    const boundActions = createActions(store, actions)
    assert.ok(boundActions)
  })
  
  it('应该执行 Action', async () => {
    const store = { state: { count: 0 } }
    const actions = {
      increment: function() {
        this.state.count++
      }
    }
    
    const boundActions = createActions(store, actions)
    await boundActions.increment()
    assert.strictEqual(store.state.count, 1)
  })
})
EOF

# 3. 运行测试
npm test

预期输出

✓ 应该创建 Actions
✓ 应该执行 Action

总结

  • ✅ 实现了 Actions
  • ✅ 理解了上下文绑定
  • ✅ 掌握了异步处理

第 6 课:模块化

目标

  • 理解模块化的原理
  • 实现模块化 Store
  • 学习 Store 组合

内容

  1. 模块化

    • 什么是模块化
    • 模块隔离
    • 模块通信
  2. 实现模块化

    • Store 注册
    • 模块访问
    • 模块通信
  3. 测试模块化

    • 单元测试
    • 集成测试

实践步骤

bash
# 1. 创建模块化
cat > src/modules.js << 'EOF'
export function createPinia() {
  const stores = new Map()
  
  return {
    defineStore(id, setup) {
      const store = setup()
      stores.set(id, store)
      return store
    },
    
    getStore(id) {
      return stores.get(id)
    },
    
    removeStore(id) {
      stores.delete(id)
    }
  }
}
EOF

# 2. 创建测试
cat > test/modules.test.js << 'EOF'
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { createPinia } from '../src/modules.js'

describe('模块化测试', () => {
  it('应该创建 Pinia', () => {
    const pinia = createPinia()
    assert.ok(pinia)
  })
  
  it('应该定义 Store', () => {
    const pinia = createPinia()
    const store = pinia.defineStore('main', () => ({
      state: { count: 0 }
    }))
    assert.ok(store)
  })
})
EOF

# 3. 运行测试
npm test

预期输出

✓ 应该创建 Pinia
✓ 应该定义 Store

总结

  • ✅ 实现了模块化
  • ✅ 理解了模块隔离
  • ✅ 掌握了模块通信

第 7 课:持久化

目标

  • 理解持久化的原理
  • 实现状态持久化
  • 学习存储策略

内容

  1. 持久化

    • 什么是持久化
    • 持久化策略
    • 存储方案
  2. 实现持久化

    • LocalStorage
    • SessionStorage
    • 自定义存储
  3. 测试持久化

    • 单元测试
    • 集成测试

实践步骤

bash
# 1. 创建持久化
cat > src/persist.js << 'EOF'
export function createPersistPlugin(options = {}) {
  const storage = options.storage || localStorage
  const key = options.key || 'pinia'
  
  return {
    install(store) {
      // 从存储恢复状态
      const saved = storage.getItem(key)
      if (saved) {
        Object.assign(store.state, JSON.parse(saved))
      }
      
      // 监听状态变化
      store.$subscribe((mutation, state) => {
        storage.setItem(key, JSON.stringify(state))
      })
    }
  }
}
EOF

# 2. 创建测试
cat > test/persist.test.js << 'EOF'
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { createPersistPlugin } from '../src/persist.js'

describe('持久化测试', () => {
  it('应该创建持久化插件', () => {
    const plugin = createPersistPlugin()
    assert.ok(plugin)
  })
})
EOF

# 3. 运行测试
npm test

预期输出

✓ 应该创建持久化插件

总结

  • ✅ 实现了持久化
  • ✅ 理解了存储策略
  • ✅ 掌握了状态恢复

第 8 课:总结与扩展

目标

  • 总结所有课程
  • 回顾关键概念
  • 提供扩展建议

内容

  1. 课程总结

    • 回顾所有功能
    • 总结关键概念
    • 展示完整代码
  2. 扩展建议

    • 添加更多功能
    • 优化性能
    • 支持更多特性
  3. 下一步

    • 学习 Pinia 源码
    • 参与开源项目
    • 构建自己的状态管理库

总结

通过本课程,你学会了:

  1. ✅ Pinia 简介
  2. ✅ Store 定义
  3. ✅ 响应式状态
  4. ✅ Getters
  5. ✅ Actions
  6. ✅ 模块化
  7. ✅ 持久化

下一步

  • 学习 Pinia 源码
  • 添加更多功能
  • 参与开源项目

参考资源

架构师AI杜公众号二维码

扫描二维码关注"架构师AI杜"公众号,获取更多技术内容和最新动态