State.js->Concepts

本文深入探讨了状态模式的核心概念,包括状态(State)实例如何封装对象在特定时刻的状态与行为,以及状态之间的转换机制。此外,文章详细介绍了状态模型的层次结构、状态间的继承关系及其线性化过程,并解释了如何通过状态的parastate和superstate关系实现多继承。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

States

 State 的实例封装了owner在指定时刻下的条件和行为。. 一个 State 是又methods, arbitrary data, events, guards, substates, 和 transition expressions的集合组成。

一个owner通常拥有多个 States, 并且指向其中一个作为 current state, 在current state中owner会表现出相应的方法和行为。通过行为来触发 transition使得由一个状态转变为另外一个状态。

Object model

State objects are modeled by a set of relational references that define three distinct dimensions or “axes”.状态对象是由一组定义三个不同的维度或“轴”关系的参考蓝本。

从根本上来说,State 模型是分层次的,从 owner 拥有着唯一的root state开始,每个state都作为 superstate substates 继承

一个 State 可能从零个或者多个 parastates继承,提供了定义成分的关系,通过C3线性多重继承实现的一种手段。 providing a means to define compositional relations, implemented via C3 linearized multiple inheritance.

如果owner的state树是由其他owner的prototypal继承而来 ,继承的owner将可以view their prototype’s States as protostates from which their own epistates inherit.

var p = {};
state( p, {
    A: state,
    B: state({
        BA: state,
        BB: state
    })
});

var o = Object.create( p );
state( o, {
    A: state({
        AA: state.extend('X, Y')
    }),
    X: state,
    Y: state
});

State object model

State S 的继承顺序如下 relation precedence:

  1. Sprotostate继承链
  2. Sparastates,按照声明的先后顺序
  3. Ssuperstate

其中parastate和superstate线性加载, or “parastate–superstate chain”,  protostate则按照顺序加载

The root state

所有被 State 影响的 owner 都要单独的 root state. root state的名称为唯一的空字符串 ''.

owner.state().root === owner.state('');   // >>> true (invariant)
owner.state('->');
owner.state();                            // >>> State ''

默认的owner’s 初始current state被设置为 root state — 除非 root state 被标记为 abstract attribute, 或者另外一个 State 被标记为 initial attribute.

root state 还可以用来存储 methods 并且可以被owner的 States重写。这些方法被替换至root state。如果没有被重写,则会调用默认的方法。

Superstates and substates

 owner 表现得行为由 substates 决定 ,这些substates superstates 生成

var o = {};
state( o, {
    A: state({
        AA: state,
        AB: state
    }),
    B: state
});


var root = o.state('');                    // >>> RootState
o.state() === root;                        // >>> true
o.state('-> AA');
o.state() === o.state('AA');               // >>> true
o.state().superstate === o.state('A');     // >>> true
o.state().superstate.superstate === root;  // >>> true

Superstates and substates

Parastates and composition

除了通过 superstates 继承,State 模型还支持通过 parastate 关系实现多继承。

The lone exception to this is a RootState, which bears neither relation.

Parastates 通过 state.extend 函数声明, which takes a string of one or more paths to parastates, along with optional parameters attributes and expression, and returns a StateExpression that can be used to produce a State with the named parastates.

var o = {};
state( o, {
    A: state({
        AA: state.extend('X, Y')
    }),
    X: state,
    Y: state
});

State AA inherits conventionally from superstate A, but not before inheriting compositionally from parastates X and Y.

Linearization, inheriting precedence, and monotonicity

The resolution order by which a State inherits from its lineage of parastate and superstate ancestors is guaranteed to be unambiguous. It is also guaranteed to be monotonic relative to the resolution order for any descendants of the State:

  • Given State S with ancestor States A and B (either parastates or superstates), where A precedes B in the resolution order of S;

  • A State T, to which S is related as either a parastate or superstate of T, is guaranteed to encounter A before B in its own resolution order.

These assertions are enforced by an implementation of the C3 linearization algorithm (Dylan, Perl, Python) — with the State–specific stipulations that:

  • A State’s “parents” are defined and ordered by its immediate parastates, in declared order, followed by its immediate superstate.

  • A RootState by rule cannot inherit from parastates, and by definition does not inherit from a superstate.

Parastates

Parastate–superstate graph and linearization — from the example code above, parastates X and Y of State AA are depicted to the left of its superstate A, indicating the superstate’s intrinsic position as the “final parent” of a State. The linearization of AA determines the precedence, or resolution order, by which the State will inherit methods, data, and events defined in its ancestors.

Attempting to implement an expression that produces a State graph which does not conform to the C3 restrictions will throw a TypeError.

Prototypal flattening

In the State model, a State and its parastates must share a common owner. However, parastate declarations may include paths that resolve to States belonging to a prototype of the owner. In such a case these “proto-parastates” are automatically flattened onto the owner’s state tree:

  • Given State S with owner O, which has prototype P, where P bears a State A whose path is 'A', and given that S declares path 'A' as a parastate relation;

  • As O contains no State with path 'A', the protostate A belonging to P will be automatically virtualized and realized — effectively flattening it — into the state tree of O as an epistate , with path 'A', such that S may inherit from parastate .

Miscellanea
  • The progression of a transition is conceptually orthogonal to the parastate relation, and traversal proceeds only over the state tree defined by the superstate–substate relations.

  • Parastates provide for compositional reuse of only their own or inherited methods, data, and custom events. Built-in events, guards, substates, transitions, and attributes are not heritable via parastate.




### 解决方案 当在使用 Pinia 时遇到 `'getActivePinia() was called but there was no active Pinia'` 的错误,通常是因为未正确安装或初始化 Pinia 插件。以下是详细的解决方案: #### 错误原因分析 此错误表明调用了 `getActivePinia()` 方法,但在当前上下文中并未找到已激活的 Pinia 实例[^1]。这种情况可能发生在以下场景之一: - Pinia 尚未被注册到 Vue 应用实例中。 - 调用 `defineStore` 或其他依赖于 Pinia 上下文的方法时,不在组件树中的有效范围。 #### 正确配置 Pinia 为了确保 Pinia 可以正常工作并避免该错误,需按照如下方式正确设置 Pinia: ```javascript // main.js or main.ts (Vue 应用入口文件) import { createApp } from 'vue'; import App from './App.vue'; import { createPinia } from 'pinia'; const app = createApp(App); const pinia = createPinia(); app.use(pinia); // 注册 Pinia 到应用实例 app.mount('#app'); ``` 如果遗漏了上述步骤,则可能导致无法创建有效的 Pinia 上下文,从而引发错误。 #### 使用 `useStore` 函数时注意事项 在定义 Store 并尝试访问它时,应始终确保是在已经挂载好 Pinia 的环境中执行操作。例如,在组件内部可以通过组合式 API 访问 Store: ```javascript <script setup> import { useSomeStore } from '@/stores/someStore'; // 替换为实际路径 const someStore = useSomeStore(); // 自动检测 Pinia 上下文 </script> <template> <div>{{ someStore.someState }}</div> <!-- 绑定状态 --> </template> ``` 如果需要手动测试 Store 功能(如单元测试),则可以显式传递 Pinia 实例给 Store 工厂函数: ```javascript import { setActivePinia, createPinia } from 'pinia'; import { useSomeStore } from '@/stores/someStore'; const pinia = createPinia(); setActivePinia(pinia); const store = useSomeStore(); // 手动指定 Pinia 实例 console.log(store.someState); ``` 以上方法适用于非组件环境下的 Store 测试或调试。 #### 性能优化建议 对于复杂的应用程序结构,考虑利用浅层响应式对象来减少不必要的性能消耗。例如,可以结合 `shallowRef` 和 `shallowReactive` 提升效率[^2]: ```javascript import { shallowRef } from 'vue'; export const useOptimizedStore = defineStore('optimized', { state: () => ({ data: shallowRef({}), }), }); ``` 这样能够显著降低深层次嵌套数据带来的性能负担。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值