.vue文件編譯成瀏覽器可執(zhí)行文件的流程詳解
vue2官網(wǎng) 其中”安裝”介紹了關(guān)于Vue的各種版本。
- 編譯器:用來將模板字符串編譯成為 JavaScript 渲染函數(shù)的代碼。
<div id="app"> <div>{{ a }}</div> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script> <script> const vm = new Vue({ el: '#app', data: { a: 'hello world', }, }) </script>
以上是一段簡單的Vue2代碼, 打開瀏覽器可以正確顯示出 “hello world”,- 可以發(fā)現(xiàn) <div>{{ a }}</div>
不是瀏覽器支持的語法. 所以實際上能顯示 hello world, 并不是由以上模板代碼直接在瀏覽器執(zhí)行的結(jié)果, 而是通過”編譯器”編譯, 再由瀏覽器執(zhí)行
- 接下來用代碼為大家演示Vue2是如何將上面代碼編譯的
- 首先必須引入”完整版”,
- 打開頁面, 在控制臺可以發(fā)現(xiàn)方法: Vue.compile
- 將剛才的 template 代碼放到編譯方法里執(zhí)行, 結(jié)果如下
- 可以看到 template 被編譯成 JavaScript,_c,_v,_s,是vue實例vm上一些方法的簡稱
- 編譯結(jié)果可以翻譯成
<script> const vm = new Vue({ el: '#app', name: 'App', data: () => ({ a: 'hello world!!!', }), render() { const {_c, _v, _s, a} = this //return createElement('div', [createTextNode(toString(a))]) return _c('div',[_v(_s(a))]) } }) </script>
這樣 模板template就被編譯為了 render函數(shù)
- 以上便是在 .html 文件中使用template 開發(fā), 由 Vue2完整版 進行編譯的過程
.vue文件是如何進行編譯的?
通常項目中是使用Webpack打包, 再由瀏覽器引入這些js, css等文件, 那么Webpack是如何對.vue文件進行編譯的?
1. .vue文件
.vue文件,.vue
文件是一個自定義的文件類型,用類 HTML 語法描述一個 Vue 組件。每個 .vue
文件包含三種類型的頂級語言塊 <template>
、<script>
和 <style>
,還允許添加可選的自定義塊.
2. vue-loader
vue-loader
會解析文件,提取每個語言塊,如有必要會通過其它 loader 處理,最后將他們組裝成一個 ES Module,它的默認導(dǎo)出是一個 Vue.js 組件選項的對象。
接下來通過vue-loader的源碼來了解是如何實現(xiàn)編譯的
vue文件分為 template, script, style 三個部分, 而實際必須通過編譯才能在瀏覽器執(zhí)行的部分只有template, 所以我們在看 vue-loader 源碼時可以重點關(guān)注 “template” 關(guān)鍵詞
descriptor.template 如上圖所示, 在源碼搜索 template 關(guān)鍵字可以找到這段處理 script, template, style 的代碼, 仔細觀察發(fā)現(xiàn)這三段都在用 descriptor 對象, 接下來搜索 descriptor, 找到這個變量在哪里生成的 descriptor
再來找 parse 方法
compiler.ts compiler.ts
parse 方法從 vue/compiler-sfc 中引用
至此, 了解到 vue-loader 是通過 @vue/compiler-sfc 的 parse 方法解析 .vue 文件, 從中解析出script, template, style
用一段nodejs代碼進行驗證
// App.vue <template> <div id="app"> <div>{{ a }}</div> <input type="text" v-model="a"> </div> </template> <script> export default { name: 'App', data: () => ({ a: 'hello world' }), } </script>
// build.js const { parse } = require('@vue/compiler-sfc') const fs = require('fs') const data = fs.readFileSync('./App.vue') const { descriptor } = parse(data.toString()) // 結(jié)果包含很多項, 本文檔中只展示重點字段 console.log(Object.keys(descriptor))
運行 build.js
[ 'styles', 'template', 'script', // ... ]
通過以上代碼可以解析出 .vue 文件的三部分, 接下來開始解析 template vue-template-compiler vue-template-compiler 可以將 template 編譯成 Javascript
- 繼續(xù)修改 build.js, 根據(jù)文檔加上 compile 的部分
// build.js const { parse } = require('@vue/compiler-sfc') const fs = require('fs') const compiler = require('vue-template-compiler') const data = fs.readFileSync('./App.vue') const { descriptor } = parse(data.toString()) // console.log(Object.keys(descriptor)) console.log(compiler.compile(descriptor.template.content).render)
- 運行結(jié)果如下
with(this){ return _c( 'div', {attrs:{"id":"app"}}, [ _c('div',[_v(_s(a))]), _v(" "), _c( 'input', { directives:[{name:"model",rawName:"v-model",value:(a),expression:"a"}], attrs:{"type":"text"}, domProps:{"value":(a)}, on:{ "input": function($event){ if($event.target.composing) return; a=$event.target.value } } } ) ] ) }
再將以上代碼放到 .html 的 new Vue(...) 方法中進行驗證
<div id="app"/> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script> <script> const vm = new Vue({ name: 'App', data: () => ({ a: 'hello world!!!', }), render() { const {_c, _v, _s, a} = this return _c( 'div', {attrs: {'id': 'app'}}, [ _c('div', [_v(_s(a))]), _v(' '), _c( 'input', { directives: [{name: 'model', rawName: 'v-model', value: (a), expression: 'a'}], attrs: {'type': 'text'}, domProps: {'value': (a)}, on: { // 注意這里的 this, 需要改成箭頭函數(shù) 'input': ($event) => { if ($event.target.composing) return this.a = $event.target.value }, }, }, ), ], ) }, }).$mount('#app') </script>
以上便是 Webpack 如何將 .vue 文件編譯成瀏覽器可執(zhí)行文件的過程
到此這篇關(guān)于.vue文件編譯成瀏覽器可執(zhí)行文件的流程詳解的文章就介紹到這了,更多相關(guān).vue文件編譯成可執(zhí)行文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue重要修飾符.sync對比v-model的區(qū)別及使用詳解
這篇文章主要為大家介紹了Vue中重要修飾符.sync與v-model的區(qū)別對比及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07vue + echarts實現(xiàn)中國省份地圖點擊聯(lián)動
這篇文章主要介紹了vue + echarts實現(xiàn)中國地圖省份點擊聯(lián)動,需要的朋友可以參考下2022-04-04vue動態(tài)的 BreadCrumb 組件el-breadcrumb ElementUI詳解
這篇文章主要介紹了vue如何做一個動態(tài)的 BreadCrumb 組件,el-breadcrumb ElementUI2024-07-07
,本文通過圖文示例代碼相結(jié)合給大家介紹的非常詳細,需要的朋友可以參考下Vue使用Props實現(xiàn)組件數(shù)據(jù)交互的示例代碼
在Vue中,組件的props屬性用于定義組件可以接收的外部數(shù)據(jù),這些數(shù)據(jù)來自父組件并傳遞給子組件,本文給大家介紹了Vue使用Props實現(xiàn)組件數(shù)據(jù)交互,文中有詳細的代碼示例供大家參考,需要的朋友可以參考下2024-06-06