Vue之文件加載執(zhí)行全流程
Vue項(xiàng)目結(jié)構(gòu)
使用webpack構(gòu)建的Vue項(xiàng)目的結(jié)構(gòu)如下所示:

主要配置文件
1、package.json
package.json是一個(gè)json文件,這是vue項(xiàng)目的表述文件。
package.json定義了項(xiàng)目所需要的各種模塊,以及項(xiàng)目的配置信息(名稱、版本、許可證等),npm install命令也是根據(jù)這個(gè)配置文件自動(dòng)下載項(xiàng)目所需的模塊。
{
"name": "myvue1",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "LearningJun <2393690538@qq.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.18.0",
"echarts": "4.6.0",
"echarts-stat": "^1.2.0",
"element-ui": "^2.13.2",
"js-cookie": "^2.2.1",
"moment": "^2.24.0",
"qs": "^6.7.0",
"vue": "^2.5.2",
"vue-amap": "^0.5.9",
"vue-axios": "^2.1.4",
"vue-baidu-map": "^0.21.22",
"vue-cookies": "^1.5.6",
"vue-echarts": "^5.0.0-beta.0",
"vue-puzzle-vcode": "^1.0.7",
"vue-router": "^3.0.1",
"vue-video-player": "^5.0.2",
"vue2-verify": "^1.1.5",
"vuex": "^3.1.0",
"vxe-table": "^2.9.22",
"xe-utils": "^2.7.12"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass-loader": "^7.3.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"style-loader": "^1.0.0",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
name:包名version:包的版本號(hào)main:入口文件,一般都是 index.jsscripts:支持的腳本,默認(rèn)是一個(gè)空的 testkeywords:關(guān)鍵字,有助于在人們使用 npm search 搜索時(shí)發(fā)現(xiàn)你的項(xiàng)目description:包的描述author: 包的作者repository:包代碼的repo信息,包括type和URL,type可以是git或者svn,url則是包的repo地址。license:默認(rèn)是 [MIT],項(xiàng)目許可證,讓使用者知道是如何被允許使用此項(xiàng)目。dependencies:生產(chǎn)環(huán)境依賴包列表devDependencies:開發(fā)環(huán)境、測(cè)試環(huán)境依賴包列表engines: 聲明項(xiàng)目需要的node或npm版本范圍
(1)添加、更新依賴
①添加依賴
可以手動(dòng)添加或者使用命令npm install <package_name> --save(將這個(gè)包名及對(duì)應(yīng)的版本添加到 package.json的 dependencies)或npm install
<package_name> --save-dev(將這個(gè)包名及對(duì)應(yīng)的版本添加到 package.json的 devDependencies)
②更新依賴
查詢依賴的包是否有新版本可以使用 npm outdated 命令。如果發(fā)現(xiàn)有的包有新版本,就可以使用npm update更新它,或者直接 npm update 更新所有。
③卸載本地依賴
npm uninstall < package-name>
(2)腳本執(zhí)行
npm 可以直接運(yùn)行運(yùn)行package.json 中 scripts 指定的腳本。 npm run 是 npm run-script的縮寫。命令行輸入 npm run dev 或者 npm run-script dev 就會(huì)執(zhí)行 'dev’后面的內(nèi)容 。
例如:當(dāng)我們執(zhí)行npm run dev時(shí),首選執(zhí)行的是webpack.dev.conf.js;當(dāng)我們執(zhí)行npm run build時(shí),首選執(zhí)行的是build.js
2、config/index.js
const path = require('path')
module.exports = {
//開發(fā)時(shí)使用的配置
dev: {
//輸出的子文件夾路徑
assetsSubDirectory: 'static',
//發(fā)布路徑
assetsPublicPath: '/',
//配置代理表
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
//端口
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
//是否自動(dòng)打開瀏覽器
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
//打包時(shí)使用的配置
build: {
// Template for index.html
// 輸入的index.html的路徑
index: path.resolve(__dirname, '../dist/index.html'),
// 輸出的目標(biāo)文件夾路徑
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
//是否使用SourceMap
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
// 是否開啟Gzip
productionGzip: false,
//Gzip的壓縮文件類型
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
3、build/webpack.base.conf.js
- 配置編譯入口和輸出路徑
- 模塊resolve的規(guī)則
- 配置不同類型模塊的處理規(guī)則
'use strict'
const path = require('path')
const utils = require('./utils')
//引入相關(guān)配置
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
//絕對(duì)路徑
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, '../'),
//webpack的入口文件
entry: {
app: './src/main.js'
},
output: {
//webpack輸出文件的路徑
path: config.build.assetsRoot,
//輸出的文件命名格式
filename: '[name].js',
// webpack編譯輸出的發(fā)布路徑
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
//配置不同類型模塊的處理規(guī)則
module: {
rules: [
//所有的.vue文件使用vue-loader
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
//src和test下的.js文件使用babel-loader
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
//所有的圖片文件使用url-loader
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
//所有的音頻文件使用url-loader
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
//所有的字體文件使用url-loader
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{ //從這一段上面是默認(rèn)的!不用改!下面是沒有的需要你手動(dòng)添加,相當(dāng)于是編譯識(shí)別sass!
test: /\.scss$/,
loaders: ["style", "css", "sass"]
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
Vue項(xiàng)目啟動(dòng)代碼執(zhí)行流程分析
一般一個(gè)初步的Vue項(xiàng)目創(chuàng)建好之后都會(huì)有這三個(gè)文件:index.html 、main.js 和App.js。
1、index.html
Vue是單頁(yè)面形式開發(fā),index.html文件在其中起著特別重要的作用。所有組件(后綴名為.vue都被視為組件)都會(huì)通過此文件進(jìn)行渲染加載。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>y</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
在body體中只有一個(gè)div標(biāo)簽,其id為app,這個(gè)id將會(huì)連接到src/main.js內(nèi)容
2、main.js
相當(dāng)于一個(gè)C/Java中的入口函數(shù),控制著初次啟動(dòng)Vue項(xiàng)目要加載的組件。
import Vue from 'vue'
import App from './App'
import router from './router'
import lhj from './components/lhj'
Vue.config.productionTip = false
import axios from "axios";
import VueAxios from "vue-axios";
Vue.use(VueAxios,axios)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
watch:{}
})
在main.js中,新建了一個(gè)vue實(shí)例,并使用el:#app鏈接到index.html中的app,并使用template引入組件和路由相關(guān)的內(nèi)容,也就是說通過main.js我們關(guān)聯(lián)到App.vue組件。
(1)import A from ‘B’
這類語(yǔ)句相當(dāng)于引入B(這一般是路徑)然后給它起個(gè)名字叫做A;
(2)Vue.use(C)
這個(gè)意思是全局方法定義 C。也就是說,定義以后你可以在這個(gè)Vue項(xiàng)目的任意地方使用該組件。
(3)el: ‘#app’
這個(gè)和index.html中的相掛鉤。

模板將會(huì)替換掛載的元素,掛載元素的內(nèi)容都將被忽略。
也就是說:template: ‘< App/>’ 表示用< app>< /app>替換index.html里面的< div id=“app”>,然后index.html文件被初步解析為這種形式
<body>
<div id="myapp">
<app></app>
</div>
</body>
(4)watch : 用來監(jiān)聽路由的變化,可以用來定義頁(yè)面切換時(shí)過渡效果。
3、App.vue
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
標(biāo)準(zhǔn)的App.vue模板的形式,包含了<template></template>、<script></script>、<style></style>三部分。
(1)export中的name屬性,相當(dāng)于給這個(gè)組件定義一個(gè)名字,便于識(shí)別和使用。
(2)< template>標(biāo)簽下,除了< img>標(biāo)簽外,還有< router-view>標(biāo)簽,< router-view>標(biāo)簽將會(huì)把路由相關(guān)內(nèi)容渲染在這個(gè)地方。路由的內(nèi)容定義在src/router/index.js文件中。
4、src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
在index.js的代碼中,建立了路由相關(guān)的內(nèi)容,也就會(huì)渲染到app.vue下面的< router-view>中。
(1)引入組件的代碼
引入的時(shí)候注意好格式、路徑就行。
(2)routes定義
path:頁(yè)面間路由跳轉(zhuǎn)的路徑;name:該路由的名稱;component:組件名,要和你引入組件時(shí)定義的名字保持一致。
Vue加載時(shí)文件的執(zhí)行順序
1、執(zhí)行index.html文件
2、執(zhí)行main.js文件
3、main.js掛載了app.vue文件,用app.vue的templete替換index.html中的
4、main.js中注入了路由文件,將對(duì)應(yīng)的組件渲染到router-view中 5、router-view中加載Layout文件
6、Layout 加載Navbar, Sidebar, AppMain
Vue內(nèi)部頁(yè)面的執(zhí)行順序
Vue 推薦在絕大多數(shù)情況下使用 template 來創(chuàng)建你的 HTML。但是模板畢竟是模板,不是真實(shí)的dom節(jié)點(diǎn)。從模板到真實(shí)dom節(jié)點(diǎn)還需要經(jīng)過一些步驟:
1、把模板編譯為render函數(shù)
2、實(shí)例進(jìn)行掛載, 根據(jù)根節(jié)點(diǎn)render函數(shù)的調(diào)用,遞歸的生成虛擬dom
3、對(duì)比虛擬dom,渲染到真實(shí)dom
4、組件內(nèi)部data發(fā)生變化,組件和子組件引用data作為props重新調(diào)用render函數(shù),生成虛擬dom, 返回到步驟3
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue-cli3使用 DllPlugin 實(shí)現(xiàn)預(yù)編譯提升構(gòu)建速度
這篇文章主要介紹了vue-cli3使用 DllPlugin 實(shí)現(xiàn)預(yù)編譯提升構(gòu)建速度 ,需要的朋友可以參考下2019-04-04
Vue項(xiàng)目從webpack3.x升級(jí)webpack4不完全指南
前段時(shí)間,泡面將自己的一個(gè)Vue-cli構(gòu)建的前端框架從webpack3.x升級(jí)到了4.x版本,現(xiàn)在才拉出來記錄一下,已備忘之用,也和大家分享一下,需要的朋友可以參考下2019-04-04
rem實(shí)現(xiàn)響應(yīng)式布局的思路詳解
這篇文章主要為大家介紹了rem實(shí)現(xiàn)響應(yīng)式布局的思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
詳解Vue學(xué)習(xí)筆記入門篇之組件的內(nèi)容分發(fā)(slot)
這篇文章主要介紹了詳解Vue學(xué)習(xí)筆記入門篇之組件的內(nèi)容分發(fā)(slot),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07

