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

使用webpack+vue.js构建前端工程化
本篇主要介绍三块知识点:

node.js

vue.js

webpack前端工程化

本篇不是写给零基础的同学看的,读者应具备一些服务器开发、前端开发基础

本篇目标
使用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.js基本入门
node.js介绍
node.js可以让javascript程序在后端运行起来。我们之前所熟知的javascript都是运行在前端浏览器,我们编写好了javascript代码后,由浏览器解释执行。而node.js,可以让我们编写javascript,然后在后端运行起来。现在的javascript和java、python一样,可以操作I/O、操作数据库、或者其他各类操作系统资源。

上面这张图,和下面的这张图很像。可以认为,node.js是javascript的一种跨平台运行在主机的实现。

环境搭建
下载node.js (运行环境)

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,所以稍微对原先的样式调整了下。最终的效果图如下:

.

使用webpack+vue.js构建前端工程化的更多相关文章

  1. 公司内部技术分享之Vue.js和前端工程化

    今天主要的核心话题是Vue.js和前端工程化.我将结合我这两年多的工作学习经历来谈谈这个,主要侧重点是前端工程化,Vue.js侧重点相对前端工程化,比重不是特别大. Vue.js Vue.js和Rea ...

  2. Vue.js到前端工程化

    b站视频地址:黑马程序员Vue.js到前端工程化(webpack打包,以及Vue-cli3和Element-UI的使用) vue学习系列 1.vue概述 2.vue基本使用 3.vue模板语法 4.指 ...

  3. 使用 Vuex + Vue.js 构建单页应用

    鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇 vue2.0 下的 vuex 使用方法,传送门:使用 Vuex + Vue.js 构建单页应用[新篇] ------------------ ...

  4. 使用 Vuex + Vue.js 构建单页应用【新篇】

    使用 Vuex + Vue.js 构建单页应用[新篇] 在去年的七月六号的时候,发布了一篇 使用 Vuex + Vue.js 构建单页应用 的文章,文章主要是介绍 vuex 的基本使用方法,发现对大部 ...

  5. Vue.js随笔一(Webpack + Vue.js开发准备,含VNM、NPM、Node、Webpack等相关工具)

    想入门工具是必须的,这一章将向大家带来vue.js相关的程序安装步骤. ①首先你需要有一个NVM(一个非常好用的Node版本管理器): 1.NVM下载地址:https://github.com/cor ...

  6. Vue.js高效前端开发知识 • 【目录】

    持续更新中- 章节 内容 实践练习 Vue.js高效前端开发 • (实践练习) 第1章 Vue.js高效前端开发 • [ 一.初识Vue.js ] 第2章 Vue.js高效前端开发 • [ 二.Vue ...

  7. Vue.js中前端知识点总结笔记

    1.框架和库的区别: 框架:framework 有着自己的语法特点.都有对应的各个模块库 library 专注于一点 框架的好处: 1.提到代码的质量,开发速度 2.提高代码的复用率 3.降低模块之间 ...

  8. webpack4.x + vue2.x 构建前端工程化(1)

    本篇文篇纯属个人笔记,实现工程化打包(用打包后的文件可以正常渲染页面),后续继续更新配置开发环境与生产环境,如果有不合理的地方还望各位指点! 不用脚手架,直接用vue和webpack搭建前端工程化项目 ...

  9. 我们为什么选择VUE来构建前端

    很多使用过VUE的程序员,对VUE的评价是"Vue.js 兼具angular.js和react.js的优点,并剔除了它们的缺点". 那么,他真的值得这么高的评价嘛? Vue.js的 ...

随机推荐

  1. jquery a

    <!DOCTYPE html><html><head><script src="//ajax.googleapis.com/ajax/libs/jq ...

  2. POJ - 1422 Air Raid(DAG的最小路径覆盖数)

    1.一个有向无环图(DAG),M个点,K条有向边,求DAG的最小路径覆盖数 2.DAG的最小路径覆盖数=DAG图中的节点数-相应二分图中的最大匹配数 3. /* 顶点编号从0开始的 邻接矩阵(匈牙利算 ...

  3. sql 指删除表,改表名,改字段名

    删除表: DECLARE @Table NVARCHAR(30) DECLARE tmpCur CURSOR FOR SELECT name FROM sys.objects WHERE TYPE=' ...

  4. Linux系统调用之open(), close() (转载)

    转自:http://joe.is-programmer.com/posts/17463.html open函数可以打开或创建一个文件. #include <sys/types.h> #in ...

  5. bzoj 3830: [Poi2014]Freight【dp】

    参考:https://blog.csdn.net/zqh_wz/article/details/52953516 妙啊 看成分段问题,因为火车只能一批一批的走(易证= =)设f[i]为到i为止的车都走 ...

  6. Luogu P2327 [SCOI2005]扫雷【递推/数学】By cellur925

    题目传送门 推了好久啊.看来以后要多玩扫雷了qwq. 其实本题只有三种答案:0.1.2. 对于所有第一列,只要第一个数和第二个数确定后,其实整个数列就确定了,我们可以通过这个递推式得出 sec[i-] ...

  7. (转载)Python一篇学会多线程

    Python 一篇学会多线程 链接:https://www.cnblogs.com/yeayee/p/4952022.html  多线程和多进程是什么自行google补脑,廖雪峰官网也有,但是不够简洁 ...

  8. [SHOI2002]舞会

    Descriptio 某学校要召开一个舞会,已知有N名学生,有些学生曾经互相跳过舞.当然跳过舞的一定是一个男生和一个女生,在这个舞会上,要求被邀请的学生中任一对男生和女生互相都不能跳过舞.问最多可邀请 ...

  9. 解题报告:hdu 1073 Online Judge

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1073 Problem Description Ignatius is building an Onli ...

  10. Optimizing Downloads for Efficient Network Access

    Optimizing Downloads for Efficient Network Access Previous  Next 1.This lesson teaches you to Unders ...