Skip to content

Commit e4d1938

Browse files
committed
✨ feat(资源): 添加新的 page
1 parent 921d7a5 commit e4d1938

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed

.eslintrc.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
root: true,
3-
env: { browser: true, node: true },
3+
env: { browser: true, node: true, es6: true },
44
extends: ['eslint:recommended'],
55
parserOptions: {
66
ecmaVersion: 'latest',

lib/components/VuePageStackNew.js

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import { cloneVNode, invokeVNodeHook, isVNode } from '../vnode';
2+
import { onBeforeUnmount, onMounted, onUpdated } from '../apiLifecycle';
3+
import { ShapeFlags, invokeArrayFns } from '@vue/shared';
4+
import { MoveType, queuePostRenderEffect } from '../renderer';
5+
import { setTransitionHooks } from './BaseTransition';
6+
import { isSuspense } from './Suspense';
7+
import { defineComponent, getCurrentInstance } from 'vue';
8+
9+
const VuePage = () => {
10+
return defineComponent({
11+
name: `VuePage`,
12+
13+
// Marker for special handling inside the renderer. We are not using a ===
14+
// check directly on KeepAlive in the renderer, because importing it directly
15+
// would prevent it from being tree-shaken.
16+
__isKeepAlive: true,
17+
18+
setup(_props, { slots }) {
19+
const instance = getCurrentInstance() || false;
20+
// KeepAlive communicates with the instantiated renderer via the
21+
// ctx where the renderer passes in its internals,
22+
// and the KeepAlive instance exposes activate/deactivate implementations.
23+
// The whole point of this is to avoid importing KeepAlive directly in the
24+
// renderer to facilitate tree-shaking.
25+
const sharedContext = instance.ctx;
26+
27+
const cache = new Map();
28+
const keys = new Set();
29+
30+
const parentSuspense = instance.suspense;
31+
32+
const {
33+
renderer: {
34+
p: patch,
35+
m: move,
36+
um: _unmount,
37+
o: { createElement }
38+
}
39+
} = sharedContext;
40+
const storageContainer = createElement('div');
41+
42+
sharedContext.activate = (vnode, container, anchor, namespace, optimized) => {
43+
const instance = vnode.component || null;
44+
move(vnode, container, anchor, MoveType.ENTER, parentSuspense);
45+
// in case props have changed
46+
patch(instance.vnode, vnode, container, anchor, instance, parentSuspense, namespace, vnode.slotScopeIds, optimized);
47+
queuePostRenderEffect(() => {
48+
instance.isDeactivated = false;
49+
if (instance.a) {
50+
invokeArrayFns(instance.a);
51+
}
52+
const vnodeHook = vnode.props && vnode.props.onVnodeMounted;
53+
if (vnodeHook) {
54+
invokeVNodeHook(vnodeHook, instance.parent, vnode);
55+
}
56+
}, parentSuspense);
57+
};
58+
59+
sharedContext.deactivate = vnode => {
60+
const instance = vnode.component || null;
61+
move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense);
62+
queuePostRenderEffect(() => {
63+
if (instance.da) {
64+
invokeArrayFns(instance.da);
65+
}
66+
const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted;
67+
if (vnodeHook) {
68+
invokeVNodeHook(vnodeHook, instance.parent, vnode);
69+
}
70+
instance.isDeactivated = true;
71+
}, parentSuspense);
72+
};
73+
74+
function unmount(vnode) {
75+
// reset the shapeFlag so it can be properly unmounted
76+
resetShapeFlag(vnode);
77+
_unmount(vnode, instance, parentSuspense, true);
78+
}
79+
80+
// cache sub tree after render
81+
let pendingCacheKey = null;
82+
const cacheSubtree = () => {
83+
// fix #1621, the pendingCacheKey could be 0
84+
if (pendingCacheKey != null) {
85+
cache.set(pendingCacheKey, getInnerChild(instance.subTree));
86+
}
87+
};
88+
onMounted(cacheSubtree);
89+
onUpdated(cacheSubtree);
90+
91+
onBeforeUnmount(() => {
92+
cache.forEach(cached => {
93+
const { subTree, suspense } = instance;
94+
const vnode = getInnerChild(subTree);
95+
if (cached.type === vnode.type && cached.key === vnode.key) {
96+
// current instance will be unmounted as part of keep-alive's unmount
97+
resetShapeFlag(vnode);
98+
// but invoke its deactivated hook here
99+
const da = vnode.component.da;
100+
da && queuePostRenderEffect(da, suspense);
101+
return;
102+
}
103+
unmount(cached);
104+
});
105+
});
106+
107+
return () => {
108+
pendingCacheKey = null;
109+
110+
if (!slots.default) {
111+
return null;
112+
}
113+
114+
const children = slots.default();
115+
const rawVNode = children[0];
116+
if (children.length > 1) {
117+
return children;
118+
} else if (!isVNode(rawVNode) || (!(rawVNode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) && !(rawVNode.shapeFlag & ShapeFlags.SUSPENSE))) {
119+
return rawVNode;
120+
}
121+
122+
let vnode = getInnerChild(rawVNode);
123+
const comp = vnode.type;
124+
125+
const key = vnode.key == null ? comp : vnode.key;
126+
const cachedVNode = cache.get(key);
127+
128+
// clone vnode if it's reused because we are going to mutate it
129+
if (vnode.el) {
130+
vnode = cloneVNode(vnode);
131+
if (rawVNode.shapeFlag & ShapeFlags.SUSPENSE) {
132+
rawVNode.ssContent = vnode;
133+
}
134+
}
135+
// #1513 it's possible for the returned vnode to be cloned due to attr
136+
// fallthrough or scopeId, so the vnode here may not be the final vnode
137+
// that is mounted. Instead of caching it directly, we store the pending
138+
// key and cache `instance.subTree` (the normalized vnode) in
139+
// beforeMount/beforeUpdate hooks.
140+
pendingCacheKey = key;
141+
142+
if (cachedVNode) {
143+
// copy over mounted state
144+
vnode.el = cachedVNode.el;
145+
vnode.component = cachedVNode.component;
146+
if (vnode.transition) {
147+
// recursively update transition hooks on subTree
148+
setTransitionHooks(vnode, vnode.transition);
149+
}
150+
// avoid vnode being mounted as fresh
151+
vnode.shapeFlag |= ShapeFlags.COMPONENT_KEPT_ALIVE;
152+
// make this key the freshest
153+
keys.delete(key);
154+
keys.add(key);
155+
} else {
156+
keys.add(key);
157+
}
158+
// avoid vnode being unmounted
159+
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE;
160+
161+
return isSuspense(rawVNode.type) ? rawVNode : vnode;
162+
};
163+
}
164+
});
165+
};
166+
167+
function resetShapeFlag(vnode) {
168+
// bitwise operations to remove keep alive flags
169+
vnode.shapeFlag &= ~ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE;
170+
vnode.shapeFlag &= ~ShapeFlags.COMPONENT_KEPT_ALIVE;
171+
}
172+
173+
function getInnerChild(vnode) {
174+
return vnode.shapeFlag & ShapeFlags.SUSPENSE ? vnode.ssContent : vnode;
175+
}
176+
177+
export { VuePage };

0 commit comments

Comments
 (0)