cbvirtua 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/vant/style/README.md +79 -0
- package/vant/style/README.zh-CN.md +79 -0
- package/vant/style/animation.less +139 -0
- package/vant/style/base.less +10 -0
- package/vant/style/clearfix.less +5 -0
- package/vant/style/demo/index.vue +110 -0
- package/vant/style/ellipsis.less +13 -0
- package/vant/style/hairline.less +47 -0
- package/vant/style/mixins/clearfix.less +7 -0
- package/vant/style/mixins/ellipsis.less +15 -0
- package/vant/style/mixins/hairline.less +39 -0
- package/vant/style/normalize.less +38 -0
- package/vant/style/reset.less +171 -0
- package/vant/style/var.less +901 -0
- package/vant/tab/README.md +307 -0
- package/vant/tab/README.zh-CN.md +342 -0
- package/vant/tab/demo/index.vue +193 -0
- package/vant/tab/index.js +95 -0
- package/vant/tab/index.less +17 -0
- package/vant/tab/test/__snapshots__/demo.spec.js.snap +349 -0
- package/vant/tab/test/__snapshots__/index.spec.js.snap +352 -0
- package/vant/tab/test/__snapshots__/insert.spec.js.snap +63 -0
- package/vant/tab/test/demo.spec.js +4 -0
- package/vant/tab/test/index.spec.js +435 -0
- package/vant/tab/test/insert.spec.js +75 -0
- package/vant/tabs/Content.js +79 -0
- package/vant/tabs/Title.js +91 -0
- package/vant/tabs/index.js +453 -0
- package/vant/tabs/index.less +153 -0
- package/vant/tabs/utils.ts +53 -0
- package/vant/utils/constant.ts +11 -0
- package/vant/utils/create/bem.ts +45 -0
- package/vant/utils/create/component.ts +86 -0
- package/vant/utils/create/i18n.ts +16 -0
- package/vant/utils/create/index.ts +14 -0
- package/vant/utils/deep-assign.ts +27 -0
- package/vant/utils/deep-clone.ts +23 -0
- package/vant/utils/dom/event.ts +56 -0
- package/vant/utils/dom/node.ts +7 -0
- package/vant/utils/dom/raf.ts +40 -0
- package/vant/utils/dom/reset-scroll.ts +16 -0
- package/vant/utils/dom/scroll.ts +81 -0
- package/vant/utils/dom/style.ts +11 -0
- package/vant/utils/format/number.ts +52 -0
- package/vant/utils/format/string.ts +15 -0
- package/vant/utils/format/unit.ts +61 -0
- package/vant/utils/functional.ts +73 -0
- package/vant/utils/index.ts +79 -0
- package/vant/utils/interceptor.ts +27 -0
- package/vant/utils/router.ts +54 -0
- package/vant/utils/test/bem.spec.js +39 -0
- package/vant/utils/test/index.spec.js +152 -0
- package/vant/utils/test/interceptor.spec.js +50 -0
- package/vant/utils/types.ts +40 -0
- package/vant/utils/validate/date.ts +8 -0
- package/vant/utils/validate/email.ts +5 -0
- package/vant/utils/validate/mobile.ts +6 -0
- package/vant/utils/validate/number.ts +12 -0
- package/vant/utils/validate/system.ts +13 -0
- package/vant/utils/vnodes.ts +33 -0
- package/vue2/ex.vue +66 -0
- package/vue2/exx.vue +44 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue Router support
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { RenderContext } from 'vue/types';
|
|
6
|
+
import VueRouter, { RawLocation } from 'vue-router/types';
|
|
7
|
+
|
|
8
|
+
export type RouteConfig = {
|
|
9
|
+
url?: string;
|
|
10
|
+
to?: RawLocation;
|
|
11
|
+
replace?: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function isRedundantNavigation(err: Error) {
|
|
15
|
+
return (
|
|
16
|
+
err.name === 'NavigationDuplicated' ||
|
|
17
|
+
// compatible with vue-router@3.3
|
|
18
|
+
(err.message && err.message.indexOf('redundant navigation') !== -1)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function route(router: VueRouter, config: RouteConfig) {
|
|
23
|
+
const { to, url, replace } = config;
|
|
24
|
+
if (to && router) {
|
|
25
|
+
const promise = router[replace ? 'replace' : 'push'](to);
|
|
26
|
+
|
|
27
|
+
/* istanbul ignore else */
|
|
28
|
+
if (promise && promise.catch) {
|
|
29
|
+
promise.catch((err) => {
|
|
30
|
+
if (err && !isRedundantNavigation(err)) {
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
} else if (url) {
|
|
36
|
+
replace ? location.replace(url) : (location.href = url);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function functionalRoute(context: RenderContext) {
|
|
41
|
+
route(context.parent && context.parent.$router, context.props);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type RouteProps = {
|
|
45
|
+
url?: string;
|
|
46
|
+
replace?: boolean;
|
|
47
|
+
to?: RawLocation;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const routeProps = {
|
|
51
|
+
url: String,
|
|
52
|
+
replace: Boolean,
|
|
53
|
+
to: [String, Object],
|
|
54
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createBEM } from '../create/bem';
|
|
2
|
+
|
|
3
|
+
test('bem', () => {
|
|
4
|
+
const bem = createBEM('button');
|
|
5
|
+
|
|
6
|
+
expect(bem()).toEqual('button');
|
|
7
|
+
|
|
8
|
+
expect(bem('text')).toEqual('button__text');
|
|
9
|
+
|
|
10
|
+
expect(bem({ disabled: false })).toEqual('button');
|
|
11
|
+
|
|
12
|
+
expect(bem({ disabled: true })).toEqual('button button--disabled');
|
|
13
|
+
|
|
14
|
+
expect(bem('text', { disabled: true })).toEqual(
|
|
15
|
+
'button__text button__text--disabled'
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
expect(bem(['disabled', 'primary'])).toEqual(
|
|
19
|
+
'button button--disabled button--primary'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
expect(bem([])).toEqual('button');
|
|
23
|
+
|
|
24
|
+
expect(bem(null)).toEqual('button');
|
|
25
|
+
|
|
26
|
+
expect(bem([null])).toEqual('button');
|
|
27
|
+
|
|
28
|
+
expect(bem(['disabled', ''])).toEqual('button button--disabled');
|
|
29
|
+
|
|
30
|
+
expect(bem(['disabled', undefined])).toEqual('button button--disabled');
|
|
31
|
+
|
|
32
|
+
expect(bem('text', ['disabled', 'primary'])).toEqual(
|
|
33
|
+
'button__text button__text--disabled button__text--primary'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
expect(bem('text', [{ disabled: true }, 'primary'])).toEqual(
|
|
37
|
+
'button__text button__text--disabled button__text--primary'
|
|
38
|
+
);
|
|
39
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { deepClone } from '../deep-clone';
|
|
2
|
+
import { deepAssign } from '../deep-assign';
|
|
3
|
+
import { isDef, get, noop } from '..';
|
|
4
|
+
import { raf, cancelRaf } from '../dom/raf';
|
|
5
|
+
import { later } from '../../../test';
|
|
6
|
+
import { isEmail } from '../validate/email';
|
|
7
|
+
import { isMobile } from '../validate/mobile';
|
|
8
|
+
import { isNumeric } from '../validate/number';
|
|
9
|
+
import { isAndroid } from '../validate/system';
|
|
10
|
+
import { camelize } from '../format/string';
|
|
11
|
+
import { formatNumber } from '../format/number';
|
|
12
|
+
import { addUnit, unitToPx } from '../format/unit';
|
|
13
|
+
|
|
14
|
+
test('deepClone', () => {
|
|
15
|
+
const a = { foo: 0 };
|
|
16
|
+
const b = { foo: 0, bar: 1 };
|
|
17
|
+
const arr = [a, b];
|
|
18
|
+
expect(deepClone(a)).toEqual(a);
|
|
19
|
+
expect(deepClone(b)).toEqual(b);
|
|
20
|
+
expect(deepClone(noop)).toEqual(noop);
|
|
21
|
+
expect(deepClone(arr)).toEqual(arr);
|
|
22
|
+
expect(deepClone(undefined)).toEqual(undefined);
|
|
23
|
+
expect(deepClone(1)).toEqual(1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('deepAssign', () => {
|
|
27
|
+
expect(deepAssign({}, { foo: null })).toEqual({});
|
|
28
|
+
expect(deepAssign({}, { foo: undefined })).toEqual({});
|
|
29
|
+
expect(deepAssign({ noop: null }, { noop })).toEqual({ noop });
|
|
30
|
+
expect(deepAssign({ foo: 0 }, { bar: 1 })).toEqual({ foo: 0, bar: 1 });
|
|
31
|
+
expect(
|
|
32
|
+
deepAssign({ foo: { bar: false } }, { foo: { bar: true, foo: false } })
|
|
33
|
+
).toEqual({
|
|
34
|
+
foo: {
|
|
35
|
+
bar: true,
|
|
36
|
+
foo: false,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('isDef', () => {
|
|
42
|
+
expect(isDef(null)).toBeFalsy();
|
|
43
|
+
expect(isDef(undefined)).toBeFalsy();
|
|
44
|
+
expect(isDef(1)).toBeTruthy();
|
|
45
|
+
expect(isDef('1')).toBeTruthy();
|
|
46
|
+
expect(isDef({})).toBeTruthy();
|
|
47
|
+
expect(isDef(noop)).toBeTruthy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('camelize', () => {
|
|
51
|
+
expect(camelize('ab')).toEqual('ab');
|
|
52
|
+
expect(camelize('a-b')).toEqual('aB');
|
|
53
|
+
expect(camelize('a-b-c-d')).toEqual('aBCD');
|
|
54
|
+
expect(camelize('a-b-')).toEqual('aB-');
|
|
55
|
+
expect(camelize('-a-b')).toEqual('AB');
|
|
56
|
+
expect(camelize('-')).toEqual('-');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('get', () => {
|
|
60
|
+
expect(get({ a: 1 }, 'a')).toEqual(1);
|
|
61
|
+
expect(get({ a: { b: 2 } }, 'a.b')).toEqual(2);
|
|
62
|
+
expect(get({ a: { b: 2 } }, 'a.b.c')).toEqual('');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('isAndroid', () => {
|
|
66
|
+
expect(isAndroid()).toBeFalsy();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('raf', async () => {
|
|
70
|
+
const spy = jest.fn();
|
|
71
|
+
raf(spy);
|
|
72
|
+
|
|
73
|
+
await later(50);
|
|
74
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
75
|
+
cancelRaf(1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('isEmail', () => {
|
|
79
|
+
expect(isEmail('abc@gmail.com')).toBeTruthy();
|
|
80
|
+
expect(isEmail(' abc@gmail.com ')).toBeTruthy();
|
|
81
|
+
expect(isEmail('abc@@gmail.com')).toBeFalsy();
|
|
82
|
+
expect(isEmail('@gmail.com')).toBeFalsy();
|
|
83
|
+
expect(isEmail('abc@')).toBeFalsy();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('isMobile', () => {
|
|
87
|
+
expect(isMobile('13000000000')).toBeTruthy();
|
|
88
|
+
expect(isMobile('+8613000000000')).toBeTruthy();
|
|
89
|
+
expect(isMobile('8613000000000')).toBeTruthy();
|
|
90
|
+
expect(isMobile('1300000000')).toBeFalsy();
|
|
91
|
+
expect(isMobile('abc')).toBeFalsy();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('isNumeric', () => {
|
|
95
|
+
expect(isNumeric('1')).toBeTruthy();
|
|
96
|
+
expect(isNumeric('1.2')).toBeTruthy();
|
|
97
|
+
expect(isNumeric('1..2')).toBeFalsy();
|
|
98
|
+
expect(isNumeric('abc')).toBeFalsy();
|
|
99
|
+
expect(isNumeric('1b2')).toBeFalsy();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('formatNumber', () => {
|
|
103
|
+
// with dot
|
|
104
|
+
expect(formatNumber('abc')).toEqual('');
|
|
105
|
+
expect(formatNumber('1.2')).toEqual('1.2');
|
|
106
|
+
expect(formatNumber('abc1.2')).toEqual('1.2');
|
|
107
|
+
expect(formatNumber('123.4.')).toEqual('123.4');
|
|
108
|
+
|
|
109
|
+
// without dot
|
|
110
|
+
expect(formatNumber('1.2', false)).toEqual('1');
|
|
111
|
+
expect(formatNumber('abc1.2', false)).toEqual('1');
|
|
112
|
+
expect(formatNumber('123.4.', false)).toEqual('123');
|
|
113
|
+
|
|
114
|
+
// minus
|
|
115
|
+
expect(formatNumber('-1.2', false)).toEqual('-1');
|
|
116
|
+
expect(formatNumber('-1.2', false, false)).toEqual('1');
|
|
117
|
+
expect(formatNumber('-1.2', true)).toEqual('-1.2');
|
|
118
|
+
expect(formatNumber('-1.2-', true)).toEqual('-1.2');
|
|
119
|
+
expect(formatNumber('123-')).toEqual('123');
|
|
120
|
+
|
|
121
|
+
// special cases
|
|
122
|
+
expect(formatNumber('.1', true)).toEqual('0.1');
|
|
123
|
+
expect(formatNumber('-.1')).toEqual('-0.1');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('addUnit', () => {
|
|
127
|
+
expect(addUnit(0)).toEqual('0px');
|
|
128
|
+
expect(addUnit(10)).toEqual('10px');
|
|
129
|
+
expect(addUnit('1%')).toEqual('1%');
|
|
130
|
+
expect(addUnit('1px')).toEqual('1px');
|
|
131
|
+
expect(addUnit('1vw')).toEqual('1vw');
|
|
132
|
+
expect(addUnit('1vh')).toEqual('1vh');
|
|
133
|
+
expect(addUnit('1rem')).toEqual('1rem');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('unitToPx', () => {
|
|
137
|
+
const originGetComputedStyle = window.getComputedStyle;
|
|
138
|
+
|
|
139
|
+
window.innerWidth = 100;
|
|
140
|
+
window.innerHeight = 200;
|
|
141
|
+
window.getComputedStyle = () => ({ fontSize: '16px' });
|
|
142
|
+
|
|
143
|
+
expect(unitToPx(0)).toEqual(0);
|
|
144
|
+
expect(unitToPx(10)).toEqual(10);
|
|
145
|
+
expect(unitToPx('10px')).toEqual(10);
|
|
146
|
+
expect(unitToPx('0rem')).toEqual(0);
|
|
147
|
+
expect(unitToPx('10rem')).toEqual(160);
|
|
148
|
+
expect(unitToPx('10vw')).toEqual(10);
|
|
149
|
+
expect(unitToPx('10vh')).toEqual(20);
|
|
150
|
+
|
|
151
|
+
window.getComputedStyle = originGetComputedStyle;
|
|
152
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { later } from '../../../test';
|
|
2
|
+
import { callInterceptor } from '../interceptor';
|
|
3
|
+
|
|
4
|
+
test('#callInterceptor', async () => {
|
|
5
|
+
const done = jest.fn();
|
|
6
|
+
callInterceptor({ done });
|
|
7
|
+
expect(done).toHaveBeenCalledTimes(1);
|
|
8
|
+
|
|
9
|
+
callInterceptor({
|
|
10
|
+
interceptor: () => false,
|
|
11
|
+
done,
|
|
12
|
+
});
|
|
13
|
+
expect(done).toHaveBeenCalledTimes(1);
|
|
14
|
+
|
|
15
|
+
callInterceptor({
|
|
16
|
+
interceptor: () => true,
|
|
17
|
+
done,
|
|
18
|
+
});
|
|
19
|
+
expect(done).toHaveBeenCalledTimes(2);
|
|
20
|
+
|
|
21
|
+
callInterceptor({
|
|
22
|
+
interceptor: () => Promise.resolve(false),
|
|
23
|
+
done,
|
|
24
|
+
});
|
|
25
|
+
await later();
|
|
26
|
+
expect(done).toHaveBeenCalledTimes(2);
|
|
27
|
+
|
|
28
|
+
callInterceptor({
|
|
29
|
+
interceptor: () => Promise.resolve(true),
|
|
30
|
+
done,
|
|
31
|
+
});
|
|
32
|
+
await later();
|
|
33
|
+
expect(done).toHaveBeenCalledTimes(3);
|
|
34
|
+
|
|
35
|
+
callInterceptor({
|
|
36
|
+
interceptor: () => Promise.reject(),
|
|
37
|
+
done,
|
|
38
|
+
});
|
|
39
|
+
await later();
|
|
40
|
+
expect(done).toHaveBeenCalledTimes(3);
|
|
41
|
+
|
|
42
|
+
callInterceptor({
|
|
43
|
+
interceptor: (...args) => {
|
|
44
|
+
expect(args).toEqual(['foo']);
|
|
45
|
+
},
|
|
46
|
+
args: ['foo'],
|
|
47
|
+
done,
|
|
48
|
+
});
|
|
49
|
+
expect(done).toHaveBeenCalledTimes(3);
|
|
50
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { VNode, CreateElement, RenderContext } from 'vue';
|
|
2
|
+
import { InjectOptions, PropsDefinition } from 'vue/types/options';
|
|
3
|
+
|
|
4
|
+
export type EventHandler = (event: Event) => void;
|
|
5
|
+
|
|
6
|
+
export type ObjectIndex = Record<string, any>;
|
|
7
|
+
|
|
8
|
+
export type ScopedSlot<Props = any> = (
|
|
9
|
+
props?: Props
|
|
10
|
+
) => VNode[] | VNode | undefined;
|
|
11
|
+
|
|
12
|
+
export type DefaultSlots = {
|
|
13
|
+
default?: ScopedSlot;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type ScopedSlots = DefaultSlots & {
|
|
17
|
+
[key: string]: ScopedSlot | undefined;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ModelOptions = {
|
|
21
|
+
prop?: string;
|
|
22
|
+
event?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type DefaultProps = ObjectIndex;
|
|
26
|
+
|
|
27
|
+
export type FunctionComponent<
|
|
28
|
+
Props = DefaultProps,
|
|
29
|
+
PropDefs = PropsDefinition<Props>
|
|
30
|
+
> = {
|
|
31
|
+
(
|
|
32
|
+
h: CreateElement,
|
|
33
|
+
props: Props,
|
|
34
|
+
slots: ScopedSlots,
|
|
35
|
+
context: RenderContext<Props>
|
|
36
|
+
): VNode | undefined;
|
|
37
|
+
props?: PropDefs;
|
|
38
|
+
model?: ModelOptions;
|
|
39
|
+
inject?: InjectOptions;
|
|
40
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function isNumeric(val: string): boolean {
|
|
2
|
+
return /^\d+(\.\d+)?$/.test(val);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isNaN(val: number): val is typeof NaN {
|
|
6
|
+
if (Number.isNaN) {
|
|
7
|
+
return Number.isNaN(val);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line no-self-compare
|
|
11
|
+
return val !== val;
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { isServer } from '..';
|
|
2
|
+
|
|
3
|
+
export function isAndroid(): boolean {
|
|
4
|
+
/* istanbul ignore next */
|
|
5
|
+
return isServer ? false : /android/.test(navigator.userAgent.toLowerCase());
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isIOS(): boolean {
|
|
9
|
+
/* istanbul ignore next */
|
|
10
|
+
return isServer
|
|
11
|
+
? false
|
|
12
|
+
: /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase());
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { VNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
function flattenVNodes(vnodes: VNode[]) {
|
|
4
|
+
const result: VNode[] = [];
|
|
5
|
+
|
|
6
|
+
function traverse(vnodes: VNode[]) {
|
|
7
|
+
vnodes.forEach((vnode) => {
|
|
8
|
+
result.push(vnode);
|
|
9
|
+
|
|
10
|
+
if (vnode.componentInstance) {
|
|
11
|
+
traverse(vnode.componentInstance.$children.map((item) => item.$vnode));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (vnode.children) {
|
|
15
|
+
traverse(vnode.children);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
traverse(vnodes);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// sort children instances by vnodes order
|
|
25
|
+
export function sortChildren(children: Vue[], parent: Vue) {
|
|
26
|
+
const { componentOptions } = parent.$vnode;
|
|
27
|
+
if (!componentOptions || !componentOptions.children) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const vnodes = flattenVNodes(componentOptions.children);
|
|
32
|
+
children.sort((a, b) => vnodes.indexOf(a.$vnode) - vnodes.indexOf(b.$vnode));
|
|
33
|
+
}
|
package/vue2/ex.vue
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<p @click="exfun()" v-if="status">222</p>
|
|
4
|
+
<div v-if="refresh">
|
|
5
|
+
<exx v-show="hasData" />
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
<script>
|
|
10
|
+
import exx from './exx.vue'
|
|
11
|
+
let context = {}
|
|
12
|
+
const setContext = (vnode) => {
|
|
13
|
+
const p = new Promise((resolve, reject) => {
|
|
14
|
+
context.resolve = resolve
|
|
15
|
+
context.reject = reject
|
|
16
|
+
if (!vnode.context) {
|
|
17
|
+
vnode.context = context
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
return p
|
|
21
|
+
}
|
|
22
|
+
const initContext = () => {
|
|
23
|
+
setContext(exx) && context.resolve()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
initContext()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
name: 'ex',
|
|
31
|
+
|
|
32
|
+
data() {
|
|
33
|
+
return {
|
|
34
|
+
refresh: false,
|
|
35
|
+
status: true,
|
|
36
|
+
hasData: false
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
async beforeCreated() {
|
|
40
|
+
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async mounted() {
|
|
44
|
+
|
|
45
|
+
},
|
|
46
|
+
components: {
|
|
47
|
+
exx
|
|
48
|
+
},
|
|
49
|
+
methods: {
|
|
50
|
+
async exfun() {
|
|
51
|
+
let p = setContext(exx)
|
|
52
|
+
this.refresh = !this.refresh
|
|
53
|
+
if (this.refresh) {
|
|
54
|
+
let d = await p
|
|
55
|
+
if (d) {
|
|
56
|
+
this.hasData = true
|
|
57
|
+
this.status = false
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<style></style>
|
|
66
|
+
|
package/vue2/exx.vue
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
const NOOP = () => { }
|
|
3
|
+
export function useContext() {
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let i = 0
|
|
8
|
+
export default {
|
|
9
|
+
name: 'ex',
|
|
10
|
+
data() {
|
|
11
|
+
return {
|
|
12
|
+
exx: 'exx1'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
created() {
|
|
16
|
+
console.log(122222)
|
|
17
|
+
this.test()
|
|
18
|
+
},
|
|
19
|
+
mounted() {
|
|
20
|
+
|
|
21
|
+
},
|
|
22
|
+
components: {
|
|
23
|
+
|
|
24
|
+
},
|
|
25
|
+
methods: {
|
|
26
|
+
test() {
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
this.exx = 'exx2'
|
|
29
|
+
const { resolve } = this.$options.context
|
|
30
|
+
console.log(resolve)
|
|
31
|
+
i++
|
|
32
|
+
resolve(i)
|
|
33
|
+
|
|
34
|
+
}, 3000)
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
render() {
|
|
38
|
+
return <div>{this.exx}</div>
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<style></style>
|
|
44
|
+
|