1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import Accessor from'@geoscene/core/core/Accessor';
import { subclass } from"@geoscene/core/core/accessorSupport/decorators";
// A type to represent a constructor functiontype Constructor<T = object> = new (...args: any[]) => T;
// A type to represent a mixin function// See for more details https://www.bryntum.com/blog/the-mixin-pattern-in-typescript-all-you-need-to-know/type Mixin<T extends (...input: any[]) => any> = InstanceType<ReturnType<T>>;
// TBase extends Constructor<Accessor> indicating that `EventedMixin`// expects the base class to extend `Accessor`, for example to be able to use the `watch` method.exportconst EventedMixin = <TBase extends Constructor<Accessor>>(Base: TBase) => {
@subclass("custom.EventedMixin")
class Evented extends Base {
// A first function defined by the mixin
emit(type: string, event?: any): boolean {
// ...
}
// Another function defined by the mixin
on(type: string, listener: (event: any) => void): IHandle {
// ...
}
}
}
// define the type of the mixin. This is useful to type properties that extends this mixin
// eg: `myProperty: EventedMixin;`
export type EventedMixinType = Mixin<typeof EventedMixin>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import Accessor from'@geoscene/core/core/Accessor';
import { subclass } from"@geoscene/core/core/accessorSupport/decorators";
@subclass("custom.Collection")
classCollectionextendsAccessor{
private _items: any[] = [];
// Example: Define a custom property getter.// Accessor caches the values returned by the getters.// At this point `length` will never change.// See the "Notify a property change" section@property()
getlength(): number {
returnthis._items.length;
}
setlength(value: number) {
// Example: perform validationif (value <= 0) {
thrownewError(`value of length not valid: ${value}`);
}
// internally you can access the cached value of `length` using `_get`.const oldValue = this.get<number>("length");
if (oldValue !== value) {
// a setter has to update the value from the cachethis.set("length", value);
// Example: perform additional work when the length changesthis._items.length = value;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Accessor from'@geoscene/core/core/Accessor';
import { subclass } from"@geoscene/core/core/accessorSupport/decorators";
@subclass("custom.Person")
classPersonextendsAccessor{
// Example: read-only property may not be externally set@property({ readOnly: true })
firstName: string;
@property({ readOnly: true })
lastName: string;
updateName(firstName: string, lastName: string): void {
// We may still update the read-only property internally, which will change// the property and notify changes to watchersthis.set({
firstName: firstName,
lastName: lastName
});
}
}
定义代理属性
这些代码片段演示如何在内部属性上创建双向绑定。
代理属性 - ESM TS代理属性 - ESM TS代理属性 - AMD JS
代码块使用深色复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Accessor from'@geoscene/core/core/Accessor';
import { subclass } from"@geoscene/core/core/accessorSupport/decorators";
@subclass("custom.GroupLayer")
classGroupLayerextendsAccessor{
@property()
sublayers: Collection = new Collection();
// Define a property that reflects one in another object.@property({ aliasOf: "sublayers.length" })
length: number;
// Alternatively you can use the `@aliasOf` decorator// @aliasOf// length: number// You can also proxy a method from another object.@aliasOf("sublayers.add")
add: (item: any) =>void;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Accessor from'@geoscene/core/core/Accessor';
import { subclass } from"@geoscene/core/core/accessorSupport/decorators";
@subclass("custom.Collection")
classCollectionextendsAccessor{
private _items: any[] = [];
@property({
readOnly: true })
getlength(): number {
returnthis._items.length;
}
add(item: any): void {
this._items.push(item);
// We know the value of `length` is changed.// Notify so that at next access, the getter will be invokedthis.notifyChange("length");
}
}
自动转换
定义属性类型
可以为类的属性定义类型。
定义属性类型 - ESM TS定义属性类型 - ESM TS定义属性类型 - AMD JS
代码块使用深色复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Graphic from'@geoscene/core/Graphic';
import Accessor from'@geoscene/core/core/Accessor';
import Collection from'@geoscene/core/core/Collection';
import { subclass, property } from"@geoscene/core/core/accessorSupport/decorators";
@subclass()
classGraphicsLayerextendsAccessor{
@property({
// Define the type of the collection of Graphics// When the property is set with an array,// the collection constructor will automatically be calledtype: Collection.ofType(Graphic)
})
graphics: Collection<Graphic>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import Accessor from'@geoscene/core/core/Accessor';
import { subclass, property, cast } from"@geoscene/core/core/accessorSupport/decorators";
@subclass()
classColorextendsAccessor{
@property()
r: number = 0;
@property()
g: number = 0;
@property()
b: number = 0;
@property()
a: number = 1;
@cast("r")
@cast("g")
@cast("b")
protected castComponent(value: number): number {
// cast method to clamp the value that// will be set on r, g or b between 0 and 255returnMath.max(0, Math.min(255, value));
}
@cast("a")
protected castAlpha(value: number): number {
// cast method to clamp the value that// will be set on a between 0 and 1returnMath.max(0, Math.min(1, value));
}
}