Vue 소스 (5) -$mount에서template의 컴파일 -optimize

위의 글은 Vue 원본 코드 (4) -$mount에서template의 컴파일 -parse를 간단히 분석했습니다. 우리는compile의parse 부분을 소개했습니다. 이로써 우리는 html 문자열 템플릿을 하나의AST 문법 트리로 해석하는 과정을 완성했습니다.다음 단계는optimize 방법을 통해AST 노드를 정적 노드로 표시해야 한다.이후 patch 프로세스 중 신구 VNode 트리 구조를 최적화하는 데 사용됩니다.static로 표시된 노드는 뒤에 있는 diff 알고리즘에서 무시되고 상세한 비교를 하지 않습니다.
src/compiler/optimizer.js
export function optimize (root: ?ASTElement, options: CompilerOptions) {
  if (!root) return
  // staticKeys              ast   
  isStaticKey = genStaticKeysCached(options.staticKeys || '')
  isPlatformReservedTag = options.isReservedTag || no
  // first pass: mark all non-static nodes.
  //        AST       
  markStatic(root)
  // second pass: mark static roots.
  //        AST      (      )
  markStaticRoots(root, false)
}
모든 정적 노드를 먼저 표시합니다.
function isStatic (node: ASTNode): boolean {
  if (node.type === 2) { //    
    return false
  }
  if (node.type === 3) { //     
    return true
  }
  //       
  return !!(node.pre || ( // v-pre   
    !node.hasBindings && // no dynamic bindings
    !node.if && !node.for && // not v-if or v-for or v-else
    !isBuiltInTag(node.tag) && // not a built-in
    isPlatformReservedTag(node.tag) && // not a component
    !isDirectChildOfTemplateFor(node) &&
    Object.keys(node).every(isStaticKey)
  ))
}
ASTNode의 type 필드는 노드의 유형을 식별하는 데 사용되며 이전 AST 노드 정의를 볼 수 있습니다.
type은 1로 원소를 표시하고,
type은 2로 보간 표현식을 나타냅니다.
type은 3으로 일반 텍스트를 나타냅니다.
ASTElement을 표시할 때 모든 하위 요소 노드의 정적 표시를 순서대로 검사하여 이 요소가 static인지 여부를 알 수 있습니다.위의markStatic 함수는 트리 데이터 구조의 깊이 우선 스트리밍 알고리즘을 사용하고 귀속 실현을 사용한다.그런 다음 정적 트리를 계속 표시합니다.
function markStaticRoots (node: ASTNode, isInFor: boolean) {
  if (node.type === 1) {
   //      v-for      。        renderStatic(_m)         key,  patch error
    if (node.static || node.once) {
      node.staticInFor = isInFor
    }
    // For a node to qualify as a static root, it should have children that
    // are not just static text. Otherwise the cost of hoisting out will
    // outweigh the benefits and it's better off to just always render it fresh.
    //              ,               。  ,                       。
    if (node.static && node.children.length && !(
      node.children.length === 1 &&
      node.children[0].type === 3
    )) {
      node.staticRoot = true
      return
    } else {
      node.staticRoot = false
    }
    if (node.children) {
      for (let i = 0, l = node.children.length; i < l; i++) {
        markStaticRoots(node.children[i], isInFor || !!node.for)
      }
    }
    if (node.ifConditions) {
      for (let i = 1, l = node.ifConditions.length; i < l; i++) {
        markStaticRoots(node.ifConditions[i].block, isInFor)
      }
    }
  }
}
markStaticRoots 함수에는 특별한 점이 없고 정적 노드에 대한 선별만 한 층 더 했다.
총결산
optimizer는 구문 트리의 노드에 static 및 staticRoot 속성을 표시하도록 설계되었습니다.첫 번째 라운드를 반복하여 static 속성을 표시합니다.
node가 static인지 아닌지 판단하기 (여러 조건이 있음) node를 표시하는 children이 static인지 여부
static 또는 노드가 staticRoot이고 이 노드 type===1(일반적으로 tag 속성이 있는 노드) v-once 명령이 있는 노드도 staticRoot로 표시되며 과도한 최적화를 피하기 위해 static text가 하위 노드인 노드만 staticRoot 표시 노드children의 staticRoot로 표시되지 않습니다
마음에 들면 스타,github 하나 주세요.
무우 씨가 주신 아이디어 감사합니다.

좋은 웹페이지 즐겨찾기