Closed liuweiGL closed 3 years ago
作者有打算合并吗?
我给你新开一个分支吧?
可以开个 next 分支
👌🏻
@liuweiGL OK了
很多方法 vue 没暴露出来,还在琢磨。
vue-router-next 会处理 window.history.state 可以从里面拿到 position,记录这个 position ,通过判断position 和 replace 可以知道 前进还是后退或者 替换,可以类似于 客户端 navgation 一样的,前进不缓存,后退读取缓存的方式,来管理。
@liuweiGL 是的,只能自己去看一些官方的方法,去理解了,好在现在版本基本稳定了,应该不会有大变动了,早前beta的时候,histroy state 里面有个参数直接告诉你 是 前进,后退还是替换,现在被去掉了
@0x30 如果可以去掉,URI上的key,那就最好了,不过还是很难
import {
callWithAsyncErrorHandling,
ComponentInternalInstance,
defineComponent,
getCurrentInstance,
onBeforeUnmount,
PropType,
queuePostFlushCb,
RendererElement,
RendererNode,
SuspenseBoundary,
VNode,
} from "vue";
import { isArray, invokeArrayFns } from "@vue/shared";
let position: number | undefined = undefined;
type ComponentContext = {
renderer: any;
activate: (
vnode: VNode,
container: RendererElement,
anchor: RendererNode | null,
isSVG: boolean,
optimized: boolean
) => void;
deactivate: (vnode: VNode) => void;
};
export function queueEffectWithSuspense(
fn: Function | Function[],
suspense: SuspenseBoundary | null
): void {
if (suspense && suspense.pendingBranch) {
if (isArray(fn)) {
suspense.effects.push(...fn);
} else {
suspense.effects.push(fn);
}
} else {
queuePostFlushCb(fn);
}
}
export function invokeVNodeHook(
hook: any,
instance: ComponentInternalInstance | null,
vnode: VNode,
prevVNode: VNode | null = null
) {
callWithAsyncErrorHandling(hook, instance, 7, [vnode, prevVNode]);
}
function resetShapeFlag(vnode: VNode) {
let shapeFlag = vnode.shapeFlag;
if (shapeFlag & 256) {
shapeFlag -= 256;
}
if (shapeFlag & 512) {
shapeFlag -= 512;
}
vnode.shapeFlag = shapeFlag;
}
function getInnerChild(vnode: VNode) {
return vnode.shapeFlag & 128 ? vnode.ssContent! : vnode;
}
export const Navigation = defineComponent({
inheritRef: true,
__isKeepAlive: true,
props: {
Component: {
type: Object as PropType<VNode>,
default: undefined,
},
},
setup: (props) => {
const stacks: VNode[] = [];
const instance = getCurrentInstance() as any;
const sharedContext = instance.ctx as ComponentContext;
const parentSuspense = instance.suspense;
const {
renderer: {
p: patch,
m: move,
um: _unmount,
o: { createElement },
},
} = sharedContext;
const storageContainer = createElement("div");
sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
const instance = vnode.component as ComponentInternalInstance;
move(vnode, container, anchor, 0, parentSuspense);
// in case props have changed
patch(
instance.vnode,
vnode,
container,
anchor,
instance,
parentSuspense,
isSVG,
optimized
);
queueEffectWithSuspense(() => {
instance.isDeactivated = false;
if ((instance as any).a) {
invokeArrayFns((instance as any).a);
}
const vnodeHook = vnode.props && vnode.props.onVnodeMounted;
if (vnodeHook) {
invokeVNodeHook(vnodeHook, instance.parent, vnode);
}
}, parentSuspense);
};
sharedContext.deactivate = (vnode: VNode) => {
const instance = vnode.component! as any;
move(vnode, storageContainer, null, 1, parentSuspense);
queueEffectWithSuspense(() => {
if ((instance as any).da) {
invokeArrayFns((instance as any).da);
}
const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted;
if (vnodeHook) {
invokeVNodeHook(vnodeHook, instance.parent, vnode);
}
instance.isDeactivated = true;
}, parentSuspense);
};
function unmount(vnode: VNode) {
// reset the shapeFlag so it can be properly unmounted
resetShapeFlag(vnode);
_unmount(vnode, instance, parentSuspense);
}
onBeforeUnmount(() => {
stacks.forEach((cached) => {
const { subTree, suspense } = instance;
const vnode = getInnerChild(subTree);
if (cached.type === vnode.type) {
// current instance will be unmounted as part of keep-alive's unmount
resetShapeFlag(vnode);
// but invoke its deactivated hook here
const da = (vnode.component as any).da;
da && queueEffectWithSuspense(da, suspense);
return;
}
unmount(cached);
});
});
return () => {
const { Component } = props;
if (Component === undefined) return null;
let component = Component;
if (position === undefined) {
console.log("初始化", component.type);
stacks.push(component);
} else if (position < window.history.state.position) {
console.log("前进", component.type);
component.shapeFlag |= 256;
stacks.push(component);
} else if (position > window.history.state.position) {
console.log("后退", component.type);
const comp = stacks.pop();
comp && unmount(comp);
component = stacks[stacks.length - 1] ?? component;
component.shapeFlag |= 512;
} else if (position == window.history.state.position) {
console.log("替换", component.type);
const comp = stacks.pop();
comp && unmount(comp);
stacks.push(component);
}
position = window.history.state.position;
return stacks[stacks.length - 1];
};
},
});
刚才写了一下,没测试,不过效果来看 是可以实现的 就是刚才我说的 前进缓存 后退销毁,没有 key
核心就是如何区分前进和后退,这个可以解决掉就真的棒,最近太忙了~
标记下,看看position是否可以尝试去除URI上的Key
82