Vue实战狗尾草博客后台管理系统第一章

这里准备采用的技术栈为:vue全家桶+element-ui 这里因为是后台管理系统,没有做SSR的必要。所以这里就采用前后端分离来昨晚这个项目~

项目搭建

    vue init webpack gwc_manage
复制代码

初始化过程中,会让我们进行一些依赖包,项目配置的基本选择。项目名称,作者信息,描述,是否安装路由,eslint,测试单元,npm/yarn。 这里不选择安装eslint和测试单元。用过的人应该知道非常酸爽。 项目初始化成功后,

npm run dev
复制代码

可以看到项目成功运行在8080端口。我么就可以打开8080端口查看我们搭建好的项目 image-20190513171201664.png 上图所述,就是vue初始化后的页面。

安装less并配置全局的变量

    npm install less less-loader -s
复制代码

注:后面的-s表示本地安装-g表示全局安装,不些则表示默认本地安装 因为使用了less后,个人一般喜欢将整个项目的配色进行一个管理。所以需要进行全局的配置。 这里安装完成后,继续安装

npm install sass-resources-loader --save-dev
复制代码

接下来,我们找到build文件夹下的utils文件 exports.cssLoaders = function (options) {}中加上一下代码:

function lessResourceLoader() {var loaders = [cssLoader,'less-loader',{loader: 'sass-resources-loader',options: {resources: [path.resolve(__dirname, '../src/assets/styles/common.less'),]}}];if (options.extract) {return ExtractTextPlugin.extract({use: loaders,fallback: 'vue-style-loader'})} else {return ['vue-style-loader'].concat(loaders)}
}
复制代码

注意位置一定要加对,且记得把path.resolve(__dirname,'../src/assets/styles/common.less')路径改成自己对应的文件。然后后面将 return{} 块中的 less: generateLoaders('less') 替换成上面自定义的函数 less: lessResourceLoader(); 修改完配置文件记得重启服务器:npm run dev 给大家上图看一下主要配置: image-20190513172125756.png

重启服务后,基本就配置完成。不过我们还是的检测一下。 在common.less中写入:

    @bg-blue: #3576e0;
复制代码

在App.vue中修改

<style lang="less" scoped>
#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;background-color: @bg-blue;
}
</style>
复制代码

然后保存,打开浏览器。就可以看到我们配置好的全局变量被成功引用 image-20190513172403241.png

背景色变成蓝色。说明在common.less中定义的变量被正常调用。这里全局的less配置也就成功了。

引入全局的基本样式

项目搭建好了,但是可以看到一些基本的样式需要我们进行更改

  1. assets文件夹下styles文件中新建base.less文件。百度搜索reset.css然后复制文中的基本样式,并添加html,body宽高为100%即可。

  2. 新建function.less文件css样式工具封装在文中找到适合自己项目的文件复制并粘贴金function.less文件。

  3. 新建index.css文件作为出口文件。文件内容如下:

@import './base.less'; @import './function.less'; 在main.js文件中引入index.css文件

至此引入的基本的样式文件就算被全局引用了。

至于封装的function样式类,我们只需要在需要的时候,选择性的 添加类名即可。

安装element-ui

    npm install element-ui -s
复制代码

安装完成后,在main.js中引入

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);
复制代码

安装完成后,修改App.vue:

<template><div id="app"><img src="./assets/logo.png"><el-button type="danger">测试Element</el-button><router-view/></div>
</template>
复制代码

打开浏览器,我们可以看到button按钮是已经生效了。 image-20190513174650403.png

这里,element-ui也已经安装成功。

请求方法,拦截器,全局加载框的配置

在src文件夹下新建utils文件夹新建http.js为我们的请求方法的文件 image-20190513174918109.png

封装前,我们需要借助axios来作为请求的底层,并且需要缓存机制去缓存登录状态

这里借助两个依赖包 axios和vue-cookies

npm install axios vue-cookies -s
复制代码
  1. 请求方法封装。

    这里封装三个类型的。get请求一个post,json格式的一个post,body格式的一个

import axios from 'axios'
import Vue from 'vue'// 请求方式的配置
export const postJsonRequest = (url, params) => {return axios({method: 'post',url: url,data: params,headers: {'Content-Type': 'application/json',},});
}
export const postRequest = (url, params) => {return axios({method: 'post',url: url,data: params,transformRequest: [function (data) {let ret = ''for (let it in data) {ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'}return ret}],headers: {'Content-Type': 'application/x-www-form-urlencoded'}});
}export const getRequest = (url, data = {}) => {return axios({method: 'get',params: data,url: url,});
}
复制代码

这个就是请求方法的配置

随后我们在utils目录下新建index.js文件作为工具文件夹的出口文件

utils>index.js:

引入封装的http请求并挂在到Vue原型链上供全局使用

import * as http from './http';const install = (Vue, opts = {}) => {if (install.installed) return;Vue.prototype.$http = http;
}export default install
main.jsimport Utils from './utils';
Vue.use(Utils);
复制代码

这里方法请求的封装就算是完成了。

  1. 拦截器的配置

    拦截器:登录状态的管理,以及每次请求时,我们做的一些处理。对不同code状态做的不同的处理

拦截器分为请求拦截器和响应拦截器。字面意思可理解为:请求时的拦截和响应时的拦截

import axios from 'axios'
import { Message } from 'element-ui'
import router from 'vue-router'
import Vue from 'vue'
import VueCookies from 'vue-cookies'
// 请求拦截
axios.interceptors.request.use(config => {if (VueCookies.isKey('isLogin')) {const token = getToken(config);config.headers['token'] = token;}return config;
}, err => {Message.error({message: '请求超时!'});return Promise.resolve(err);
})// 响应拦截
axios.interceptors.response.use(res => {switch (res.data.code) {case 200:return res.data.result;case 401:Message.error({message: res.data.message});router.push('/login');VueCookies.remove('userinfo');return Promise.reject(res);case 201:Message.error({message: res.data.message});case 403:Message.warning({message: res.data.message});return Promise.reject(res);default:return Promise.reject(res);}}, err => {if (!err.response) {return false;}switch (err.response.status) {case 500:Message.error({message: '服务器出小差了⊙﹏⊙∥'});break;case 504:Message.error({message: '服务器被吃了⊙﹏⊙∥'});break;case 404:Message.error({message: '服务器被吃了⊙﹏⊙∥'});break;case 403:Message.error({message: '权限不足,请联系管理员!'});break;default:Message.error({message: '网络超时'});}return Promise.reject(err);
})
复制代码

Vue拦截器的基本配置也就是以上这些了。下来个人想要实现一个loading的局部加载。就要借助计数器了。

为什么说要做一个计数器?

因为在同一个view中可能会有很多个请求,我们总不可能在一个请求完成后就关闭loading的加载吧?这样显然不合适。所以我们需要计时器去将所有的请求记录起来。然后在所有的请求完成后关闭loading。

//请求时loading配置
var loading;function startLoading() {loading = Vue.prototype.$loading({lock: true,text: "Loading...",background: 'rgba(0, 0, 0, 0.5)',target: document.querySelector('.loading-area') //设置加载动画区域});
}function endLoading() {loading.close();
}
var needLoadingRequestCount = 0;
//开启loading并计数
function showFullScreenLoading() {if (needLoadingRequestCount === 0) {startLoading();}needLoadingRequestCount++;
};
//计数器==0关闭loading
function tryHideFullScreenLoading() {if (needLoadingRequestCount <= 0) return;needLoadingRequestCount--;if (needLoadingRequestCount === 0) {endLoading();}
};
复制代码

loading的依赖在element安装后是直接挂在到了vue的原型链上。我们不再需要做过多处理。这里计数器完成。下来我们只需要在请求的时候调用,在响应的时候或者请求报错的时候调用关闭的方法即可。

需要注意的是要实现局部的加载,我们就需要在响应实现loading的地方添加类型loading-area才可以!!!

http.js所有代码如下:/*** @description 配置网络请求* @author luokaibin chaizhiyang*/
import axios from 'axios'
import { Message } from 'element-ui'
import router from 'vue-router'
import Vue from 'vue'
import VueCookies from 'vue-cookies'axios.defaults.timeout = 300000; // 请求超时5fen//请求时loading配置
var loading;function startLoading() {loading = Vue.prototype.$loading({lock: true,text: "Loading...",background: 'rgba(0, 0, 0, 0.5)',target: document.querySelector('.loading-area') //设置加载动画区域});
}function endLoading() {loading.close();
}
var needLoadingRequestCount = 0;function showFullScreenLoading() {if (needLoadingRequestCount === 0) {startLoading();}needLoadingRequestCount++;
};function tryHideFullScreenLoading() {if (needLoadingRequestCount <= 0) return;needLoadingRequestCount--;if (needLoadingRequestCount === 0) {endLoading();}
};// 请求拦截
axios.interceptors.request.use(config => {showFullScreenLoading();if (VueCookies.isKey('userinfo')) {const token = getToken(config);config.headers['token'] = token;}return config;
}, err => {tryHideFullScreenLoading();Message.error({message: '请求超时!'});return Promise.resolve(err);
})// 响应拦截
axios.interceptors.response.use(res => {tryHideFullScreenLoading();switch (res.data.code) {case 200:return res.data.result;case 401:Message.error({message: res.data.message});router.push('/login');// VueCookies.remove('userinfo');return Promise.reject(res);case 201:Message.error({message: res.data.message});case 403:Message.warning({message: res.data.message});return Promise.reject(res);default:return Promise.reject(res);}}, err => {tryHideFullScreenLoading();if (!err.response) {return false;}switch (err.response.status) {case 500:Message.error({message: '服务器出小差了⊙﹏⊙∥'});break;case 504:Message.error({message: '服务器被吃了⊙﹏⊙∥'});break;case 404:Message.error({message: '服务器被吃了⊙﹏⊙∥'});break;case 403:Message.error({message: '权限不足,请联系管理员!'});break;default:Message.error({message: '网络超时'});}return Promise.reject(err);
})// 请求方式的配置
export const postJsonRequest = (url, params) => {return axios({method: 'post',url: url,data: params,headers: {'Content-Type': 'application/json',},});
}
export const postRequest = (url, params) => {return axios({method: 'post',url: url,data: params,transformRequest: [function (data) {let ret = ''for (let it in data) {ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'}return ret}],headers: {'Content-Type': 'application/x-www-form-urlencoded'}});
}export const getRequest = (url, data = {}) => {return axios({method: 'get',params: data,url: url,});
}
复制代码

至此整个的全局loading,拦截器,fetch方法的封装就算完成了。

总结

  1. element-ui的使用,我们要多借助官方文档去灵活使用。而不是死记硬背。太多的ui框架,再强的大脑也背不过来,何况,为了自己的头发着想一下啦~

  2. 这里并未设置跨域访问。大家可以根据vue的代理。这样也是可以进行跨域访问的。详见我的这篇博文Vue设置代理进行跨域访问,不过这篇文章是针对vue3.0设置,2.0的设置文件,为config下的index.js文件。当然前提是后端接口也进行跨域的设置,否则单纯的前端设置是没有作用的。

  3. 局部loading的使用,要求有一个好的布局基础。否则,在后期的使用过程中,会有喝多样式错乱的问题。

  4. 请求方式有很多种,还有下载文件的请求配置,delete,post,put等等大家可根据自己需求灵活配置。最终的使用this.$http. get/post/put/...等等就可以进行调用

下一章节:

底层布局(Layout),路由(Router),状态库(vuex),Github仓库关联。

敬请期待~

Vue实战狗尾草博客后台管理系统相关推荐

  1. Vue实战狗尾草博客后台管理系统第三章

    Vue实战狗尾草博客后台管理系统第三章 Vue实现狗尾草博客后台管理系统第三章 本章节,咱们开发管理系统侧边栏及面包屑功能. 先上一张效果图 样式呢,作者前端初审,关于设计上毫无美感可言,大家可根据自 ...

  2. Vue实战狗尾草博客后台管理系统第七章

    Vue实战狗尾草博客后台管理平台第七章 本章内容为借助模块化来阐述Vuex的进阶使用. 在复杂项目的架构中,对于数据的处理是一个非常头疼的问题.处理不当,不仅对维护增加相当的工作负担,也给开发增加巨大 ...

  3. Vue实战狗尾草博客管理系统第二章

    Vue实战狗尾草博客后台管理系统第二章 本章主要内容如下:底层布局,路由配置,github仓库推送关联. 关联GitHub仓库 > 关联建立在github已创建账号的基础上 复制代码 登录自己的 ...

  4. Vue实战狗尾草博客管理系统第一章

    Vue实战狗尾草博客管理系统第一章 Vue实战狗尾草博客后台管理系统第一章 这里准备采用的技术栈为:vue全家桶+element-ui 这里因为是后台管理系统,没有做SSR的必要.所以这里就采用前后端 ...

  5. Vue实战狗尾草博客管理平台第六章

    Vue实现狗尾草博客后台管理系统第六章 本章节内容 文章列表 文章详情 草稿箱 文章发布. 本章节内容呢,开发的很是随意哈,因为多数就是element-ui的使用,熟悉的童鞋,是可以很快完成本章节的内 ...

  6. Vue实战狗尾草博客管理平台第四章

    本章主要内容如下: 填补上期的坑. iconfont仓库的关联,引入. 开发登录页面 填坑 上期中我们功能都已正常使用.但不知道有没有小伙伴测试过error页面,当访问地址不存在时,路由是否能正常挑战 ...

  7. Vue实战狗尾草博客管理平台第五章

    本章主要内容如下: 静态资源服务器的配置.学会如何使用静态资源服务器引入静态资源.并给大家推荐一个免费可使用的oss服务器~ 页面的开发由于近期做出的更改较大.就放在下一篇中. 静态资源服务器 静态资 ...

  8. 个人博客后台管理系统

    博客后台管理系统 博客后台管理系统背景介绍 一.项目介绍 1.1 登录 1.2 文章管理页 1.3 撰写文章页 1.4 文章分类页 1.5 用户管理页 1.6 管理员添加页 1.7 博主个人信息页 二 ...

  9. 使用react全家桶制作博客后台管理系统

    前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基于react全家桶(React.React-r ...

最新文章

  1. 嵌入式linux应用程序升级,基于嵌入式Linux平台的应用升级机制的研究与设计
  2. 微信小程序如何搭建本地环境开发
  3. 世界领先!详解蚂蚁金服自研数据库OceanBase的高可用及容灾方案
  4. Cocos2d-x使用iOS游戏内付费IAP(C++篇)
  5. 【BZOJ1146】【CTSC2008】网络管理 [整体二分]
  6. Android取消EditText自动获取焦点默认行为
  7. 复现经典:《统计学习方法》第15章 奇异值分解
  8. ai快捷键常用表_遇到这些办公软件快捷键赶集收藏-mark 视频剪辑|办公软件...
  9. intel CPU详解
  10. L1-052 2018我们要赢 (5 分)—团体程序设计天梯赛
  11. python ocr 识别 开源_OCR识别-python版(一)
  12. 利用DiskGenius对硬盘无损分区大小调整+无损分割新分区。
  13. ARM开发软件ADS教程
  14. L1-030 一帮一 (15分) “一帮一学习小组”是中小学中常见的学习组织方式,老师把学习成绩靠前的学生跟学习成绩靠后的学生排在一组。本题就请你编写程序帮助老师自动完成这个分配工作,即在得到全班学生
  15. 轻松一下,做到题目吧。
  16. 无密码登陆的ssh和ssh-agent
  17. Centos 7 下joomla简体中文版安装
  18. 囊括七大主流搜索引擎 这个网站统计工具神了!
  19. SAP小技巧 DOCKING容器解决分辨率问题
  20. linux grep搜索不到内容的解决

热门文章

  1. python递归详解+汉诺塔小案例_汉诺塔,python递归实现解法步骤
  2. Android性能优化典范第二季
  3. 【RxSwift】flatMapLatest、 Error事件中断序列
  4. Flutter开发之路由跳转与传参(七)
  5. Effect Java 学习笔记-对象的创建与销毁
  6. 网上的说TB6560存在的问题
  7. 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图
  8. Android进程保活
  9. 嗷嗷嗷,kuangbin大大博客上拉的题
  10. R语言基本操作函数(1)变量的基本操作