首页首页
前端
非前端
辅助
Github
前端
非前端
辅助
Github
  • 前端基础

    • HTML基础
    • CSS基础
    • JS基础
    • ES6基础
    • HTTP基础
    • 前端缓存
    • 页面性能
    • 数据结构基础
    • 我的文章
  • 前端进阶

    • Vue2基础
    • Vue2进阶
    • Vue3基础
    • Vue3进阶
    • React基础
    • React进阶
    • React18新特性
    • Vue和React对比
    • RN基础
    • RN环境搭建和打包发布
    • 打包工具
    • TS基础
    • Nuxt基础
    • 小程序基础
    • 微前端基础
    • uni-app基础
    • 业务相关
    • 低代码相关
  • 前端代码练习

    • CSS代码练习
    • JS代码练习
    • 算法代码练习
  • 前端代码技巧

    • 工具库
    • 工具函数
    • CSS动画库
    • CSS代码技巧
    • JS代码技巧
    • 项目技巧

1. Pinia的state是函数,而Vuex的state是对象

一、核心设计差异

特性Vuex (state为对象)Pinia (state为函数)
​​定义方式​直接对象字面量返回对象的函数
​​复用性​单例模式支持多实例
响应式初始化​需要Vue.set自动响应式
​​SSR支持​需要额外处理原生支持

二、Vuex 的 state 设计解析

1. 对象形式的原因

// vuex/src/store.js
class Store {
  constructor(options = {}) {
    // 直接将state对象挂载到实例
    this._state = options.state || {}
  }
}
  • 设计背景​​:
    • 基于 Vue 2 的响应式系统(Object.defineProperty)
    • 遵循 Flux 架构的单例模式
    • 强调"单一状态树"概念

2. 带来的限制

  • 引用共享问题​​:
const state = { count: 0 }

// 多个store实例共享同一state引用
const store1 = new Vuex.Store({ state })
const store2 = new Vuex.Store({ state })

store1.state.count++ // 会影响store2
  • SSR 问题​​:
// 服务端渲染时state会被多个请求共享
export function createStore() {
  return new Vuex.Store({
    state: { user: null } // 所有用户共享此对象
  })
}

三、Pinia 的 state 函数设计解析

1. 函数形式实现

// pinia/src/store.ts
function defineStore(id, options) {
  const setup = () => {
    // 执行state函数获取初始状态
    const state = isRef(options.state) 
      ? options.state.value
      : reactive(typeof options.state === 'function'
        ? options.state()
        : options.state)
    return { ...state }
  }
}

2. 设计优势​​:

  • ​​隔离性​​:每次调用返回新对象
// 每次useStore()都会获得独立state
const store1 = useStore()
const store2 = useStore() // 与store1完全隔离
  • 使用 Vue 3 提供的 reactive 函数将状态转换为响应式对象。
state: () => ({ count: 0 }) // 自动被reactive()包裹

四、设计哲学差异

  • Vuex 的设计理念
    • 集中式管理​​:单一状态树作为"唯一数据源"
    • 严格的数据流​​:必须通过 mutations 修改状态
    • 面向配置​​:通过对象配置创建 store
  • Pinia 的设计理念
    • ​组合式思想​​:受 Vue 3 Composition API 启发
    • ​灵活性优先​​:直接修改状态 + 自动响应式
    • ​面向函数式​​:通过工厂函数创建 store

2. Flux 架构

Flux 是 Facebook 提出的一种前端应用架构模式,专门用于解决 MVC 架构在前端复杂应用中的数据流管理问题。

一、Flux 核心概念

1. 基本架构图

2. 核心组成要素

组成部分职责描述类比 MVC
​​Actions​描述发生的事件(如ADD_TODO),携带数据载荷用户输入/事件
​​Dispatcher​中央枢纽,负责将Actions分发给所有注册的Store路由器
​Stores​业务逻辑和状态容器,维护应用状态,响应Actions进行更新Model
​​Views​展示层(React组件),监听Store变化并重新渲染,触发新ActionsView

二、Flux 实现原理

  • 数据更新流程
    • 用户交互​​:点击"添加任务"按钮
    • 创建Action​​:{ type: 'ADD_TODO', payload: '学习Flux' }
    • ​Dispatcher分发​​:将Action发送给所有Store
    • ​Store处理​​:TodoStore接收并更新状态
    • ​视图更新​​:组件监听Store变化并重新渲染

三、Flux 的现代实现

Redux职责描述类比 MVC
​​Actions​单一Store,纯函数Reducer,中间件支持React生态
Vuex专为Vue设计,支持模块化,提供mutations/actions分离Vue 2
FluxibleFacebook官方实现,支持同构应用通用

四、Flux 的优缺点

  • 优势
    • ​可预测性​​:严格单向数据流使状态变化可追踪
    • ​易于调试​​:通过Action日志可重现整个应用状态
    • ​组件解耦​​:视图层不直接修改状态,通过Action通信
    • ​测试友好​​:Store和Reducer都是纯函数,易于单元测试
  • 局限性
    • ​样板代码​​:需要编写大量Action类型和分发逻辑
    • ​学习曲线​​:对新手概念较多(Action、Dispatcher、Store)
    • ​小型项目过重​​:简单应用可能不需要如此严格的结构

3. 时间旅行调试

时间旅行调试是现代前端开发中一项革命性的调试技术,它允许开发者像操作视频播放器一样​​自由前进/后退​​应用状态,极大提升了调试效率

一、核心概念

1. 基本定义

  • 通过记录​​完整状态快照​​或​​动作序列​​,实现:
    • ​​回退​​到任意历史状态
    • ​重放​​特定操作序列
    • ​分支调试​​从历史点创建新路径

2. 技术实现原理

实现方式原理代表工具
​​状态快照​深拷贝每次状态变化Vue DevTools
​​动作重放​记录所有action+reducerRedux DevTools
增量快照​只记录变化部分+逆向操作Immer.js

二、具体实现示例

1. Redux 时间旅行实现

// 1. 创建支持时间旅行的store
import { createStore } from 'redux'
import reducer from './reducers'
const store = createStore(reducer)
// 2. 添加状态记录逻辑
const states = []
store.subscribe(() => {
  states.push(JSON.parse(JSON.stringify(store.getState())))
})
// 3. 实现时间旅行方法
function timeTravel(step) {
  const targetState = states[states.length + step]
  store.dispatch({ type: 'TIME_TRAVEL', payload: targetState })
}

2. Vuex/Pinia 的实现

// 基于vuex-plugin-history的实现
const historyPlugin = store => {
  store.subscribe((mutation, state) => {
    history.push(JSON.parse(JSON.stringify(state)))
  })
  
  store.timeTravel = index => {
    Object.assign(store.state, history[index])
  }
}

三、开发工具演示

1. Redux DevTools 操作流程

    1. 触发动作​​:点击界面按钮触发ADD_TODO
    1. 记录动作​​​​:
{ type: "ADD_TODO", payload: "学习时间旅行" }
    1. 时间旅行​​:​​
    • 拖动滑块回到之前状态
    • 查看对应时期的DOM渲染
    1. 分支调试​​:
// 从历史点创建新分支
dispatch({ type: 'JUMP_TO_STATE', index: 2 })

2. Vue DevTools 示例

# 操作步骤:
1. 打开"Timeline"标签
2. 选择组件状态变化节点
3. 点击"Time Travel"按钮
4. 观察DOM回退到选定状态

四、应用场景价值

1. 复杂Bug复现

1. 用户报告"提交表单后数据错乱"
2. 导出用户操作序列JSON
3. 在开发环境重放操作
4. 精准定位到第7步的状态异常

2. 自动化测试

// 测试用例示例
it('should handle undo correctly', () => {
  fireEvent.click(addButton)
  fireEvent.click(deleteButton)
  timeTravel(-1) // 回退到添加后状态
  expect(listItems).toHaveLength(1)
})

3. 用户行为分析

分析导出的状态序列:
- 67%用户在步骤3放弃购买
- 错误集中在"地址表单"步骤
最后更新: 2025/5/26 17:49
Prev
Vue3基础
Next
React基础