这篇文章主要整理一下WebPack、Vue-CLI、ElementUI、Axios这些前后端分离中一定会用到的知识点
0.引言
上一篇文章前后端分离:前导——后端程序员能看懂的VUE整理了一些Vue的基本语法和知识点,在搬砖的过程中后端程序员不至于看不懂前端的代码;这篇文章将继续整理前后端分离所需要的知识点,主要分为WebPack、Vue-CLI、ElementUI、Axios这几个部分,分别讲述了如何打包程序成为现在市面上浏览器都能看懂的代码、规模化的生产前端代码、高效简洁堪比HTML/CSS/JS时期Bootstrap的神器ElementUI、以及前后端分离最重要的工具Axios。
1.Webpack
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
很多网站都是基于ES5+的,但是Vue是基于ES6+开发的,所以我们就需要一个工具来将ES6+降级为ES5+来满足各浏览器的需要,对详细的教程感兴趣的同学可以移步webpack官网文档,这里我只讲一下最基本的如何将程序打包。
在之前的程序中,如果需要加载一些文件通常会选用<script>直接引用,虽然很方便,但是也有一些显而易见的弊端:
- 全局作用域下容易造成变量冲突;
- 文件只能按照<script>的书写顺序进行加载;
- 开发人员必须主观的解决各模板之间和代码库的依赖关系;
- 在大型项目中各种资源难以管理,长期积累的问题导致代码库混乱不堪。
简单举个例子来说:我在写项目,引入了一个外部的JS文件,但是这个文件的作者使用的变量名称和我的项目中变量名称有冲突,那么这时候的报错怎么查?查出来怎么改?这就是问题。
通过了CommonsJS、AMD、CMD、ES6等标准后,大家希望的模块系统给可以兼容多种模块风格,尽量利用已有的代码,不仅仅是Javascript模块化,还有字体、CSS、图片等资源也要模块化。
安装webpack
webpack作为一款模块加载兼打包工具,可以将各种资源:JS、JSX、ES6、SASS、LESS、图片等都作为模块来处理和使用,使用如下命令安装:
npm install webpack -g
npm insatall webpack-cli -g
测试通过webpack -v和webpack-cli -v来查看是否安装成功:
使用
我们创建一个新的文件夹,名为Webpack-Build,用IDEA打开,接下来我们创建一个module文件夹,用来放置JS文件;现在我们写一个hello.js:
//暴露一个方法
exports.sayHi = function () {
document.write("<div><h1>zijun</h1></div>")
};
这个文件中使用exports来暴露方法sayHi,再写一个main.js:
var hello = require("./hello");
hello.sayHi();
既然有了暴露的方法,那就要有一个地方来引入,在main.js中使用var引入hello.js文件,这样我们就可以使用它的暴露的方法sayHi(),不管hello.js中有多少个方法,只要使用exports暴露就可以在main.js中使用。
接下来就是重点部分:打包。我们在项目目录下建立一个js文件webpack.config.js:
module.exports = {
entry: './modules/main.js',
output: {
filename: "./js/bundle.js"
}
};
这是一个规范的webpack打包代码,exports代表需要导出;entry是入口,代表程序打包好之后的入口;output代表打包之后的输出,filename为输出位置;总的来说就是从main.js开始将代码打包,打包输出到bundle.js,在控制台输入:webpack,等待程序运行完毕就会在项目目录下发现dist文件夹,打开就会看到js文件夹,里面就是我们的bundle.js文件:
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){n(1).sayHi()},function(e,t){t.sayHi=function(){document.write("<div><h1>zijun</h1></div>")}}]);
这时如果需要使用hello.js或者main.js就不需要引入这两个文件,直接引入bundle.js即可,建一个Index.html来检测一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="dist/js/bundle.js"></script>
</body>
</html>
可以正常打开:
并且在控制台如果没有关闭进程,那么在修改代码的时候bundle.js也会睡着我们的修改内容为之改变,也就是热部署。
2.Vue-CLI
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供:
- 通过
@vue/cli
实现的交互式的项目脚手架。 - 通过
@vue/cli
+@vue/cli-service-global
实现的零配置原型开发。 - 一个运行时依赖 (
@vue/cli-service
),该依赖:-
可升级;
-
基于 webpack 构建,并带有合理的默认配置;
-
可以通过项目内的配置文件进行配置;
-
可以通过插件进行扩展。
-
- 一个丰富的官方插件集合,集成了前端生态中最好的工具。
- 一套完全图形化的创建和管理 Vue.js 项目的用户界面。
Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject。
安装
首先我们要安装Node.js,需要8.9或者更高版本,官方推荐的是8.11.0+,安装好后使用node -v和 npm -v来查看版本:
接下来我们需要安装Node的淘宝加速镜像:
npm install cnpm -g
一般我们会选择cnpm来安装其他的东西,因为国内的还是比国外的要快,如果cnpm安装失败则尝试npm,直到安装成功。
接下来我们通过cnpm安装vue-cli:
cnpm install vue-cli -g
安装好后可以使用vue list来查看可以使用哪些模板来创建Vue应用:
第一个Vue-cli程序
安装好后就可以开始建立应用了,找到应用的位置,进入路径,使用vue init webpack myvue来建立一个叫做myvue的vue-cli应用,确定好名称(名称不能有大写)和作者后,其余的选项全部选择no就可以建立一个空白的基于webpack的vue-cli应用程序,安装好后的文件夹就变成了这样:
可以看到我的多了一个node-config文件夹,接下来需要初始化就可以得到这个文件夹,继续在命令行输入:
cd myvue
npm install
npm run dev
分别是,进入刚才建立的myvue文件夹、安装初始化、运行,全部成功后我们会看到一个界面:
这时就可以在浏览器中输入localhost:8080,如果看到下面的界面,说明成功的创建了第一个vue-cli程序:
这时我们通过IDEA打开myxue文件夹,就可以看到我们的第一个vue-cli程序的内容了:
components文件夹是放置组件的,APP.vue用来展示模板,main.js用来绑定APP.vue,这些是基本配置。
路由
我们有了vue-cli后就可以来学习一下路由,基于刚才的应用,我们删除logo.png、HelloWorld.vue,并且将APP.vue和main.js中有关HelloWorld.vue的代码删除,现在你就得到了一个空白的Vue应用程序。
在后端我们要进行页面跳转时,只需要进行转发或者重定向就可以了,而在前端集成时,就要通过路由来进行处理:Vue Router是Vue的官方路由管理器,和Vue.js核心深度集成,让构建页面变得易如反掌。
vue-router是一个插件包,所以要使用npm/cnpm来安装的,如果你的node_modules中没有vue-router文件夹,那么就使用下面的命令来安装:
npm install vue-router --save-dev
安装好后就可以来测试了,我们首先建立两个页面,分别是首页main.vue:
<template>
<h1>首页</h1>
</template>
<script>
export default {
name: "main"
}
</script>
<style scoped>
</style>
内容页content.vue:
<template>
<h1>内容页</h1>
</template>
<script>
export default {
name: "content"
}
</script>
<style scoped>
</style>
这时候为了能够实现页面跳转,我们要建立一个路由管理文件夹router,建立一个index.js文件:
//主配置
import Vue from 'vue'
import VueRouter from 'vue-router'
import Content from '../components/content'
import Main from '../components/main'
//安装路由
Vue.use(VueRouter);
//导出
export default new VueRouter({
routes: [
{
//路由的路径
path: '/content',
//还可以起名字
name: 'content',
//跳转的组件
component: Content
},
{
path: '/main',
name: 'main',
component: Main
}
]
});
解释一下,首先我们配置Vue,然后配置路由vue-router,将两个页面import导入,安装路由Vue.use,最后导出路由export,在导出时可以设置路由的路径、路由的名字、跳转的位置;
然后我们在main.js中进行路由的配置:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/index' //自动扫描里面的路由配置
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
//配置路由
router,
components: { App },
template: '<App/>'
})
配置很简单,import导入我们的路由管理文件,然后再Vue对象中加入就可以了;
最后是对入口页面的配置:
<template>
<div id="app">
<h1>Vue-Router</h1>
<router-link to="/main">首页</router-link>
<router-link to="/content">内容页</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</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>
<router-link> 是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容,to 属性为目标地址, 即要显示的内容;使用<router-view>来展示跳转后的内容。
可以看一下最终的效果:
3.Axios
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
安装
使用CDN:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
或者使用npm:
$ npm install axios
生命周期
从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件统称生命周期,而生命周期钩子就是生命周期方法事件的别名。
从官网的图上可以看到,在不同的进度中有不同的钩子函数,主要的生命周期函数分类为:
- 创建期间的生命周期函数:
- beforeCreate:实例刚在内存中被创建出来,此时还没有初始化好data和methods属性;
- created:实例在内存中完成创建OK,此时data和mthods已经创建OK,还没有开始编译模板;
- beforeMount:此时已经完成了模板的编译,但还没有挂载到页面中;
- mounted:此时已经将编译好的模板挂载到了页面指定的容器中显示;
- 运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行函数,此时data中的状态值是最新的,但界面上显示的数据还是旧的,因为还没有重新渲染DOM节点;
- updated:实例更新完后调用此函数,此时data中的状态值和界面上显示的数据都已经完成了更新,界面已经被重新渲染好了;
- 销毁期间的生命周期函数:
- beforeDestroy:实例销毁之前调用,在这一步实例仍完全可用;
- destroyed:Vue实例销毁后调用,调用后Vue实例所指示的所有东西都会解绑定,所有事件监听器会被移除,所有子实例也会被销毁。
使用
因为使用Axios是为了实现异步通信,所以就要有后端传过来的数据,我来模仿后端传来的数据建立一个data.json文件:
{
"name": "zijun",
"age": "18",
"url": "https://blog.csdn.net/qq_39732867",
"page": 1,
"isNotProfit": "true",
"address": {
"street": "安远门",
"city": "西安",
"country": "中国"
},
"links": [
{
"name": "001",
"url": "001"
},
{
"name": "002",
"url": "002"
},
{
"name": "003",
"url": "003"
}
]
}
这段代码就是模仿后端传过来的json数据,包含了布尔值、数字、字符串、数组、对象等类型,现在我们写一个html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="vue">
{{info.name}}
</div>
<script src="../vue/vue.min.js"></script>
<script src="http://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var vm = new Vue({
el: '#vue',
data:{},//这是属性的data
data(){
return{
//请求的返回参数格式必须和JSON字符串一样
info:{
name: null
}
}
},
mounted(){ //钩子函数,链式编程
axios.get('data.json').then(response=>(this.info = response.data));
}
});
</script>
</body>
</html>
我们以mounted函数来举例,在mounted函数中应该写异步请求,Java中是$Ajax,Vue2.0+就是axios,因为是链式编程所以首先使用get方法获取数据获取的是‘data.json’,then表示‘然后’的意思,response就是得到的数据这里可以替换为其他的变量,然后‘=>’得到‘this.info = response.data’;
这时的data()和Vue对象中的data不一样,这里的data()是钩子函数执行后的数据装载,在mounted函数未执行时,info.name的值仍为null,mounted函数执行后,获取了data.json的数据response.data,data()更新并渲染,这时效果如下:
分别给出get方法和post方法:
//get
<body>
<div id="app">
{{ info }}
</div>
<script type = "text/javascript">
new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.get('json_demo.json')
.then(response => (this.info = response.data))
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
})
</script>
</body>
//post
<body>
<div id="app">
{{ info.data.name }}
</div>
<script type = "text/javascript">
new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.post('demo_axios_post.php')
.then(response => (this.info = response))
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
})
</script>
</body>
4.ElementUI
最后说起前端页面怎么画,大家第一时间想到的应该是BootStrap,但是ElementUI更加与Vue兼容:
可以通过npm安装:
npm i element-ui -S
或者使用CDN:
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
这时我们随便找一些组件:
可以看到已经完全使用Vue的方式才能看的懂了,这就是技术更新啊朋友们,因为组件是模板,所以是可复用的,需要时只需要通过slot插入就可以用,就很棒,现在我们来做一个实例:
首先创建一个新的Vue-cli应用,进行一些文件的创建:
这时先写Login.vue:
<template>
<div>
<el-form ref="loginForm" :model="form" :rules="rules" label-width="80px " class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="账号" prop="username">
<el-input type="text" placeholder="请输入账号" v-model="form.username"/>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" placeholder="请输入密码" v-model="form.password"/>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
</el-form-item>
</el-form>
<el-dialog
title="温馨提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>请输入账号和密码</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
username: '',
password: ''
},
//表单验证,需要在el-form-item元素中增加prop属性
rules: {
username: [
{required: true, message: '账号不可为空', trigger: 'blur'}
],
password: [
{required: true, message: '密码不可为空', trigger: 'blur'}
]
},
//对话框显示和隐藏
dialogVisible: false
}
},
methods: {
onSubmit(formName) {
//为表单绑定验证功能
this.$refs[formName].validate((vaild) => {
if (vaild) {
//使用vue-router 路由指导到指定页面,该方式称为编程式导航
this.$router.push("/main");
} else {
this.dialogVisible = true;
return false;
}
});
}
}
}
</script>
<style lang="scss" scoped>
.login-box {
border: 1px solid #DCDFE6;
width: 350px;
margin: 180px auto;
padding: 35px 35px 15px 35px;
}
</style>
然后是Main.vue:
<template>
<h1>首页</h1>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
</style>
写好后顺便配个路由:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Main from '../views/Main'
import Login from '../views/Login'
Vue.use(VueRouter);
export default new VueRouter({
routes: [
{
path: '/main',
name: 'main',
component: Main
},
{
path: '/login',
name: 'login',
component: Login
}
]
});
然后是main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/index'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(router);
Vue.use(ElementUI);
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
最后配一下APP.vue:
<template>
<div id="app">
<router-link to="/login">login</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
看一下效果:
这里一直出现login是因为我们在APP.vue的模板中就写下了router-link,而其他的内容都是在router-view中显示的,所以只需要将router-link放在Main.vue中就可以了。
这篇文章简单整理了一下前后端分离会遇到的知识点,包括webpack、vue-cli的使用,axios进行异步加载数据,ElementUI进行前端页面的开发,这些都是前后端分离过程中会用到的,当然作为后端工程师只需要了解会用就可以了【笑~】,接下来就可以尝试使用前后端分离来写项目了,我们下次见👋