一,、使用vue-cli腳手架創(chuàng)建一個(gè)最簡(jiǎn)單項(xiàng)目
我們通過vue的腳手架工具,,執(zhí)行vue create vue-demo 可以生成最初項(xiàng)目。從最初的腳手架初始化項(xiàng)目中,,我們可以看到項(xiàng)目根目錄下主要有一個(gè)public目錄和src目錄,,其中public目錄下主要就是一個(gè)index.html文件,這個(gè)index.html文件的作用就是為當(dāng)前vue項(xiàng)目提供一個(gè)html模板,,因?yàn)?strong>Vue實(shí)例要想掛載,,即要想顯示到html模板上,必須給其提供一個(gè)掛載點(diǎn),,所以模板中必須存在一個(gè)<div id="app"></div>,,如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vue-webpack</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
接下來,看一下src目錄,,該目錄下主要有main.js和App.vue兩個(gè)文件,,其中main.js就是整個(gè)Vue項(xiàng)目的入口文件,App.vue就是整個(gè)Vue項(xiàng)目的首頁,,即當(dāng)前單頁面應(yīng)用的首頁,。整個(gè)Vue項(xiàng)目是通過webpack打包來啟動(dòng)項(xiàng)目,但是我們發(fā)現(xiàn),,整個(gè)項(xiàng)目中并沒有webpack的配置文件,。因?yàn)槠洳]有對(duì)外暴露webpack的配置文件,如果我們需要修改webpack的配置文件,,那么可以在項(xiàng)目根目錄下新建一個(gè)vue.config.js文件, 然后在configureWebpack中進(jìn)行配置文件的修改,,內(nèi)容如下:
// vue.config.js
module.exports = {
configureWebpack: {
mode: "development",
plugins: [
new MyAwesomeWebpackPlugin()
]
}
}
當(dāng)然,如果想要查看默認(rèn)的webpack文件到底給我們配置了什么,,我們可以通過在項(xiàng)目根目錄下執(zhí)行 vue inspect > output.txt來大體查看webpack配置文件內(nèi)容,。
二、vue項(xiàng)目的啟動(dòng)過程
vue項(xiàng)目的啟動(dòng)過程就是,,首先以src目錄下的main.js為項(xiàng)目入口進(jìn)行打包,,然后將打包后的js文件,自動(dòng)插入到public目錄下的index.html模板中,,然后加載index.html文件并執(zhí)行打包后的js文件,。首先看一下main.js中的具體內(nèi)容,如:
// vue.config.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false // 禁用生產(chǎn)模式下的提示信息
new Vue({
render: (h) => {
return h(App)
},
}).$mount('#app')
我們可以看到main.js中就是引入了一下vue.js并創(chuàng)建一個(gè)Vue實(shí)例對(duì)象,,然后調(diào)用$mount()方法進(jìn)行了一下mount,。 需要注意的是,傳入$mount()方法的參數(shù),,必須和public目錄下的index.html中的id值一致,,否則Vue實(shí)例將找不到掛載點(diǎn)掛載。 那么Vue實(shí)例掛載到頁面后顯示什么內(nèi)容呢?答案就是,,創(chuàng)建Vue實(shí)例的時(shí)候配置的render()函數(shù),,當(dāng)Vue實(shí)例創(chuàng)建完成后,通過調(diào)用$mount()函數(shù)開始Vue實(shí)例的掛載,,掛載的過程中,,會(huì)執(zhí)行render()函數(shù),,render()函數(shù)執(zhí)行會(huì)產(chǎn)生一個(gè)虛擬節(jié)點(diǎn),,然后將虛擬節(jié)點(diǎn)轉(zhuǎn)換為真實(shí)DOM節(jié)點(diǎn)并掛載到頁面中。需要注意的時(shí)候,,Vue實(shí)例掛載后,,public目錄下的index.html文件中的<div id="app"></div> 會(huì)被渲染結(jié)果替換掉,即覆蓋掉,。
其中有一行Vue.config.productionTip = false ,,該行代碼的作用就是禁用生產(chǎn)模式下的提示警告,簡(jiǎn)單說就是,,如果當(dāng)前項(xiàng)目是在production模式下,,那么就禁用一些無用的警告信息提示;如果當(dāng)前項(xiàng)目是在development模式下,,那么就不禁用,,而是正常提示警告信息,通常就是禁用如下提示,,如:
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https:///guide/deployment.html
再看一下App.vue,,App.vue就是一個(gè)Vue的組件,其會(huì)被vue-loader處理,,然后交給render()渲染函數(shù)處理并渲染,。
// App.vue
<template>
<div id="app">
{{msg}}
</div>
</template>
<script>
export default {
data() {
return {
msg: "hello msg"
}
}
}
</script>
項(xiàng)目中通過import Vue from "vue" 引入的其實(shí)是運(yùn)行時(shí)的vue,因?yàn)槲覀兛梢酝ㄟ^查看vue的webpack配置文件,,我們可以看到,,其配置了一個(gè)alias別名,所以當(dāng)引入vue的時(shí)候,,找的是vue/dist/vue.runtime.esm.js,,這是一個(gè)runtime運(yùn)行時(shí)的版本,而運(yùn)行時(shí)的vue版本,,是不支持template配置的,,因?yàn)?strong>運(yùn)行時(shí)的版本沒有編譯器,所以無法將template模板內(nèi)容編譯為渲染函數(shù),。
resolve: {
vue$: 'vue/dist/vue.runtime.esm.js' // $表示精確匹配
}
如果使用的是運(yùn)行時(shí)的版本,,那么當(dāng)配置了template的時(shí)候,項(xiàng)目運(yùn)行就會(huì)輸出如下警告信息,即你當(dāng)前使用的是運(yùn)行時(shí)的vue,,此時(shí)編譯器不可用,,即不包含編譯器,因?yàn)榫幾g器的作用就是,,將template模板編譯為渲染函數(shù),,所以你可以自己手動(dòng)配置一個(gè)render渲染函數(shù)或者使用帶編譯器的vue進(jìn)行構(gòu)建。
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build
如果想要使用帶編譯器的版本,,我們可以引入 "vue.esm.js",。這里有點(diǎn)比較難于理解的地方就是,我們引入的App.vue可以直接交給渲染函數(shù)的createElement(App)函數(shù)進(jìn)行處理,,因?yàn)関ue-loader對(duì).vue文件進(jìn)行了轉(zhuǎn)換,,我們可以以下面的方式理解,如:
import Vue from "vue";
// App.vue start
const _vm = new Vue({
data() {
return {
msg: "hello msg."
}
}
});
// import App from "./App.vue"; 引入后等價(jià)于如下
const App = ["div", {attrs: {"id":"app"}},_vm.msg];
// App.vue end
let vm = new Vue({
render: (h) => {
return h(...App);
}
});
vm.$mount("#app")
當(dāng)然,,我們不需要知道vue-loader具體是怎么轉(zhuǎn)換的,,為什么轉(zhuǎn)換后的內(nèi)容可以直接被createElement()函數(shù)直接渲染。我們只需要知道vue-loader會(huì)對(duì).vue文件中的<template></template> 模板進(jìn)行預(yù)編譯即可,。
三,、自己配置webpack
為了更好的理解vue-cli生成的項(xiàng)目,我們可以自己配置webpack,,然后實(shí)現(xiàn)vue-cli生成項(xiàng)目的運(yùn)行,,即自己創(chuàng)建一個(gè)新的項(xiàng)目,然后在src目錄下加入main.js和App.vue以及在public目錄下加入index.html文件,,然后通過自己配置的webpack讓項(xiàng)目運(yùn)行起來,,其webpack.config.js內(nèi)容如下
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
mode: "development",
target: "web",
entry: {
main: "./src/main.js"
},
output: {
path: path.resolve(__dirname, "./dist"),
filename: "[name].js"
},
devServer: {
port: 3000, // 讓devServer監(jiān)聽3000端口
contentBase: "./dist", // 將當(dāng)前項(xiàng)目的dist目錄作為devServer的根目錄
progress: true, // 顯示打包進(jìn)度條
compress: true // 是否啟用Gzip壓縮,默認(rèn)為false
},
module: {
rules: [
{
test: /\.vue$/, // 處理.vue文件
use: [
{
loader: "vue-loader"
}
]
},
{
test: /\.css$/, // 處理.css文件,,包括.vue文件中的<style></style>部分
use: [
'style-loader',
'css-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({ // 將打包后的js文件自動(dòng)注入到public目錄下的index.html文件中
template: "./public/index.html",
filename: "index.html"
}),
new VueLoaderPlugin() // 處理.vue文件
]
}
|