mirror of https://github.com/vuejs/core.git
perf: cache static children on parent
This commit is contained in:
parent
41509dcc61
commit
479ea96e59
|
@ -20,8 +20,8 @@ describe('api: template', () => {
|
|||
|
||||
test('nthChild', () => {
|
||||
const t = template('<div><span><b>nested</b></span><p></p></div>')
|
||||
const root = t()
|
||||
const span = nthChild(root, 0)
|
||||
const root = t() as ParentNode
|
||||
const span = nthChild(root, 0) as ParentNode
|
||||
const b = nthChild(span, 0)
|
||||
const p = nthChild(root, 1)
|
||||
expect(span).toBe(root.firstChild)
|
||||
|
@ -31,7 +31,7 @@ describe('api: template', () => {
|
|||
|
||||
test('next', () => {
|
||||
const t = template('<div><span></span><b></b><p></p></div>')
|
||||
const root = t()
|
||||
const root = t() as ParentNode
|
||||
const span = child(root as ParentNode)
|
||||
const b = next(span)
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ function performHydration<T>(
|
|||
// optimize anchor cache lookup
|
||||
;(Comment.prototype as any).$fe = undefined
|
||||
;(Node.prototype as any).$idx = undefined
|
||||
;(Node.prototype as any).$children = undefined
|
||||
isOptimized = true
|
||||
}
|
||||
enableHydrationNodeLookup()
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import {
|
||||
type ChildItem,
|
||||
type InsertionParent,
|
||||
getHydrationState,
|
||||
getTemplateChildren,
|
||||
} from '../insertionState'
|
||||
|
||||
export function createElement(tagName: string): HTMLElement {
|
||||
|
@ -46,23 +46,23 @@ const __txt: typeof __child = (node: ParentNode): Node => {
|
|||
}
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function _child(node: ParentNode): Node {
|
||||
const templateChildren = getTemplateChildren(node)
|
||||
return templateChildren ? templateChildren[0] : node.firstChild!
|
||||
export function _child(node: InsertionParent): Node {
|
||||
const children = node.$children
|
||||
return children ? children[0] : node.firstChild!
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydration-specific version of `child`.
|
||||
*/
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function __child(node: ParentNode & { $lpn?: Node }): Node {
|
||||
export function __child(node: ParentNode): Node {
|
||||
return __nthChild(node, 0)!
|
||||
}
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function _nthChild(node: Node, i: number): Node {
|
||||
const templateChildren = getTemplateChildren(node as ParentNode)
|
||||
return templateChildren ? templateChildren[i] : node.childNodes[i]
|
||||
export function _nthChild(node: InsertionParent, i: number): Node {
|
||||
const children = node.$children
|
||||
return children ? children[i] : node.childNodes[i]
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,10 +92,8 @@ export function __nthChild(node: Node, i: number): Node {
|
|||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function _next(node: Node): Node {
|
||||
const templateChildren = getTemplateChildren(node.parentNode!)
|
||||
return templateChildren
|
||||
? templateChildren[(node as ChildItem).$idx + 1]
|
||||
: node.nextSibling!
|
||||
const children = (node.parentNode! as InsertionParent).$children
|
||||
return children ? children[(node as ChildItem).$idx + 1] : node.nextSibling!
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
import { isHydrating } from './dom/hydration'
|
||||
export interface ChildItem extends ChildNode {
|
||||
$idx: number
|
||||
}
|
||||
export type ChildItem = ChildNode & { $idx: number }
|
||||
export type InsertionParent = ParentNode & { $children?: ChildItem[] }
|
||||
|
||||
type HydrationState = {
|
||||
logicalChildren: ChildItem[]
|
||||
prevDynamicCount: number
|
||||
insertionAnchors: Map<Node, number> | null
|
||||
appendAnchor: Node | null
|
||||
}
|
||||
export let insertionParent: ParentNode | undefined
|
||||
export let insertionParent: InsertionParent | undefined
|
||||
export let insertionAnchor: Node | 0 | undefined | null
|
||||
|
||||
const templateChildrenCache = new WeakMap<ParentNode, ChildItem[]>()
|
||||
|
||||
const hydrationStateCache = new WeakMap<ParentNode, HydrationState>()
|
||||
|
||||
/**
|
||||
|
@ -87,22 +85,22 @@ function initializeHydrationState(
|
|||
|
||||
function cacheTemplateChildren(
|
||||
anchor: number | Node | null | undefined,
|
||||
parent: ParentNode,
|
||||
parent: InsertionParent,
|
||||
) {
|
||||
// special handling append anchor value to null
|
||||
insertionAnchor =
|
||||
typeof anchor === 'number' && anchor > 0 ? null : (anchor as Node)
|
||||
|
||||
if (!templateChildrenCache.has(parent)) {
|
||||
if (!parent.$children) {
|
||||
const nodes = parent.childNodes
|
||||
const len = nodes.length
|
||||
const children = new Array(len)
|
||||
const children = new Array(len) as ChildItem[]
|
||||
for (let i = 0; i < len; i++) {
|
||||
const node = nodes[i] as ChildItem
|
||||
node.$idx = i
|
||||
children[i] = node
|
||||
}
|
||||
templateChildrenCache.set(parent, children)
|
||||
parent.$children = children
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,12 +108,6 @@ export function resetInsertionState(): void {
|
|||
insertionParent = insertionAnchor = undefined
|
||||
}
|
||||
|
||||
export function getTemplateChildren(
|
||||
parent: ParentNode,
|
||||
): ChildItem[] | undefined {
|
||||
return templateChildrenCache.get(parent)
|
||||
}
|
||||
|
||||
export function getHydrationState(
|
||||
parent: ParentNode,
|
||||
): HydrationState | undefined {
|
||||
|
|
Loading…
Reference in New Issue