最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue AST源碼解析第一篇

 更新時間:2017年07月19日 14:05:42   作者:QH-Jimmy  
這篇文章主要為大家詳細(xì)介紹了Vue AST源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

講完了數(shù)據(jù)劫持原理和一堆初始化,現(xiàn)在是DOM相關(guān)的代碼了。

上一節(jié)是從這個函數(shù)開始的:

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

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

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

// 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)
 };

現(xiàn)在進(jìn)入后面的$mount函數(shù)看看內(nèi)部結(jié)構(gòu):

// Line-9552
 var mount = Vue$3.prototype.$mount;
 Vue$3.prototype.$mount = function(el,hydrating) {
  // 將el格式化為DOM節(jié)點
  el = el && query(el);
  // 判斷是否掛載到body或者h(yuǎn)tml標(biāo)簽上
  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 轉(zhuǎn)換為渲染函數(shù)
  if (!options.render) {
   // ...非常多代碼
  }
  return mount.call(this, el, hydrating)
 };

代碼前半段首先將el轉(zhuǎn)換為DOM節(jié)點,并判斷是否掛載到body或者h(yuǎn)tml標(biāo)簽,看看簡單的query函數(shù):

 // Line-4583
 function query(el) {
  // 如果是字符串就調(diào)用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
  }
  // 不是字符串就默認(rèn)傳進(jìn)來的是DOM節(jié)點 
  else {
   return el
  }
 }

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

下面看接下來的代碼:

// Line-9552
 var mount = Vue$3.prototype.$mount;
 Vue$3.prototype.$mount = function(el,hydrating) {
  // ...el轉(zhuǎn)換為DOM節(jié)點
  // ...
  // 沒有render屬性 進(jìn)入代碼段
  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屬性,會直接進(jìn)入第二個判斷條件,調(diào)用getOuterHTML來初始化template變量,函數(shù)比較簡單, 來看看:

// 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
  }
 }

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

下面看最后一段代碼:

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

    // 將DOM樹字符串編譯為函數(shù)
    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;

    // 編譯結(jié)束
    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件事,調(diào)用compileToFunctions函數(shù)肢解DOM樹字符串,將返回的對象屬性添加到options上,再次調(diào)用mount函數(shù)。

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

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

// Line-9326
 function compileToFunctions(template,options,vm) {
  // 獲取配置參數(shù)
  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)
 }

可以看到,這個函數(shù)流程可以分為4步,獲取參數(shù) => 調(diào)用compile函數(shù)進(jìn)行編譯 => 將得到的compiled轉(zhuǎn)換為函數(shù) => 返回并緩存。

 第一節(jié)現(xiàn)在這樣吧。一張圖總結(jié)下:

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue實現(xiàn)頁面加載動畫效果

    vue實現(xiàn)頁面加載動畫效果

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)頁面加載動畫效果,vue頁面出現(xiàn)正在加載的初始頁面與實現(xiàn)動畫效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • 基于vue實現(xiàn)分頁組件的示例代碼

    基于vue實現(xiàn)分頁組件的示例代碼

    分頁組件是一種用戶界面元素,用于在長列表或數(shù)據(jù)集中分割內(nèi)容,分頁組件是每個開發(fā)人員必須掌握的一個組件,廣泛應(yīng)用在各個場所,用以用戶方便閱讀等,本文就給大家介紹一下如何基于vue寫出的分頁組件,需要的朋友可以參考下
    2023-08-08
  • TypeScript在vue中的使用解讀

    TypeScript在vue中的使用解讀

    這篇文章主要介紹了TypeScript在vue中的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • vue深拷貝的3種實現(xiàn)方式小結(jié)

    vue深拷貝的3種實現(xiàn)方式小結(jié)

    當(dāng)使用同一個對象產(chǎn)生沖突時,可以使用lodash包,對該對象進(jìn)行深拷貝,從而使操作的對象為不同的對象,這篇文章主要給大家介紹了關(guān)于vue深拷貝的3種實現(xiàn)方式,需要的朋友可以參考下
    2023-02-02
  • 基于vue 添加axios組件,解決post傳參數(shù)為null的問題

    基于vue 添加axios組件,解決post傳參數(shù)為null的問題

    下面小編就為大家分享一篇基于vue 添加axios組件,解決post傳參數(shù)為null的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue.js中created()與activated()的個人使用解讀

    vue.js中created()與activated()的個人使用解讀

    這篇文章主要介紹了vue.js中created()與activated()的個人使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 前端vue中實現(xiàn)嵌入代碼編輯器的詳細(xì)代碼

    前端vue中實現(xiàn)嵌入代碼編輯器的詳細(xì)代碼

    隨著Web技術(shù)的不斷發(fā)展,前端開發(fā)也正日新月異,下面這篇文章主要給大家介紹了關(guān)于前端vue中實現(xiàn)嵌入代碼編輯器的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • 解決vue前后端端口不一致的問題

    解決vue前后端端口不一致的問題

    這篇文章主要介紹了解決vue前后端端口不一致的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • vue 解決data中定義圖片相對路徑頁面不顯示的問題

    vue 解決data中定義圖片相對路徑頁面不顯示的問題

    這篇文章主要介紹了vue 解決data中定義圖片相對路徑頁面不顯示的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Vue使用vue-recoure + http-proxy-middleware + vuex配合promise實現(xiàn)基本的跨域請求封裝

    Vue使用vue-recoure + http-proxy-middleware + vuex配合promise實現(xiàn)基本

    這篇文章主要介紹了Vue使用vue-recoure + http-proxy-middleware + vuex配合promise實現(xiàn)基本的跨域請求封裝問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-10-10

最新評論

杭锦后旗| 平乐县| 江阴市| 雅安市| 宁武县| 乌兰浩特市| 昌乐县| 阜阳市| 得荣县| 凤凰县| 恩平市| 利川市| 乐平市| 乌拉特前旗| 乌拉特中旗| 龙江县| 渭源县| 山阳县| 乌兰县| 吴忠市| 保靖县| 河津市| 阿克陶县| 屯门区| 衡东县| 朝阳市| 富川| 万山特区| 北碚区| 伊川县| 微博| 县级市| 宁乡县| 隆德县| 甘南县| 什邡市| 民丰县| 台东县| 北票市| 临猗县| 嵊州市|