vue 的腳手架整合了 webpack,並進行了大量的預設設定
我們只需要按照框架的要求編寫程式碼,打包就好了
慢慢的我們就成了傻瓜,不知道這其中到底發生了什麼,一旦遇到問題,不知道該如何思考,因為你可能都不清楚它的運作原理
更何況,看尤大的思路,將來很可能使用腳手架建立專案時,打包工具不再是預設的,而是讓你 webpack 和 vite 二選一
所以,我們就更需要對打包過程有一個大概的瞭解
下面我們就手動實現這一點
SPA 和元件化密不可分,元件化讓SPA成為可能,SPA促使元件化程式設計的落地
vue 的單檔案元件就是具體的體現
建立專案資料夾 webpack-demo
執行如下命令進行初始化
npm init -y
根目錄下新建 src 目錄
src 目錄下新建 index.html,main.js
index.html 程式碼
<!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>Document</title>
</head>
<body>
<div id="app"></div>
<!-- 引入打包之後的檔案,先不用理解 -->
<script src="../dist/bundle.js"></script>
</body>
</html>
src 目錄下新建 Home.vue
<template>
<div class="home">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
data: function () {
return {
msg: 'Home'
}
},
methods: {
},
computed: {
},
watch: {
}
}
</script>
<style scoped>
h1 {
color: red;
}
</style>
當前目錄結構如下
安裝 webpack
npm i webpack webpack-cli -D
根目錄下新建 webpack.config.js,設定打包模式、入口和出口檔案
const path = require('path')
module.exports = {
mode: 'development',
entry: path.join(__dirname, 'src', 'main.js'), // 打包的入口檔案
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
}
}
package.json 中新增打包命令
在 src/main.js 中編寫程式碼
import Vue from 'vue'
import Home from './Home.vue'
let vm = new Vue({
el: '#app', // 指定當前vue範例的掛載點,也就是將index.html 中的id=app 的dom作為掛載點
// 將 Home 元件中的模板和樣式渲染到 index.html 頁面中,具體來說,
// 就是用模板中的內容替換 index.html 中的 id=app 的元素,也會將 css 放到頁面中
render: h => h(Home)
})
執行打包命令
npm run dev
報錯
錯誤解決見下一節
上面錯誤原因在於 webpack 預設只能打包 js 檔案,對於 .vue 檔案不認識
所以需要安裝能夠處理 vue 檔案的 loader
這個 loader 不能在 webpack 檔案中找,因為 webpack 與 vue 本身是沒有關係的
webpack 只是一個打包工具,預設可以處理 js 檔案,並且提供了一些通用的 laoder,比如
所以,vue 官方提供了能夠處理 vue 檔案的載入器
https://vue-loader.vuejs.org/zh/
安裝
npm install -D vue-loader vue-template-compiler
在webpack 中設定
錯誤資訊
上面錯誤是因為元件中有 css 程式碼,需要對應的 loader
安裝 loader
npm i style-loader css-loader -D
設定規則
module: {
rules: [
{ test: /\.vue$/, loader: 'vue-loader' },
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
重新執行
npm run dev
打包成功
執行 index.html
src 目錄下新建 About.vue
<template>
<div class="about">
<h2>關於我們</h2>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
h2 {
color: orange;
}
</style>
希望執行 index.html 的時候展示 About 元件的內容,怎麼辦?
可以修改 main.js
重新打包
npm run dev
index.html
雖然實現了,但很顯然,這種實現方案是不現實的
其實,元件切換的邏輯應該是這樣的
我們都知道,頁面實際執行中,其實就是將 vue 範例中 render 屬性指定的元件內容替換掉 index.html 中的 id=app 的元素
我們新建一個根元件,將根元件的內容顯示到 index.html 中的 id=app 的元素上
當元件發生切換時,改變根元件中的內容,也就是將其他元件的內容顯示到跟元件上,而根元件又渲染到 index.html 中,所以最終 html 頁面也會變化
引入 vue 的官方路由 vue-router,來實現這一點
安裝vue-router
npm install vue-router
建立根元件
src 目錄下建立 App.vue
<template>
<div id="app">
<!-- 路由出口 -->
<!-- 路由匹配到的元件將渲染在這裡 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
其中 router-view 作為匹配到路由規則的元件的展示區域
修改打包入口檔案
main,js 中引入 vue-router,並編寫路由規則,並向 vue 範例註冊 router 範例
還要注意,上面 render 函數中將元件名稱改成了 App 元件
重新打包
通過修改位址列中的 hash 值,可以看到對應的元件內容
我們不能要求使用者通過修改位址列來切換不同的元件
必須要提供一個導航
而且這個導航,無論 Home 還是 About 元件都需要
所以不能分別在兩個元件中定義一份,否則隨著專案的擴大,維護成本會越來越高
解決方案:提取一個公共導航
src 目錄下新建 NavBar.vue
<template>
<nav>
<ul>
<li><router-link to="/home">首頁</router-link></li>
<li><router-link to="/about">關於我們</router-link></li>
</ul>
</nav>
</template>
<script>
export default {
}
</script>
<style scoped>
ul {
list-style-type: none;
overflow: hidden;
}
li {
float: left;
padding: 10px;
}
a {
text-decoration: none;
}
</style>
修改 App.vue,引入上面的元件,並在 router-view 上面使用
重新打包,然後執行 index.html
現在我們可以通過點選連線切換元件了
至此,一個簡單的 SPA 應用就完成了
隨著專案變大,元件會越來越多,全部都放在 src 目錄下,不便於管理
另外,隨著元件的增多,路由規則也會越來越多,我們當前將所有路由規則寫在 入口檔案 main.js 中,會讓檔案越來越臃腫,另外入口檔案的作用應該是告訴webpack 哪些檔案應該打包,而不應該放路由處理這種邏輯程式碼,所以應該也提取出來
具體操作
router/index.js 中程式碼如下
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 安裝路由功能:
Vue.use(VueRouter)
/**
* 建立路由規則
* 當使用者請求不同的hash值時,顯示不同的元件(將不同的元件內容顯示在 <router-view></router-view>)
*/
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
// 建立 router 範例,然後傳 `routes` 設定
const router = new VueRouter({
routes
})
export default router
main.js 中程式碼修改如下
import Vue from 'vue'
import router from './router' // 可以省略 index.js
import App from './App.vue'
let vm = new Vue({
el: '#app', // 指定當前vue範例的掛載點,也就是將index.html 中的id=app 的dom作為掛載點
// 將 Home 元件中的模板和樣式渲染到 index.html 頁面中,具體來說,
// 就是用模板中的內容替換 index.html 中的 id=app 的元素,也會將 css 放到頁面中
render: h => h(App),
router
})
執行命令,重新打包,發現程式能夠正常執行
npm run dev
經過一系列的步驟,我們手動建立的第一個單頁面應用已經成功
仔細對比一下,發現與使用 vue 腳手架建立專案,目錄結構基本一致了