Skip to content

作用域

计算作用域指的是传递给计算函数Getter的第一个参数。

Autostore在创建Store时,支持配置scope参数来指定计算属性函数的第一个参数,如下:

ts
export enum ObserverScopeRef{
  Root    = 'root',                   // 指向State根对象
  Current = 'current',                // 指向计算属性所在的对象
  Parent  = 'parent',                 // 指向计算属性所在对象的父对象
  Depends = 'depends'                 // 指向异步计算的依赖数组,仅在异步计算时生效
  Self    = 'self'                    // 指向自身,默认值
}

// 指定Store中计算函数的上下文,如果是字符串代表是当前对象的指定键
// 如果是string[],则代表是当前Store对象的完整路径
export type ComputedScope  =  ObserverScopeRef | string | string[]
            | ((state:any)=>string | string[] | ObserverScopeRef)

const store = new AutoStore( {
  user:{
    firstName:"Zhang",
    lastName:"Fisher",
    fullName: computed((scope)=>{
      //  scope指向user
    },["user.firstName","user.lastName"])
  }
} )
  • scope参数的类型是ComputedScope,可以是ObserverScopeRef枚举值,也可以是字符串或字符串数组,也可以是一个函数。
  • scope参数的默认值是ObserverScopeRef.Current,即指向计算属性所在的对象。

指定Scope

默认情况下computed的计算函数Getter可以指定scope参数,如下:

  • 默认值

默认情况下,scope指向计算函数所在的对象。如上例中,scope指向fullName所在的user对象。

  • 全局指定

可以在创建Store时,通过scope参数来全局指定计算属性的默认scope,如下:

tsx
const store = new AutoStore(
    {
        user: {
            firstName: "Zhang",
            lastName: "Fisher",
            fullName: computed((scope) => {
                //  scope指向root
                return scope.user.firstName + scope.user.lastName;
            }),
        },
    },
    {
        scope: ObserverScopeRef.Root, // 所有计算属性的默认scope指向状态根
    },
);
  • 局部指定

也可以局部指定计算属性的scope,如下:

tsx
const store = new AutoStore({
    user: {
        firstName: "Zhang",
        lastName: "Fisher",
        fullName: computed(
            (scope) => {
                //  scope指向root
                return scope.user.firstName + scope.user.lastName;
            },
            {
                scope: ObserverScopeRef.Root, // 仅指定当前计算属性的scope
            },
        ),
    },
});

取值范围

Current

默认情况下,scope==ObserverScopeRef.Current时,计算函数的scope指向计算函数所在的对象。

tsx
import { ObserverScopeRef, useStore } from "@autostorejs/react";
import { ColorBlock } from "x-react-components";

export default () => {
    const { state } = useStore(
        {
            user: {
                firstName: "Zhang",
                lastName: "Fisher",
                fullName: function (scope) {
                    // scope指向user对象
                    return scope.firstName + scope.lastName;
                },
            },
        },
        {
            // 指定计算属性的默认上下文指向计算函数所有的当前对象
            scope: () => ObserverScopeRef.Current,
        },
    );
    return (
        <div>
            <ColorBlock name="FullName">{state.user.fullName}</ColorBlock>
        </div>
    );
};
  • 上面代码中,fullName函数的scope指向所在的user对象,即state.user

注意🌝

scope==ObserverScopeRef.Current是默认值,一般不需要指定,以上仅仅是示例。

Root

@autostorejs/react会将计算属函数的scope指向ObserverScopeRef.Root,即当前的State根对象,如下:

tsx
import { useStore, ObserverScopeRef } from "@autostorejs/react";
import { ColorBlock } from "x-react-components";

export default () => {
    const { state } = useStore(
        {
            user: {
                firstName: "Zhang",
                lastName: "Fisher",
                fullName: function (scope) {
                    // scope指向root对象
                    return scope.user.firstName + scope.user.lastName;
                },
            },
        },
        {
            scope: ObserverScopeRef.Root,
        },
    );
    return (
        <div>
            <ColorBlock name="FullName">{state.user.fullName}</ColorBlock>
        </div>
    );
};

Parent

scope==ObserverScopeRef.Parent时,指向计算函数所在的对象的父对象。

tsx
import { new AutoStore, ObserverScopeRef } from "@autostorejs/react";
import { ColorBlock } from "x-react-components";

const { state } = new AutoStore(
    {
        parent: {
            user: {
                firstName: "Zhang",
                lastName: "Fisher",
                fullName: function (scope) {
                    // scope指向user对象的父对象,即parent
                    return scope.user.firstName + scope.user.lastName;
                },
            },
        },
    },
    {
        // 指定计算属性的默认上下文指向计算函数所有的当前对象
        scope: ObserverScopeRef.Parent,
    },
);

export default () => {
    return (
        <div>
            <ColorBlock name="FullName">{state.parent.user.fullName}</ColorBlock>
        </div>
    );
};

字符串

store.options.scope==<字符串>时,此时<字符串>就是指向绝对路径。

tsx
import { new AutoStore } from "@autostorejs/react";
import { ColorBlock } from "x-react-components";

const { state } = new AutoStore(
    {
        user: {
            firstName: "Zhang",
            lastName: "Fisher",
            fullName: function (scope) {
                // this指向user.address.city
                return scope;
            },
            address: {
                city: "Quanzhou",
            },
        },
    },
    {
        scope: "user.address.city",
    },
);

export default () => {
    return (
        <div>
            <ColorBlock name="FullName">{state.user.fullName}</ColorBlock>
        </div>
    );
};

提醒

scope===<字符串>时使用的是绝对路径,采用.作为路径分隔符,如user.address.city

字符串数组

tsx
import { new AutoStore } from "@autostorejs/react";
import { ColorBlock } from "x-react-components";

const { state } = new AutoStore(
    {
        user: {
            firstName: "Zhang",
            lastName: "Fisher",
            fullName: function (scope) {
                // this指向user.address['main.city']
                return scope;
            },
            address: {
                "main.city": "Quanzhou",
            },
        },
    },
    {
        scope: ["user", "address", "main.city"],
    },
);

export default () => {
    return (
        <div>
            <ColorBlock name="FullName">{state.user.fullName}</ColorBlock>
        </div>
    );
};

提醒

当状态路径中包含.字符时,可以使用字符串数组来指定路径,避免产生歧义。

Depends

scope==ObserverScopeRef.Depends时,指向计算函数的依赖项的值。

tsx
import { new AutoStore, computed, ObserverScopeRef } from "@autostorejs/react";
import { ColorBlock } from "x-react-components";

const { state } = new AutoStore({
    user: {
        firstName: "Zhang",
        lastName: "Fisher",
        fullName: computed(
            async (deps) => {
                return deps[0] + deps[1];
            },
            ["user.firstName", "user.lastName"], // 声明依赖
            {
                async: true,
                scope: ObserverScopeRef.Depends,
            },
        ),
    },
});

export default () => {
    return (
        <div>
            <ColorBlock name="FullName">{state.user.fullName.value}</ColorBlock>
        </div>
    );
};

提示

ObserverScopeRef.Depends仅在异步计算时生效,而异步计算必须通过computed函数来指定依赖