日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue源码学习--vue源码学习入门

發布時間:2023/12/18 vue 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue源码学习--vue源码学习入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文為開始學習vue源碼的思路整理。在拿到vue項目源碼的之后看到那些項目中的文件夾,會很困惑,不知道每個文件夾內的世界,怎么變換,怎樣的魔力,最后產生了vue框架。學習源碼也無從學起。我解決了這些困惑之后,形成了這篇文章----vue源碼學習入門。文章會根據我自己的學習思路,理清vue項目的大體框架。文章先介紹vue項目中各個文件夾中內包含的功能,然后是從package.json文件開始我們的尋找vue構造函數之旅,最后再從vue構造函數返回入口,看看旅程中的各個節點都為vue加了什么“戲”。

一、Vue項目結構

在GitHub中下載vue項目的源碼后解壓我們會得到如下的目錄。

每個文件夾是做什么的,在項目中的CONTRIBUTING有介紹。我翻譯了一下,形成了以下腦圖:

?

我們源碼學習,學習的是vue框架內容的源碼,而項目中包含的許多構建vuejs的配置文件和輔助vue代碼編寫的功能模塊是我們幾乎接觸不到的。

我們需要著重注意的是,包含vue源碼的【src】文件夾。我把src的內容單獨整理,形成了又一腦圖,如下:

?

現在我們大致知道vue項目的各個文件夾的用處了。而且,對于我們需要著重關注的源碼src也大致掌握了每個文件夾負責的功能模塊。接下來,我們就要開始啃食vue源碼了。做一只饑渴的寄生蟲吧~

?

二、尋找構造函數之旅

要了解一個前端項目,一般情況下我們都可以從查看項目的package.json文件開始。從package.json我們可以知道項目有哪些依賴包,定義了哪些腳本字段。其實在CONTRIBUTING中還提到了常用的npm命令。以下是我的截圖:

?

其中提及可以用npm run dev來達到監控和自動重建dist目錄下的vue.js文件以及還有一些npm命令在package.json的script中,大家可以按需執行。

那我們找到vue項目中的package.json,看看npm run dev執行了什么命令

rollup指的是一個專注于es6模塊構建的工具,會對其構建的代碼進行tree-shaking,是tree-shaking的提出者。它與webpack的區別是rollup沒做uplify,其構建后的代碼盡量保持源代碼的樣子。

rollup -c指定配置文件為build/config.js,最后將TARGET的值設置成web-full-dev。

打開build文件夾下的config.js。簡化后代碼如下:

const builds = {...// Runtime+compiler development build (Browser)'web-full-dev': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.js'),format: 'umd',env: 'development',alias: { he: './entity-decoder' },banner}... }function genConfig (name) {const opts = builds[name]const config = {input: opts.entry,external: opts.external,plugins: [replace({__WEEX__: !!opts.weex,__WEEX_VERSION__: weexVersion,__VERSION__: version}),flow(),buble(),alias(Object.assign({}, aliases, opts.alias))].concat(opts.plugins || []),output: {file: opts.dest,format: opts.format,banner: opts.banner,name: opts.moduleName || 'Vue'}}if (opts.env) {config.plugins.push(replace({'process.env.NODE_ENV': JSON.stringify(opts.env)}))}Object.defineProperty(config, '_name', {enumerable: false,value: name})return config }if (process.env.TARGET) {module.exports = genConfig(process.env.TARGET) } else {exports.getBuild = genConfigexports.getAllBuilds = () => Object.keys(builds).map(genConfig) }

?

我們可以看出,該js中包含著一個builds常量對象,對象的屬性名為之前package.json中npm對應命里里設置的TAGET值。js的最后根據是否有TAGET值返回不同的值。我們npm run dev的命令對應的是:

module.exports = genConfig({entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.js'),format: 'umd',env: 'development',alias: { he: './entity-decoder' },banner});

并最終返回一個config對象,也就是執行rollup的配置對象。

從builds對象中可以知道,vue的入口文件為:web/entry-runtime-with-compiler.js。在項目結構的介紹中,我們也提及了dist、build的入口文件在platform中。在經過resolve函數之后,路徑就是:\vue-dev\src\platforms\web\entry-runtime-with-compiler.js。

?

打開這個文件,在import中看到了Vue又來自./runtime/index即\vue-dev\src\platforms\web\runtime\index.js。按照這個Vue是來自于import的套路我們接著又找到了core/index.js、instance/index.js。撥開層層迷霧,終識廬山真面目,最終找到了最終的vue構造函數,如下:(\vue-dev\src\core\instance\index.js)

1 function Vue (options) { 2 if (process.env.NODE_ENV !== 'production' && 3 !(this instanceof Vue) 4 ) { 5 warn('Vue is a constructor and should be called with the `new` keyword') 6 } 7 this._init(options) 8 }

所以尋找Vue構造函數之旅如下圖:

?

三、回首來路,旅程給Vue加了哪些戲

  如果直接從Vue實例化開始閱讀源碼(一般思路)在閱讀的過程中常常會遇見一些沒有見過的屬性和方法。心中就會產生疑惑,這些屬性的值是啥,在哪賦值定義的。為了解決這個疑問,本節通過“回顧旅程”,其實也是vuejs執行順序,來看看程序對Vue構造函數都加了哪些“戲”。

  Vue(options)作為函數本質上也是一個對象。作為構造函數其原型對象將會對實例產生影響。所以整理出了vuejs執行時掛載在函數上和函數原型上的屬性方法有哪些。

vue的構造函數的文件在\vue-dev\src\core\instance\index.js,源碼如下:

function Vue (options) {if (process.env.NODE_ENV !== 'production' &&!(this instanceof Vue)) {warn('Vue is a constructor and should be called with the `new` keyword')}this._init(options) }initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue)export default Vue

?

vue構造函數先是做一個安全模式的處理,告訴使用者必須通過new字符串調用Vue方法,然后用了一個_init(options)方法。可以推斷出_init方法是在Vue原型對象上的方法。

構造函數之外還執行了許多從幾個依賴中引入的函數,并將構造函數作為參數傳入方法。整理過后再instance/index.js中對Vue以及Vue原型的改變如下:

?

往上一層core/index.js中,這個js導入了已經在原型上掛載了方法合屬性后的Vue,然后導入initGlobalAPI為Vue導入許多全局API(我們在閱讀vue官方文檔中API分為全局配置、全局API以及實例屬性等全局API正是這時導入的)。initGlobalAPI中最后調用依賴引入的initUse、initMixin、initExtend、initAssetRegisters等方法

然后和在Vue原型對象上定義$isServer、$ssrContext兩個訪問器屬性和為Vue添加version屬性。具體添加見下圖:

?

?

再往回看,我們回到runtime/index.js。這個js顯示為Vue下的config屬性添加屬性和賦值,再是將平臺相關的directives和components擴展給Vue.options下的directives和components中也就是安裝平臺特有的指令和組件。

然后為判斷是否在瀏覽器中,如果是就為Vue原型對象安裝平臺patch功能。接著定義公共的$mount方法。

Vue.prototype.$mount = function (el?: string | Element,hydrating?: boolean ): Component {el = el && inBrowser ? query(el) : undefinedreturn mountComponent(this, el, hydrating) }

$mount方法先是根據是否在瀏覽器決定是否query(el),最后都將參數傳給core/instance/lifecycle.js中的mountComponent方法,該方法負責掛載更新組件。

具體添加如下:

?

最后是runtime/entry-runtime-with-compiler.js,這個文件首先是緩存原型對象中存在的$mount方法,然后用一個可以將template/el轉化為render函數的方法覆蓋原型對象的$mount方法。然后定義了Vue.compile屬性為compileToFunctions 函數。這個函數的作用就是將模板 template 編譯為render函數。如下圖所示:

匯總一下:

第一步:instance/index.js 為Vue.prototype定義實例屬性、實例方法/數據、實例方法/事件以及生命周期等實例相關的屬性方法。

第二步:core/index.js? 主要是通過initGlobalAPI掛載平臺相關的全局API 和Vue需要用到的工具函數

第三部:runtime/index.js? ?是添加平臺相關的指令、組件和配置參數和$mount方法

第四部? ? runtime/entry-runtime-with-compiler.js 給Vue添加了可以支持template的$mount方法和compiler編譯器。

回首之旅結束,希望你得到你想得到的。

如此一路走來,我想我們應該是知道vue源碼學習的大致框架了。知道了去哪找對應功能模塊的代碼,以及vue對象上的屬性和vue原型對象上的屬性有粗略的了解。如果遇見也知道要去哪認識他們,而不是帶著苦惱前行了。

希望能幫到你~

?注:本文章中學習的源碼版本為vue? 2.5.2. 文章中涉及的觀點和理解均是個人的理解,如有偏頗或是錯誤還請大神指出,不吝賜教,萬分感謝~

轉載于:https://www.cnblogs.com/mlFronter/p/7730042.html

總結

以上是生活随笔為你收集整理的vue源码学习--vue源码学习入门的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。