https://github.com/simonwep/reactivity-playground
💫 Simple recreation of reactivity as its mainly used in Vue3
https://github.com/simonwep/reactivity-playground
Last synced: about 1 year ago
JSON representation
💫 Simple recreation of reactivity as its mainly used in Vue3
- Host: GitHub
- URL: https://github.com/simonwep/reactivity-playground
- Owner: simonwep
- Created: 2022-06-27T15:22:06.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2022-07-03T09:48:04.000Z (about 4 years ago)
- Last Synced: 2025-05-12T19:12:44.757Z (about 1 year ago)
- Language: TypeScript
- Homepage:
- Size: 53.7 KB
- Stars: 4
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Summary
[](https://github.com/Simonwep/reactivity-demo/actions/workflows/ci.yml)
This is a demo project to better understand how [Vue3's reactivity](https://vuejs.org/guide/extras/reactivity-in-depth.html#what-is-reactivity) works internally.
Some features are ignored on purpose as it doesn't make that much sense to implement those in vanilla js without having a lifecycle.
### Implementations
* [Refs](#refs)
* [Effects](#effects)
* [Computed values](#computed-values)
* [Watchers](#watchers)
### Refs
> [back to top](#summary) | [source](src/lib/ref.ts) | [ref in vue](https://vuejs.org/api/reactivity-core.html#ref)
#### Signature
```ts
type Subscriber = (newValue: T, oldValue: T) => void
interface Ref {
subscribe(fn: Subscriber);
unSubscribe(fn: Subscriber);
value: T;
};
type ref = (v: T) => Ref;
```
#### Example
A `ref` holds a single value which can be changed at any time and subscribed to:
```ts
const a = ref(0);
a.subscribe((value, oldValue) => console.log({ value, oldValue }))
a.value = 5; // Logs {value: 5, oldValue: 0}
a.value = 2; // Logs {value: 2, oldValue: 5}
```
### Effects
> [back to top](#summary) | [source](src/lib/effect.ts) | [effects in vue](https://vuejs.org/api/reactivity-core.html#watcheffect)
#### Signature
````ts
type StopEffectCallback = () => void;
type effect = (fn: () => void) => StopEffectCallback;
````
#### Example
An effect takes a function which gets called whenever the ref accessed in it changes:
```ts
const a = ref(0);
const b = ref(0);
effect(() => console.log({ a: a.value, b: b.value }));
a.value = 5; // Logs {a: 5, b: 0}
b.value = 3; // Logs {a: 5, b: 3}
```
`effect` returns a function to clear it:
```ts
const a = ref(0);
const b = ref(0);
const stop = effect(() => console.log({ a: a.value, b: b.value }));
a.value = 5; // Logs {a: 5, b: 0}
stop();
a.value = 5; // Logs nothing
```
### Computed values
> [back to top](#summary) | [source](src/lib/computed.ts) | [computed in vue](https://vuejs.org/guide/essentials/computed.html)
#### Signature
```ts
type ComputedRef = ReadonlyRef;
type computed = (v: () => T) => ComputedRef;
```
#### Example
Same as effect but returning a value:
```ts
const a = ref(0);
const b = ref(0);
const sum = computed(() => a.value + b.value);
sum.subscribe((value, oldValue) => console.log({ value, oldValue }))
a.value = 3; // Logs {value: 3, oldValue: 0}
b.value = 5; // Logs {value: 5, oldValue: 3}
```
Trying to set the value of a computed value will throw an error.
### Watchers
> [back to top](#summary) | [source](src/lib/watch.ts) | [watchers in vue](https://vuejs.org/guide/essentials/watchers.html)
#### Signature
```ts
interface WatchOptions {
immediate?: boolean;
};
type StopWatchCallback = () => void;
type WatchCallback = (args: UnwrapRefs) => void;
type watch = (
refs: T,
cb: WatchCallback,
options: WatchOptions
) => StopWatchCallback;
```
#### Example
Watches a list or a single ref.
```ts
const a = ref(6);
const b = ref(3);
const stop = watch([a, b], ([a, b]) => {
console.log({ a, b }); // {a: 6, b: 4}
});
// Trigger watch by changing "b"
b.value = 4;
// Stop watching
stop();
```
### Readonly
> [back to top](#summary) | [source](src/lib/readonly.ts) | [readonly in vue](https://vuejs.org/api/reactivity-core.html#readonly)
#### Signature
```ts
type ReadonlyRef = Ref;
type Readonly = (v: Ref) => ReadonlyRef;
```
#### Example
Wraps a [`ref`](#refs) and marks it as readonly:
```ts
const a = ref(6);
const b = readonly(a);
b.value; // 6
a.value = 7;
b.value; // 7;
b.value = 5; // Throw error
```