5 Vue原始碼之AST(1)

2022-02-09 08:09:13 字數 3576 閱讀 7166

//

line-3924

vue.prototype._init = function

(options)

};

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

(時隔多日,我終於看懂了,這裡首先定義了原型方法$mount,然後將其賦給了乙個變數mount,然後重新定義此方法,所以呼叫mount.call會呼叫第一次定義的$mount,vue原型上最終只有第二次定義的$mount) => 多此一舉! 2017.7.31

//

line-7531

//public mount method

vue$3.prototype.$mount = function

(el,hydrating) ;

//line-9552

var mount = vue$3.prototype.$mount;

vue$3.prototype.$mount = function

( el,

hydrating

) ;

現在進入後面的$mount函式看看內部結構:

//

line-9552

var mount = vue$3.prototype.$mount;

vue$3.prototype.$mount = function

(el,hydrating)

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)

return

selected

}//不是字串就預設傳進來的是dom節點

else

}

函式比較簡單,值得注意的乙個點是,由於呼叫的是queryselector方法,所以可以傳標簽名、類名、c3新選擇器等,都會返回查詢到的第乙個。當然,總是傳乙個id或者確定的dom節點才是正確用法。

下面看接下來的**:

//

line-9552

var mount = vue$3.prototype.$mount;

vue$3.prototype.$mount = function

(el,hydrating) }}

else

if(template.nodetype)

else

return

this

} }

//有el 獲取字串化的dom樹

else

if(el)

if(template)

}return mount.call(this

, el, hydrating)

};

由於沒有template屬性,會直接進入第二個判斷條件,呼叫getouterhtml來初始化template變數,函式比較簡單, 來看看:

//

line-9623

function

getouterhtml(el)

//相容ie中的svg

else

}

簡單來講,就是呼叫outerhtml返回dom樹的字串形式,看圖就明白了:

下面看最後一段**:

//

line-9552

var mount = vue$3.prototype.$mount;

vue$3.prototype.$mount = function

(el,hydrating)

//將dom樹字串編譯為函式

var ref =compiletofunctions(template, ,

this

);

//options新增屬性

var render =ref.render;

var staticrenderfns =ref.staticrenderfns;

options.render =render;

options.staticrenderfns =staticrenderfns;

//編譯結束

if ("development" !== 'production' && config.performance &&mark) }}

return mount.call(this

, el, hydrating)

};

忽略2段dev模式下的提示**,剩下的**做了3件事,呼叫compiletofunctions函式肢解dom樹字串,將返回的物件屬性新增到options上,再次呼叫mount函式。

首先看一下compiletofunctions函式,該函式接受3個引數,分別為字串、配置物件、當前vue例項。

由於函式比較長,而且部分是錯誤判斷,簡化後如下:

//

line-9326

function

compiletofunctions(template,options,vm) ;

//...

var key = options.delimiters ?string(options.delimiters) +template :

template;

//檢測快取

if(functioncompilecache[key])

//1var 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++)

//...//3

return (functioncompilecache[key] =res)

}

可以看到,這個函式流程可以分為4步,獲取引數 => 呼叫compile函式進行編譯 => 將得到的compiled轉換為函式 => 返回並快取。

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

Vue之Watcher原始碼解析(1)

上一節最後再次呼叫了mount函式,我發現竟然跳到了7000多行的那個函式,之前我還說因為宣告早了被覆蓋,看來我錯了!就是這個函式 line 7531 vue 3.prototype.mount function el,hydrating 第一步query就不用看了,el此時是乙個dom節點,所以直...

vue原始碼分析1

在vue的原始碼中使用的是es5的方法 prototype.slice.bind obj 來實現的 例如 已 為例 obj 定義屬性的物件 prop 定義或修改屬性的名稱 descriptor 將被定義或修改的屬性描述符 value 預設值 configurable 是否可以重新定義 enumera...

Vue 原始碼閱讀1之開篇感悟

隨著網際網路的大風越刮越大,前端的發展也是十分的迅猛,出現了各種各樣的前端框架,vue是其中的佼佼者,這一系列的文章我將以初學者的身份分析vue的相關實現,希望能夠和大家一起進步,早日實現高薪。我個人感覺要要學習vue的原始碼,vue的生命週期是離不開的話題,每個人都知道vue的生命週期為befor...