webpack+vue.js構(gòu)建前端工程化的詳細(xì)教程
本篇主要介紹三塊知識(shí)點(diǎn): node.js ,vue.js,webpack前端工程化 ,希望對(duì)您能有所幫助。
本文來自于csdn,由火龍果軟件Alice編輯推薦。
node.js基本入門
node.js介紹
node.js可以讓javascript程序在后端運(yùn)行起來。我們之前所熟知的javascript都是運(yùn)行在前端瀏覽器,我們編寫好了javascript代碼后,由瀏覽器解釋執(zhí)行。而node.js,可以讓我們編寫javascript,然后在后端運(yùn)行起來。現(xiàn)在的javascript和java、python一樣,可以操作I/O、操作數(shù)據(jù)庫(kù)、或者其他各類操作系統(tǒng)資源。

上面這張圖,和下面的這張圖很像。可以認(rèn)為,node.js是javascript的一種跨平臺(tái)運(yùn)行在主機(jī)的實(shí)現(xiàn)。

環(huán)境搭建
下載node.js (運(yùn)行環(huán)境)
https://nodejs.org/en/
下載Visual Studio Code(開發(fā)環(huán)境)
https://code.visualstudio.com/
npm介紹
寫過Java的同學(xué)應(yīng)該都知道,我們要編寫程序往往都需要導(dǎo)入很多其他額外的JAR包(官方的JavaSE包默認(rèn)提供了)。早期在Maven出現(xiàn)之前,我們都是需要手動(dòng)去下載各種框架的JAR包。自從有了Maven之后,我們不再需要手動(dòng)下載了,直接在一個(gè)POM.XML文件中引入需要的依賴即可。在node中,運(yùn)行一個(gè)node程序也會(huì)依賴于其他的一些模塊。當(dāng)然node也會(huì)自帶一些基本模塊。那當(dāng)我們需要使用這些模塊的時(shí)候,我們需要從網(wǎng)絡(luò)上下載。這個(gè)去網(wǎng)上下載非常麻煩。node官方提供了一個(gè)管理工具npm,這個(gè)工具可以根據(jù)需要自動(dòng)從服務(wù)器下載各種包。這就省去了,我們自己去網(wǎng)上下載包的過程。
npm淘寶鏡像
官方的npm在國(guó)內(nèi)速度是比較慢的,可以使用淘寶的鏡像
npm install -g cnpm --registry=https://registry.npm.taobao.org
安裝完成后,就可以使用cnpm從淘寶鏡像來下載、安裝node包
使用cnpm安裝包
cnpm install <包的名稱>
包的名稱可以去https://npm.taobao.org/上搜索
node.js模塊化程序結(jié)構(gòu)
每一個(gè)js文件就是一個(gè)模塊(json等其實(shí)也可以作為一個(gè)模塊),對(duì)應(yīng)的就是一個(gè)module對(duì)象。下面這一段程序,表示從外部引入一個(gè)模塊,然后執(zhí)行模塊中的函數(shù)。
var fs = require("fs"); // 引入fs模塊
var data = fs.readFileSync('input.txt'); // 調(diào)用fs模塊中的readFileSync方法
console.log(data.toString());
第一行的, required表示引入一個(gè)包,返回的就是module對(duì)象。這個(gè)fs包,是node自帶的包,引入一個(gè)包后就可以調(diào)用這個(gè)包下的方法。但是包中的方法不是都可以被調(diào)用的,只有類似:
exports.world = function() {
console.log('Hello World');
}
這樣的代碼,才能被調(diào)用。更簡(jiǎn)單來說,在包中定義的函數(shù)都是對(duì)外不可見的,要想被外部調(diào)用,需要使用exports來定義函數(shù)。

這個(gè)require函數(shù)有點(diǎn)類似于C語(yǔ)言中的#include。它首先會(huì)從文件cache緩存中查找傳入的模塊名,如果沒有找到再查找原生模塊,最后查找文件中加載。
node.js重要模塊(API)介紹
node.js全局對(duì)象

node.js原生模塊

實(shí)現(xiàn)一個(gè)用戶管理模塊
創(chuàng)建項(xiàng)目
建立一個(gè)空的文件夾用于保存該項(xiàng)目
進(jìn)入命令提示符,使用npm init初始化項(xiàng)目,結(jié)束后會(huì)自動(dòng)生成一個(gè)package.json文件,這個(gè)文件中包含了項(xiàng)目的所有依賴包,可以把這個(gè)package.json文件理解為項(xiàng)目文件
創(chuàng)建客戶Service模塊
/**
* 客戶Service
*/
exports.CustomerService = function() {
this.customers = [];
// 添加客戶
this.add = function(cstm) {
this.customers.push(cstm);
}
// 根據(jù)客戶名字移除
this.remove = function(name) {
for(var i = 0; i < this.customers.length; ++i) {
if(this.customers[i].name === name) {
this.customers.splice(i, 1);
break;
}
}
}
// 獲取所有客戶
this.findAll = function() {
return this.customers;
}
}
創(chuàng)建入口模塊index.js
var customerService = require('./customerService');
var cm = new customerService.CustomerService();
cm.add({name: '小喬', age: 20, sex: '女'});
cm.add({name: '二喬', age: 21, sex: '女'});
cm.add({name: '大喬', age: 22, sex: '女'});
// 查詢所有客戶
var cstms = cm.findAll();
console.log("---");
console.log(cstms);
// 刪除客戶
cm.remove("小喬");
console.log("---");
console.log(cm.findAll())
執(zhí)行node index.js
PS H:\code\nodejs\02> node .\index.js
---
[ { name: '小喬', age: 20, sex: '女' },
{ name: '二喬', age: 21, sex: '女' },
{ name: '大喬', age: 22, sex: '女' } ]
---
[ { name: '二喬', age: 21, sex: '女' },
{ name: '大喬', age: 22, sex: '女' } ]
vue.js基本入門
介紹
Vue是一套前端框架。它實(shí)現(xiàn)了前端頁(yè)面視圖(HTML/CSS)和模型數(shù)據(jù)的分離,而且它提供了快速簡(jiǎn)單構(gòu)建組件的方式。讓我們以一種全新的方式來開發(fā)前端。

基本編程模型(模板 + 模型)
使用Vue指令定義模板
<div id="app">
<span>
{{name}}
</span>
</div>
使用Vue定義數(shù)據(jù)模型
var app2 = new Vue({
el: '#app',
data: { // 定義模型數(shù)據(jù)
name: 'Hello, Tom!'
},
method: { // 定義綁定數(shù)據(jù)方法
sayHello: function() {
alert('hello!');
}
}
})
常用指令介紹

組件化開發(fā)
在前端開發(fā)中引入組件化是一個(gè)大的進(jìn)步。其實(shí),如果我們用過一些UI框架就會(huì)知道,大多數(shù)的UI框架都定義了很多的組件,例如:button按鈕、datagrid表格組件、tree樹形組件、dialog對(duì)話框組件等等。但是,之前我們都是使用別人給我們開發(fā)好的框架。我們今天要學(xué)習(xí)如何使用Vue來開發(fā)一個(gè)自己的組件。將來,我們可以自己開發(fā)一套自己的組件庫(kù),然后使用這些組件庫(kù)來構(gòu)建我們的前端應(yīng)用程序。
組件結(jié)構(gòu)
可以把組件理解為就是一個(gè)小的頁(yè)面視圖。使用Vue開發(fā)的組件也分為兩個(gè)部分:
視圖模板
屬性(模型數(shù)據(jù))
視圖模板依舊是使用HTML/CSS+Vue指令,但是模型數(shù)據(jù)現(xiàn)在跟之前不太一樣,模型數(shù)據(jù)應(yīng)該是使用組件的時(shí)候,動(dòng)態(tài)傳入進(jìn)來的。所以,模型數(shù)據(jù)需要先定義出來。

實(shí)現(xiàn)一個(gè)購(gòu)物車程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>購(gòu)物車</title>
<link rel="stylesheet" href="./bootstrap/css/bootstrap.css" rel="external nofollow" >
</head>
<body>
<div id="app" class="container">
<h1>購(gòu)物車</h1>
<hr>
<btn-grp :buttons="buttons"></btn-grp>
<btn-grp :buttons="buttons_test"></btn-grp>
<btn-grp :buttons="buttons"></btn-grp>
<btn-grp :buttons="buttons_test"></btn-grp>
<br>
<br>
<table class="table table-bordered table-striped table-hover">
<tr>
<th>ID</th>
<th>商品名稱</th>
<th>商品價(jià)格</th>
<th>商品數(shù)量</th>
<th>商品總價(jià)</th>
</tr>
<tr v-for="(prod, index) in products">
<td>{{index+1}}</td>
<td>{{prod.name}}</td>
<td>{{prod.price}}</td>
<td>
<button @click="changeCount(prod, -1)">-</button>
<input type="text" v-model="prod.count">
<button @click="changeCount(prod, 1)">+</button>
</td>
<td>{{prod.price * prod.count}}</td>
</tr>
<tr>
<td colspan="4" class="text-right">總價(jià):</td>
<td class="text-primary">{{getTotalMoney()}}</td>
</tr>
</table>
</div>
<script src="./vue.js"></script>
<script>
// 自定義組件,這里實(shí)現(xiàn)了一個(gè)按鈕組組件
Vue.component('btn-grp', {
props: ['buttons'],
template:
'<div class="btn-group" role="group">'
+ '<button type="button" @click="btn.handler" v-for="btn in buttons" :class="\'btn \' + (btn.class == null || btn.class == \'\' ? \'btn-default\':btn.class)">'
+ '{{btn.title}}'
+ '</button>'
+ '</div>'
});
var app = new Vue({
el: '#app',
data: {
// 按鈕組件測(cè)試
buttons_test: [
{title: '測(cè)試1', class: 'btn-danger'},{title: '測(cè)試2'},{title: '測(cè)試3'},{title: '測(cè)試4'},
],
buttons: [{
title: '添加',
class: 'btn-primary',
handler: function() {
alert('點(diǎn)擊添加按鈕');
}
}, {
title: '修改',
class: 'btn-default',
handler: function() {
alert('點(diǎn)擊修改按鈕');
}
}, {
title: '刪除',
class: 'btn-default',
handler: function() {
alert('點(diǎn)擊刪除按鈕');
}
}, ],
products: [
{
name: '小米6S',
price: 3999,
count: 1,
},
{
name: '錘子2',
price: 4999,
count: 1,
},
{
name: '華為P20',
price: 3599,
count: 1,
},
{
name: 'OPPO R15',
price: 2999,
count: 1,
},
{
name: 'OPPO R11',
price: 1999,
count: 1,
},
],
},
methods: {
// 用戶點(diǎn)擊加減數(shù)量時(shí)調(diào)用
changeCount: function(prod, num) {
if(num < 0) {
if(prod.count > 0) {
prod.count += num;
}
}
else {
prod.count += num;
}
},
// 獲取總金額
getTotalMoney: function() {
var totalMoney = 0.0;
for(var i = 0; i < this.products.length; ++i) {
totalMoney += parseFloat(this.products[i].price * this.products[i].count);
}
return totalMoney;
}
}
});
</script>
</body>
</html>
效果圖

使用webpack構(gòu)建前端工程化
webpack介紹
webpack是一個(gè)前端項(xiàng)目構(gòu)建工具。使用webpack可以把前端當(dāng)成一個(gè)工程來開發(fā)。而且能夠很好地把前端的各類資源統(tǒng)一管理、編譯、打包。
它是一個(gè)“編譯器”,可以通過各種插件將基于node.js、sass、less編寫代碼編譯成能夠運(yùn)行在前端瀏覽器的javascript、和css
它是一個(gè)打包工具,可以將所有前端的資源打包到一個(gè)bundle.js中
有了webpack,我們可以像開發(fā)后端應(yīng)用一樣開發(fā)前端。
總體結(jié)構(gòu)圖

webpack是基于node.js開發(fā)的一款應(yīng)用,其實(shí)webpack就是一個(gè)node.js的模塊。

安裝webpack
創(chuàng)建一個(gè)空的文件夾
使用npm init創(chuàng)建package.json
安裝cnpm淘寶鏡像
使用cnpm install vue-cli -g全局安裝vue-cli模塊
使用vue init webpack cart創(chuàng)建基于webpack購(gòu)物車項(xiàng)目
使用cnpm install bootstrap --save安裝bootstrap模塊
具體步驟請(qǐng)參考:https://www.webpackjs.com/guides/installation/
使用webpack重構(gòu)購(gòu)物車程序
使用vue-cli生成項(xiàng)目腳手架如下圖:

將原來編寫的btn-grp組件單獨(dú)編寫到BtnGrp.vue文件中
可以看到現(xiàn)在代碼清晰了很多,template標(biāo)簽部分編寫模板,script標(biāo)簽部分編寫組件的交互代碼,編寫方式和原先寫在HTML的代碼一致
現(xiàn)在整個(gè)前端應(yīng)用都是基于組件化的,代碼變得更加清晰了
<template>
<div class="btn-group" role="group">
<button :key="btn.title"
type="button" @click="btn.handler"
v-for="btn in buttons"
:class="'btn ' + (btn.class == null || btn.class == '' ? 'btn-outline-secondary':btn.class)">
{{btn.title}}
</button>
</div>
</template>
<script>
export default {
props: ['buttons']
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
將原來寫在HTML中的代碼重構(gòu)到App.vue中
此處因?yàn)樾枰玫紹tnGrp組件,所以需要先import 組件,然后在components中引用該組件
<template>
<div id="app" class="container">
<h1>WEBPACK + VUE 實(shí)現(xiàn)購(gòu)物車</h1>
<BtnGrp :buttons="buttons"></BtnGrp>
<br/>
<br/>
<table class="table table-bordered table-striped table-hover">
<tr>
<th>ID</th>
<th>商品名稱</th>
<th>商品價(jià)格</th>
<th>商品數(shù)量</th>
<th>商品總價(jià)</th>
</tr>
<tr :key="index+1" v-for="(prod, index) in products">
<td>{{index+1}}</td>
<td>{{prod.name}}</td>
<td>{{prod.price}}</td>
<td>
<button class="btn btn-outline-info btn-sm" @click="changeCount(prod, -1)">-</button>
<input style="width:50px" type="text" v-model="prod.count">
button class="btn btn-outline-info btn-sm" @click="changeCount(prod, 1)">+</button>
</td>
<td>{{prod.price * prod.count}}</td>
</tr>
<tr>
<td colspan="4" class="text-right">總價(jià):</td>
<td class="text-primary">{{getTotalMoney()}}</td>
</tr>
</table>
</div>
</template>
<script>
/* eslint-disable no-new */
import 'bootstrap/dist/css/bootstrap.min.css'
import BtnGrp from './components/BtnGrp'
export default {
name: 'App',
components: {BtnGrp},
data () {
return {
products: [
{
name: '小米6S',
price: 3999,
count: 1,
},
{
name: '錘子2',
price: 4999,
count: 1,
},
{
name: '華為P20',
price: 3599,
count: 1,
},
{
name: 'OPPO R15',
price: 2999,
count: 1,
},
{
name: 'OPPO R11',
price: 1999,
count: 1,
},
],
buttons: [{
title: '添加',
class: 'btn-outline-primary',
handler: function() {
alert('點(diǎn)擊添加按鈕');
}
}, {
title: '修改',
class: 'btn-outline-primary',
handler: function() {
alert('點(diǎn)擊修改按鈕');
}
}, {
title: '刪除',
class: 'btn-outline-danger',
handler: function() {
alert('點(diǎn)擊刪除按鈕');
}
}, ],
changeCount: function(prod, num) {
if(num < 0) {
if(prod.count > 0) {
prod.count += num;
}
}
else {
prod.count += num;
}
},
getTotalMoney: function() {
var totalMoney = 0.0;
for(var i = 0; i < this.products.length; ++i) {
totalMoney += parseFloat(this.products[i].price * this.products[i].count);
}
?
return totalMoney;
}
}
}
}
</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>
因?yàn)閚pm安裝的bootstrap是bootstrap4,所以稍微對(duì)原先的樣式調(diào)整了下。最終的效果圖如下:

總結(jié)
到此這篇關(guān)于webpack+vue.js構(gòu)建前端工程化的文章就介紹到這了,更多相關(guān)webpack vuejs 前端工程化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue的路由動(dòng)畫切換頁(yè)面無法讀取meta值的bug記錄
這篇文章主要介紹了vue的路由動(dòng)畫切換頁(yè)面無法讀取meta值的bug記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
vue如何實(shí)現(xiàn)未登錄不能訪問某些頁(yè)面
這篇文章主要介紹了vue如何實(shí)現(xiàn)未登錄不能訪問某些頁(yè)面問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
Vue單頁(yè)面應(yīng)用做預(yù)渲染的方法實(shí)例
vue是一個(gè)單頁(yè)面的應(yīng)用,這導(dǎo)致一些爬蟲和百度無法搜索到,如果你想針對(duì)你應(yīng)用的其中某些頁(yè)面進(jìn)行SEO優(yōu)化,讓他們可以被爬蟲和百度搜索到,你可以進(jìn)行預(yù)渲染操作,下面這篇文章主要給大家介紹了關(guān)于Vue單頁(yè)面應(yīng)用做預(yù)渲染的相關(guān)資料,需要的朋友可以參考下2021-10-10
Vue使用Echarts實(shí)現(xiàn)橫向柱狀圖,并通過WebSocket即時(shí)通訊更新
這篇文章主要介紹了Vue使用Echarts實(shí)現(xiàn)橫向柱狀圖,并通過WebSocket即時(shí)通訊更新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Vue resource三種請(qǐng)求格式和萬(wàn)能測(cè)試地址
這篇文章主要介紹了Vue-resource三種請(qǐng)求格式和萬(wàn)能測(cè)試地址,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
vue-router 源碼之實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vue-router
這篇文章主要介紹了vue-router 源碼之實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vue-router,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07
vue elementUI 表單校驗(yàn)的實(shí)現(xiàn)代碼(多層嵌套)
這篇文章主要介紹了vue elementUI 表單校驗(yàn)的實(shí)現(xiàn)代碼(多層嵌套),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

