-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from star-ll/develop
Add Computed decorator and replace Effect.target
- Loading branch information
Showing
11 changed files
with
315 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Effect, effectStack } from 'src/reactive/effect'; | ||
import { DecoratorMetaKeys } from '../enums/decorators'; | ||
import { StatePool } from 'src/reactive/observe'; | ||
|
||
export default function Computed() { | ||
return function computed(target: any, propertyKey: string) { | ||
const computedKeys = Reflect.getMetadata(DecoratorMetaKeys.computedKeys, target) || new Set(); | ||
computedKeys.add(propertyKey); | ||
Reflect.defineMetadata(DecoratorMetaKeys.computedKeys, computedKeys, target); | ||
}; | ||
} | ||
|
||
export function computed(this: any, name: string, descriptor: { get: () => any; set?: (value: any) => any }) { | ||
// eslint-disable-next-line @typescript-eslint/no-this-alias | ||
const target = this; | ||
let dirty = true; | ||
let value: any; | ||
const statePool = Reflect.getMetadata('statePool', this) as StatePool; | ||
const getter = descriptor.get; | ||
const setter = descriptor.set; | ||
|
||
descriptor.get = function () { | ||
if (effectStack.current && effectStack.current.stateNode === target) { | ||
const effect = effectStack.current.effect; | ||
effect.captureSelf(target, name); | ||
} | ||
|
||
const effect = new Effect(() => { | ||
dirty = true; | ||
statePool.notify(target, name); | ||
}); | ||
|
||
if (dirty) { | ||
effectStack.push({ | ||
effect, | ||
stateNode: target, | ||
}); | ||
value = getter(); | ||
effectStack.pop(); | ||
|
||
dirty = false; | ||
} | ||
|
||
return value; | ||
}; | ||
|
||
if (setter) { | ||
descriptor.set = function (value: unknown) { | ||
setter.call(target, value); | ||
dirty = true; | ||
statePool.notify(target, name); | ||
}; | ||
} | ||
|
||
return descriptor; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
import Component from './Component'; | ||
import Prop from './Prop'; | ||
import State from './State'; | ||
import Computed from './Computed'; | ||
import Watch from './Watch'; | ||
import Ref, { RefType } from './Ref'; | ||
import Store from './Store'; | ||
import { Event, Listen, type EventEmitter as EventEmitterType } from './Event'; | ||
|
||
type EventEmitter = EventEmitterType | undefined; | ||
|
||
export { Component, Prop, State, Watch, Ref, Event, Listen, Store, type EventEmitter, type RefType }; | ||
export { Component, Prop, State, Computed, Watch, Ref, Event, Listen, Store, type EventEmitter, type RefType }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export enum DecoratorMetaKeys { | ||
computedKeys = 'computedKeys', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Component, DecoElement, Computed, State } from '@decoco/core'; | ||
|
||
@Component('test-computed') | ||
export class ComputedTest extends DecoElement { | ||
@State() | ||
state = { | ||
value: 0, | ||
}; | ||
|
||
@State() | ||
list: { id: number; value: string }[] = []; | ||
|
||
@Computed() | ||
get computedValue() { | ||
const global = window as any; | ||
global.computeCount = (global.computeCount || 0) + 1; // record computed execute count | ||
|
||
const result = this.list.find((i) => i.id === this.state.value)?.value || `value is ${this.state.value}`; | ||
return result; | ||
} | ||
set computedValue(value: string) { | ||
console.log('set computedValue', value); | ||
this.state.value = Number(value); | ||
} | ||
|
||
constructor() { | ||
super(); | ||
|
||
setTimeout(() => { | ||
this.list = new Array(10).fill(0).map((_, index) => ({ id: index, value: 'list index is ' + index })); | ||
}, 1000); | ||
} | ||
|
||
render() { | ||
const getComputedValue = () => { | ||
console.log('computedValue=' + this.computedValue); | ||
}; | ||
return ( | ||
<div> | ||
<div>computedValue: {this.computedValue}</div> | ||
<div>state.value: {this.state.value}</div> | ||
<button onClick={() => this.state.value++}>state.value++</button> | ||
<button onClick={getComputedValue}>getComputedValue</button> | ||
<button onClick={() => (this.computedValue = String(this.state.value + 1))}> | ||
change computedValue | ||
</button> | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.