使用webpack+vue.js構建前端工程化

參考文章:https://blog.csdn.net/qq_40208605/article/details/80661572javascript

使用webpack+vue.js構建前端工程化
本篇主要介紹三塊知識點:css

node.jshtml

vue.js前端

webpack前端工程化vue

本篇不是寫給零基礎的同窗看的,讀者應具有一些服務器開發、前端開發基礎java

本篇目標
使用webpack+vue.js構建前端工程化本篇目標node.js基本入門node.js介紹環境搭建npm介紹npm淘寶鏡像使用cnpm安裝包node.js模塊化程序結構node.js重要模塊(API)介紹node.js全局對象node.js原生模塊實現一個用戶管理模塊vue.js基本入門介紹基本編程模型(模板 + 模型)使用Vue指令定義模板使用Vue定義數據模型經常使用指令介紹組件化開發組件結構實現一個購物車程序使用webpack構建前端工程化webpack介紹整體結構圖安裝webpack使用webpack重構購物車程序node

node.js基本入門
node.js介紹
node.js可讓javascript程序在後端運行起來。咱們以前所熟知的javascript都是運行在前端瀏覽器,咱們編寫好了javascript代碼後,由瀏覽器解釋執行。而node.js,可讓咱們編寫javascript,而後在後端運行起來。如今的javascript和java、python同樣,能夠操做I/O、操做數據庫、或者其餘各種操做系統資源。python

 


上面這張圖,和下面的這張圖很像。能夠認爲,node.js是javascript的一種跨平臺運行在主機的實現。webpack

 

環境搭建
下載node.js (運行環境)web

https://nodejs.org/en/

下載Visual Studio Code(開發環境)

https://code.visualstudio.com/

npm介紹
寫過Java的同窗應該都知道,咱們要編寫程序每每都須要導入不少其餘額外的JAR包(官方的JavaSE包默認提供了)。早期在Maven出現以前,咱們都是須要手動去下載各類框架的JAR包。自從有了Maven以後,咱們再也不須要手動下載了,直接在一個POM.XML文件中引入須要的依賴便可。


在node中,運行一個node程序也會依賴於其餘的一些模塊。固然node也會自帶一些基本模塊。那當咱們須要使用這些模塊的時候,咱們須要從網絡上下載。這個去網上下載很是麻煩。node官方提供了一個管理工具npm,這個工具能夠根據須要自動從服務器下載各類包。這就省去了,咱們本身去網上下載包的過程。

npm淘寶鏡像
官方的npm在國內速度是比較慢的,可使用淘寶的鏡像

npm install -g cnpm --registry=https://registry.npm.taobao.org

安裝完成後,就可使用cnpm從淘寶鏡像來下載、安裝node包

使用cnpm安裝包
cnpm install <包的名稱>

包的名稱能夠去https://npm.taobao.org/上搜索

node.js模塊化程序結構
每個js文件就是一個模塊(json等其實也能夠做爲一個模塊),對應的就是一個module對象。下面這一段程序,表示從外部引入一個模塊,而後執行模塊中的函數。

var fs = require("fs"); // 引入fs模塊

var data = fs.readFileSync('input.txt'); // 調用fs模塊中的readFileSync方法

console.log(data.toString());
第一行的, required表示引入一個包,返回的就是module對象。這個fs包,是node自帶的包,引入一個包後就能夠調用這個包下的方法。可是包中的方法不是均可以被調用的,只有相似:


exports.world = function() {
   console.log('Hello World');
}
這樣的代碼,才能被調用。更簡單來講,在包中定義的函數都是對外不可見的,要想被外部調用,須要使用exports來定義函數。

 

這個require函數有點相似於C語言中的#include。它首先會從文件cache緩存中查找傳入的模塊名,若是沒有找到再查找原生模塊,最後查找文件中加載。

node.js重要模塊(API)介紹
node.js全局對象
變量名 註釋
__filename 表示當前正在執行的腳本的文件名
__dirname 表示當前執行腳本所在的目錄。
console.log 輸出日誌
node.js原生模塊
模塊名稱 介紹
os模塊 獲取操做系統相關的信息,例如:獲取臨時文件夾,獲取主機名、獲取操做系統名稱
http模塊 提供了開發服務器後端程序的相關API
path模塊 提供了處理文件路徑相關的API
net模塊 提供了網絡編程API
實現一個用戶管理模塊
建立項目

創建一個空的文件夾用於保存該項目

進入命令提示符,使用npm init初始化項目,結束後會自動生成一個package.json文件,這個文件中包含了項目的全部依賴包,能夠把這個package.json文件理解爲項目文件

建立客戶Service模塊


/**
* 客戶Service
*/
exports.CustomerService = function() {
   this.customers = [];

   // 添加客戶
   this.add = function(cstm) {
       this.customers.push(cstm);
  }

   // 根據客戶名字移除
   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;
  }
}
建立入口模塊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())
執行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是一套前端框架。它實現了前端頁面視圖(HTML/CSS)和模型數據的分離,並且它提供了快速簡單構建組件的方式。讓咱們以一種全新的方式來開發前端。

 

基本編程模型(模板 + 模型)
使用Vue指令定義模板

<div id="app">
   <span>
      {{name}}
   </span>
</div>
使用Vue定義數據模型

var app2 = new Vue({
   el: '#app',
   data: { // 定義模型數據
       name: 'Hello, Tom!'
  },
   method: { // 定義綁定數據方法
       sayHello: function() {
           alert('hello!');
      }
  }
})
經常使用指令介紹
指令 用途
{{模型名稱}} 插值,綁定模型數據(單向綁定)
v-bind:標籤屬性,能夠縮寫爲:標籤屬性 綁定模型數據到HTML標籤的屬性
v-if 條件判斷
v-for="item in list" foreach循環
v-on:click,能夠縮寫爲@click 綁定用戶事件
v-model 綁定表單數據
指令.修飾符 .number(將輸入的數據轉換爲數字)、.trim(去除輸入的數據後面的空格)
詳細語法參見:https://cn.vuejs.org/v2/guide/

組件化開發
在前端開發中引入組件化是一個大的進步。其實,若是咱們用過一些UI框架就會知道,大多數的UI框架都定義了不少的組件,例如:button按鈕、datagrid表格組件、tree樹形組件、dialog對話框組件等等。可是,以前咱們都是使用別人給咱們開發好的框架。咱們今天要學習如何使用Vue來開發一個本身的組件。未來,咱們能夠本身開發一套本身的組件庫,而後使用這些組件庫來構建咱們的前端應用程序。

組件結構
能夠把組件理解爲就是一個小的頁面視圖。使用Vue開發的組件也分爲兩個部分:

視圖模板

屬性(模型數據)

視圖模板依舊是使用HTML/CSS+Vue指令,可是模型數據如今跟以前不太同樣,模型數據應該是使用組件的時候,動態傳入進來的。因此,模型數據須要先定義出來。

 

實現一個購物車程序

<!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>購物車</title>
   <link rel="stylesheet" href="./bootstrap/css/bootstrap.css">
</head>
<body>
   <div id="app" class="container">
       <h1>購物車</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>商品價格</th>
               <th>商品數量</th>
               <th>商品總價</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">總價:</td>
               <td class="text-primary">{{getTotalMoney()}}</td>
           </tr>
       </table>
   </div>
   <script src="./vue.js"></script>
   <script>
       // 自定義組件,這裏實現了一個按鈕組組件
       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: {
               // 按鈕組件測試
               buttons_test: [
                  {title: '測試1', class: 'btn-danger'},{title: '測試2'},{title: '測試3'},{title: '測試4'},
              ],
               buttons: [{
                   title: '添加',
                   class: 'btn-primary',
                   handler: function() {
                       alert('點擊添加按鈕');
                  }
              }, {
                   title: '修改',
                   class: 'btn-default',
                   handler: function() {
                       alert('點擊修改按鈕');
                  }
              }, {
                   title: '刪除',
                   class: 'btn-default',
                   handler: function() {
                       alert('點擊刪除按鈕');
                  }
              }, ],
               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: {
               // 用戶點擊加減數量時調用
               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構建前端工程化
webpack介紹
webpack是一個前端項目構建工具。使用webpack能夠把前端當成一個工程來開發。並且可以很好地把前端的各種資源統一管理、編譯、打包。

它是一個「編譯器」,能夠經過各類插件將基於node.js、sass、less編寫代碼編譯成可以運行在前端瀏覽器的javascript、和css

它是一個打包工具,能夠將全部前端的資源打包到一個bundle.js中

有了webpack,咱們能夠像開發後端應用同樣開發前端。

整體結構圖


webpack是基於node.js開發的一款應用,其實webpack就是一個node.js的模塊。

 

安裝webpack
建立一個空的文件夾

使用npm init建立package.json

安裝cnpm淘寶鏡像

使用cnpm install vue-cli -g全局安裝vue-cli模塊

使用vue init webpack cart建立基於webpack購物車項目

使用cnpm install bootstrap --save安裝bootstrap模塊

具體步驟請參考:https://www.webpackjs.com/guides/installation/

使用webpack重構購物車程序
使用vue-cli生成項目腳手架以下圖:

 

將原來編寫的btn-grp組件單獨編寫到BtnGrp.vue文件中

能夠看到如今代碼清晰了不少,template標籤部分編寫模板,script標籤部分編寫組件的交互代碼,編寫方式和原先寫在HTML的代碼一致

如今整個前端應用都是基於組件化的,代碼變得更加清晰了


<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中的代碼重構到App.vue中

此處由於須要用到BtnGrp組件,因此須要先import 組件,而後在components中引用該組件


<template>
   <div id="app" class="container">
       <h1>WEBPACK + VUE&nbsp;實現購物車</h1>
       <BtnGrp :buttons="buttons"></BtnGrp>
       <br/>
       <br/>
       <table class="table table-bordered table-striped table-hover">
           <tr>
               <th>ID</th>
               <th>商品名稱</th>
               <th>商品價格</th>
               <th>商品數量</th>
               <th>商品總價</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">總價:</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('點擊添加按鈕');
        }
    }, {
         title: '修改',
         class: 'btn-outline-primary',
         handler: function() {
             alert('點擊修改按鈕');
        }
    }, {
         title: '刪除',
         class: 'btn-outline-danger',
         handler: function() {
             alert('點擊刪除按鈕');
        }
    }, ],
     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>
由於npm安裝的bootstrap是bootstrap4,因此稍微對原先的樣式調整了下。最終的效果圖以下:

 

.

相關文章
相關標籤/搜索