中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue中AST源碼解析的示例分析

發布時間:2021-09-06 10:01:56 來源:億速云 閱讀:160 作者:小新 欄目:web開發

這篇文章主要介紹Vue中AST源碼解析的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

從這個函數開始的:

// Line-3924
 Vue.prototype._init = function(options) {
  // 大量初始化
  // ...
  // Go!
  if (vm.$options.el) {
   vm.$mount(vm.$options.el);
  }
 };

弄完data屬性的數據綁定后,開始處理el屬性,也就是掛載的DOM節點,這里的vm.$options.el也就是傳進去的'#app'字符串。

有一個值得注意的點是,源碼中有2個$mount函數都是Vue$3的原型函數,其中一個標記了注釋public mount method,在7531行,另外一個在9553行。打斷點進入的是后面,因為定義的晚,覆蓋了前面的函數。

// Line-7531
 // public mount method
 Vue$3.prototype.$mount = function(el,hydrating) {
  el = el && inBrowser ? query(el) : undefined;
  return mountComponent(this, el, hydrating)
 };

 // Line-9552
 var mount = Vue$3.prototype.$mount;
 Vue$3.prototype.$mount = function(
  el,
  hydrating
 ) {
  // ...很多代碼
  return mount.call(this, el, hydrating)
 };

現在進入后面的$mount函數看看內部結構:

// Line-9552
 var mount = Vue$3.prototype.$mount;
 Vue$3.prototype.$mount = function(el,hydrating) {
  // 將el格式化為DOM節點
  el = el && query(el);
  // 判斷是否掛載到body或者html標簽上
  if (el === document.body || el === document.documentElement) {
   "development" !== 'production' && warn(
    "Do not mount Vue to <html> or <body> - mount to normal elements instead."
   );
   return this
  }

  var options = this.$options;
  // 處理template/el 轉換為渲染函數
  if (!options.render) {
   // ...非常多代碼
  }
  return mount.call(this, el, hydrating)
 };

代碼前半段首先將el轉換為DOM節點,并判斷是否掛載到body或者html標簽,看看簡單的query函數:

 // Line-4583
 function query(el) {
  // 如果是字符串就調用querySelector
  if (typeof el === 'string') {
   var selected = document.querySelector(el);
   if (!selected) {
    "development" !== 'production' && warn(
     'Cannot find element: ' + el
    );
    // 找不到就返回一個div
    return document.createElement('div')
   }
   return selected
  }
  // 不是字符串就默認傳進來的是DOM節點 
  else {
   return el
  }
 }

函數比較簡單,值得注意的幾個點是,由于調用的是querySelector方法,所以可以傳標簽名、類名、C3新選擇器等,都會返回查詢到的第一個。當然,總是傳一個ID或者確定的DOM節點才是正確用法。

下面看接下來的代碼:

// Line-9552
 var mount = Vue$3.prototype.$mount;
 Vue$3.prototype.$mount = function(el,hydrating) {
  // ...el轉換為DOM節點
  // ...
  // 沒有render屬性 進入代碼段
  if (!options.render) {
   var template = options.template;
   // 沒有template 跳
   if (template) {
    if (typeof template === 'string') {
     if (template.charAt(0) === '#') {
      template = idToTemplate(template);
      /* istanbul ignore if */
      if ("development" !== 'production' && !template) {
       warn(
        ("Template element not found or is empty: " + (options.template)),
        this
       );
      }
     }
    } else if (template.nodeType) {
     template = template.innerHTML;
    } else {
     {
      warn('invalid template option:' + template, this);
     }
     return this
    }
   }
   // 有el 獲取字符串化的DOM樹
   else if (el) {
    template = getOuterHTML(el);
   }
   if (template) {
    // ...小段代碼
   }
  }
  return mount.call(this, el, hydrating)
 };

由于沒有template屬性,會直接進入第二個判斷條件,調用getOuterHTML來初始化template變量,函數比較簡單, 來看看:

// Line-9623
 function getOuterHTML(el) {
  if (el.outerHTML) {
   return el.outerHTML
  }
  // 兼容IE中的SVG
  else {
   var container = document.createElement('div');
   container.appendChild(el.cloneNode(true));
   return container.innerHTML
  }
 }

簡單來講,就是調用outerHTML返回DOM樹的字符串形式,看圖就明白了:

Vue中AST源碼解析的示例分析

下面看最后一段代碼:

 // Line-9552
 var mount = Vue$3.prototype.$mount;
 Vue$3.prototype.$mount = function(el,hydrating) {
  // ...el轉換為DOM節點
  // ...
  // 沒有render屬性 進入代碼段
  if (!options.render) {
   // ...處理template
   // ...
   if (template) {
    // 編譯開始
    if ("development" !== 'production' && config.performance && mark) {
     mark('compile');
    }

    // 將DOM樹字符串編譯為函數
    var ref = compileToFunctions(template, {
     shouldDecodeNewlines: shouldDecodeNewlines,
     delimiters: options.delimiters
    }, this);
    // options添加屬性
    var render = ref.render;
    var staticRenderFns = ref.staticRenderFns;
    options.render = render;
    options.staticRenderFns = staticRenderFns;

    // 編譯結束
    if ("development" !== 'production' && config.performance && mark) {
     mark('compile end');
     measure(((this._name) + " compile"), 'compile', 'compile end');
    }
   }
  }
  return mount.call(this, el, hydrating)
 };

忽略2段dev模式下的提示代碼,剩下的代碼做了3件事,調用compileToFunctions函數肢解DOM樹字符串,將返回的對象屬性添加到options上,再次調用mount函數。

首先看一下compileToFunctions函數,該函數接受3個參數,分別為字符串、配置對象、當前vue實例。

由于函數比較長,而且部分是錯誤判斷,簡化后如下:

// Line-9326
 function compileToFunctions(template,options,vm) {
  // 獲取配置參數
  options = options || {};

  // ...

  var key = options.delimiters ?
   String(options.delimiters) + template :
   template;
  // 檢測緩存
  if (functionCompileCache[key]) {
   return functionCompileCache[key]
  }

  // 1
  var compiled = compile(template, options);

  // ...

  // 2
  var res = {};
  var fnGenErrors = [];
  res.render = makeFunction(compiled.render, fnGenErrors);
  var l = compiled.staticRenderFns.length;
  res.staticRenderFns = new Array(l);
  for (var i = 0; i < l; i++) {
   res.staticRenderFns[i] = makeFunction(compiled.staticRenderFns[i], fnGenErrors);
  }

  // ...

  // 3
  return (functionCompileCache[key] = res)
 }

可以看到,這個函數流程可以分為4步,獲取參數 => 調用compile函數進行編譯 => 將得到的compiled轉換為函數 => 返回并緩存。

 第一節現在這樣吧。一張圖總結下:

Vue中AST源碼解析的示例分析

以上是“Vue中AST源碼解析的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

防城港市| 玉田县| 巫溪县| 庄河市| 高邑县| 鲜城| 盈江县| 新宁县| 建德市| 阿拉善右旗| 泗阳县| 特克斯县| 平武县| 黎川县| 布拖县| 曲阜市| 东丰县| 龙南县| 冕宁县| 策勒县| 乌拉特前旗| 武冈市| 龙里县| 得荣县| 治多县| 临城县| 嘉义县| 延庆县| 吴桥县| 广河县| 祁连县| 柳州市| 韶山市| 双城市| 兴文县| 兖州市| 珲春市| 紫云| 柳江县| 潜山县| 西乌|