Skip to content

Commit 7701ff8

Browse files
pikaxLinusBorgantfu
authored
feat: adding missing reactivity api from vue-next (#311)
* fix(watch): component should runCleaup() on unmount close #293 * feat: add unref API to match API with vue3 * types: making ComputedRef types inline with vue3 and provide ComputedRef type * feat: bring API to vue-3 compatible * fix rollup build * ref tests, add some sort of effect api implementation is wrong, but it just to have something kinda working, suggestions and help is welcome :) * add unref test * more tests * fix computed.spec.ts * watch/watchEffect making the apis inline with vue3 * fix state.spec.js tests * tests * apiWatch.spec.ts passing * fix computed.spec.ts * removing reactivity collection tests :( Vue2 Limitations * implementing `shallowReactive` * removing bad import :/ * rename nonReactive to markRaw and add toRaw * removing readonly.spec.ts * add shallowRef * clean stuff * cleanup * computed Ref * Add toRefs type fixes #315 * inline ref, reactive, computed, watch api to v3.0.0-beta.8 * code-review fixes * feat(lifeCycleHook): `getCurrentInstance` inside lifecycle hook * feat: warn when calling lifecycleHook outside setup() instead of throw, also change message * fix(test): capture warning properly * fix: apiLifecycleTests Co-authored-by: Thorsten <[email protected]> Co-authored-by: Anthony Fu <[email protected]>
1 parent d1715e4 commit 7701ff8

33 files changed

+2391
-302
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
},
3636
"homepage": "https://github.com/vuejs/composition-api#readme",
3737
"devDependencies": {
38-
"@types/jest": "^24.0.13",
38+
"@types/jest": "^25.2.1",
3939
"@types/node": "^12.0.2",
4040
"cross-env": "^5.2.0",
4141
"husky": "^2.7.0",
@@ -76,6 +76,9 @@
7676
},
7777
"jest": {
7878
"verbose": true,
79+
"globals": {
80+
"__DEV__": true
81+
},
7982
"setupFiles": [
8083
"<rootDir>/test/setupTest.js"
8184
],

rollup.config.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,15 @@ function genConfig({ outFile, format, mode }) {
5656
typescript: require('typescript'),
5757
}),
5858
resolve(),
59-
replace({ 'process.env.NODE_ENV': JSON.stringify(isProd ? 'production' : 'development') }),
59+
replace({
60+
'process.env.NODE_ENV': JSON.stringify(isProd ? 'production' : 'development'),
61+
__DEV__:
62+
format === 'es'
63+
? // preserve to be handled by bundlers
64+
`(__DEV__)`
65+
: // hard coded dev/prod builds
66+
!isProd,
67+
}),
6068
isProd && terser(),
6169
].filter(Boolean),
6270
};

src/apis/computed.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ interface Option<T> {
88
set: (value: T) => void;
99
}
1010

11+
export interface ComputedRef<T = any> extends WritableComputedRef<T> {
12+
readonly value: T;
13+
}
14+
15+
export interface WritableComputedRef<T> extends Ref<T> {}
16+
1117
// read-only
12-
export function computed<T>(getter: Option<T>['get']): Readonly<Ref<Readonly<T>>>;
18+
export function computed<T>(getter: Option<T>['get']): ComputedRef<T>;
1319
// writable
14-
export function computed<T>(options: Option<T>): Ref<Readonly<T>>;
20+
export function computed<T>(options: Option<T>): WritableComputedRef<T>;
1521
// implement
1622
export function computed<T>(
1723
options: Option<T>['get'] | Option<T>
18-
): Readonly<Ref<Readonly<T>>> | Ref<Readonly<T>> {
24+
): ComputedRef<T> | WritableComputedRef<T> {
1925
const vm = getCurrentVM();
2026
let get: Option<T>['get'], set: Option<T>['set'] | undefined;
2127
if (typeof options === 'function') {
@@ -37,7 +43,7 @@ export function computed<T>(
3743
return createRef<T>({
3844
get: () => (computedHost as any).$$state,
3945
set: (v: T) => {
40-
if (process.env.NODE_ENV !== 'production' && !set) {
46+
if (__DEV__ && !set) {
4147
warn('Computed property was assigned to but it has no setter.', vm!);
4248
return;
4349
}

src/apis/inject.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { ComponentInstance } from '../component';
2-
import { ensureCurrentVMInFn } from '../helper';
2+
import { currentVMInFn } from '../helper';
33
import { hasOwn, warn } from '../utils';
4+
import { getCurrentVM } from '../runtimeContext';
45

56
const NOT_FOUND = {};
67
export interface InjectionKey<T> extends Symbol {}
78

8-
function resolveInject(provideKey: InjectionKey<any>, vm: ComponentInstance): any {
9+
function resolveInject(provideKey: InjectionKey<any> | string, vm: ComponentInstance): any {
910
let source = vm;
1011
while (source) {
1112
// @ts-ignore
@@ -20,7 +21,9 @@ function resolveInject(provideKey: InjectionKey<any>, vm: ComponentInstance): an
2021
}
2122

2223
export function provide<T>(key: InjectionKey<T> | string, value: T): void {
23-
const vm: any = ensureCurrentVMInFn('provide');
24+
const vm: any = currentVMInFn('provide');
25+
if (!vm) return;
26+
2427
if (!vm._provided) {
2528
const provideCache = {};
2629
Object.defineProperty(vm, '_provided', {
@@ -34,19 +37,23 @@ export function provide<T>(key: InjectionKey<T> | string, value: T): void {
3437

3538
export function inject<T>(key: InjectionKey<T> | string): T | undefined;
3639
export function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T;
37-
export function inject<T>(key: InjectionKey<T> | string, defaultValue?: T): T | undefined {
40+
export function inject(key: InjectionKey<any> | string, defaultValue?: unknown) {
3841
if (!key) {
3942
return defaultValue;
4043
}
4144

42-
const vm = ensureCurrentVMInFn('inject');
43-
const val = resolveInject(key as InjectionKey<T>, vm);
44-
if (val !== NOT_FOUND) {
45-
return val;
46-
} else {
47-
if (defaultValue === undefined && process.env.NODE_ENV !== 'production') {
48-
warn(`Injection "${String(key)}" not found`, vm);
45+
const vm = getCurrentVM();
46+
if (vm) {
47+
const val = resolveInject(key, vm);
48+
if (val !== NOT_FOUND) {
49+
return val;
50+
} else {
51+
if (defaultValue === undefined && process.env.NODE_ENV !== 'production') {
52+
warn(`Injection "${String(key)}" not found`, vm);
53+
}
54+
return defaultValue;
4955
}
50-
return defaultValue;
56+
} else {
57+
warn(`inject() can only be used inside setup() or functional components.`);
5158
}
5259
}

src/apis/lifecycle.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
11
import { VueConstructor } from 'vue';
22
import { ComponentInstance } from '../component';
3-
import { getCurrentVue } from '../runtimeContext';
4-
import { ensureCurrentVMInFn } from '../helper';
3+
import { getCurrentVue, setCurrentVM, getCurrentVM } from '../runtimeContext';
4+
import { currentVMInFn } from '../helper';
55

66
const genName = (name: string) => `on${name[0].toUpperCase() + name.slice(1)}`;
77
function createLifeCycle(lifeCyclehook: string) {
88
return (callback: Function) => {
9-
const vm = ensureCurrentVMInFn(genName(lifeCyclehook));
10-
injectHookOption(getCurrentVue(), vm, lifeCyclehook, callback);
9+
const vm = currentVMInFn(genName(lifeCyclehook));
10+
if (vm) {
11+
injectHookOption(getCurrentVue(), vm, lifeCyclehook, callback);
12+
}
1113
};
1214
}
1315

1416
function injectHookOption(Vue: VueConstructor, vm: ComponentInstance, hook: string, val: Function) {
1517
const options = vm.$options as any;
1618
const mergeFn = Vue.config.optionMergeStrategies[hook];
17-
options[hook] = mergeFn(options[hook], val);
19+
options[hook] = mergeFn(options[hook], wrapHookCall(vm, val));
20+
}
21+
22+
function wrapHookCall(vm: ComponentInstance, fn: Function) {
23+
return (...args: any) => {
24+
let preVm = getCurrentVM();
25+
setCurrentVM(vm);
26+
try {
27+
return fn(...args);
28+
} finally {
29+
setCurrentVM(preVm);
30+
}
31+
};
1832
}
1933

2034
// export const onCreated = createLifeCycle('created');

src/apis/state.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1-
export { reactive, ref, Ref, isRef, toRefs, set } from '../reactivity';
1+
export {
2+
reactive,
3+
ref,
4+
Ref,
5+
isRef,
6+
toRefs,
7+
set,
8+
toRef,
9+
isReactive,
10+
UnwrapRef,
11+
markRaw,
12+
unref,
13+
shallowReactive,
14+
toRaw,
15+
shallowRef,
16+
triggerRef,
17+
} from '../reactivity';

0 commit comments

Comments
 (0)