Vue实战狗尾草博客管理系统第一章
源码地址:https://github.com/18291907191/gwc_manage
Vue实战狗尾草博客后台管理系统第一章
这里准备采用的技术栈为:vue全家桶+element-ui
这里因为是后台管理系统,没有做SSR的必要。所以这里就采用前后端分离来昨晚这个项目~
项目搭建
vue init webpack gwc_manage
这里不选择安装eslint和测试单元。用过的人应该知道非常酸爽。
项目初始化成功后,
npm run dev
可以看到项目成功运行在8080端口。我么就可以打开8080端口查看我们搭建好的项目
上图所述,就是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
给大家上图看一下主要配置:
重启服务后,基本就配置完成。不过我们还是的检测一下。
在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>
然后保存,打开浏览器。就可以看到我们配置好的全局变量被成功引用
背景色变成蓝色。说明在common.less中定义的变量被正常调用。这里全局的less配置也就成功了。
引入全局的基本样式
项目搭建好了,但是可以看到一些基本的样式需要我们进行更改
assets文件夹下styles文件中新建base.less文件。百度搜索reset.css然后复制文中的基本样式,并添加html,body宽高为100%即可。
新建function.less文件css样式工具封装在文中找到适合自己项目的文件复制并粘贴金function.less文件。
新建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按钮是已经生效了。
这里,element-ui也已经安装成功。
请求方法,拦截器,全局加载框的配置
在src文件夹下新建utils文件夹新建http.js为我们的请求方法的文件
封装前,我们需要借助axios来作为请求的底层,并且需要缓存机制去缓存登录状态
这里借助两个依赖包 axios和vue-cookies
npm install axios vue-cookies -s
请求方法封装。这里封装三个类型的。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.js
import Utils from './utils';
Vue.use(Utils);
这里方法请求的封装就算是完成了。
拦截器的配置
拦截器:登录状态的管理,以及每次请求时,我们做的一些处理。对不同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方法的封装就算完成了。
总结
element-ui的使用,我们要多借助官方文档去灵活使用。而不是死记硬背。太多的ui框架,再强的大脑也背不过来,何况,为了自己的头发着想一下啦~
这里并未设置跨域访问。大家可以根据vue的代理。这样也是可以进行跨域访问的。详见我的这篇博文Vue设置代理进行跨域访问,不过这篇文章是针对vue3.0设置,2.0的设置文件,为config下的index.js文件。当然前提是后端接口也进行跨域的设置,否则单纯的前端设置是没有作用的。
局部loading的使用,要求有一个好的布局基础。否则,在后期的使用过程中,会有喝多样式错乱的问题。
请求方式有很多种,还有下载文件的请求配置,delete,post,put等等大家可根据自己需求灵活配置。最终的使用this.$http. get/post/put/...等等就可以进行调用
下一章节:
底层布局(Layout),路由(Router),状态库(vuex),Github仓库关联。
敬请期待~
Vue实战狗尾草博客管理系统第一章的更多相关文章
- Vue实战狗尾草博客管理系统第二章
伙伴们出来啦,探讨各问题,关于项目中大量的表单,大家是怎么处理的? 本章主要内容如下:底层布局,路由配置,github仓库推送关联. 关联GitHub仓库 关联建立在github已创建账号的基础上 登 ...
- Vue实战狗尾草博客后台管理系统第七章
Vue实战狗尾草博客后台管理平台第七章 本章内容为借助模块化来阐述Vuex的进阶使用. 在复杂项目的架构中,对于数据的处理是一个非常头疼的问题.处理不当,不仅对维护增加相当的工作负担,也给开发增加巨大 ...
- Vue实战狗尾草博客后台管理系统第三章
Vue实现狗尾草博客后台管理系统第三章 本章节,咱们开发管理系统侧边栏及面包屑功能. 先上一张效果图 样式呢,作者前端初审,关于设计上毫无美感可言,大家可根据自己情况设计更好看的哦~ 侧边栏 这里我们 ...
- Vue实战狗尾草博客管理平台第六章
Vue实现狗尾草博客后台管理系统第六章 本章节内容 文章列表 文章详情 草稿箱 文章发布. 本章节内容呢,开发的很是随意哈,因为多数就是element-ui的使用,熟悉的童鞋,是可以很快完成本章节的内 ...
- Vue实战狗尾草博客管理平台第四章
本章主要内容如下: 填补上期的坑. iconfont仓库的关联,引入. 开发登录页面 填坑 上期中我们功能都已正常使用.但不知道有没有小伙伴测试过error页面,当访问地址不存在时,路由是否能正常挑战 ...
- Vue实战狗尾草博客管理平台第五章
本章主要内容如下: 静态资源服务器的配置.学会如何使用静态资源服务器引入静态资源.并给大家推荐一个免费可使用的oss服务器~ 页面的开发由于近期做出的更改较大.就放在下一篇中. 静态资源服务器 静态资 ...
- yii2实战教程之新手入门指南-简单博客管理系统
作者:白狼 出处:http://www.manks.top/document/easy_blog_manage_system.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文 ...
- SSM(Spring+Spring MVC+Mybatis)开发前台后功能完整的java开源博客管理系统
项目描述 本项目通过SSM(SpringMVC+Mybatis+Spring)框架编写的一个人博客管理系统,使用hexo主题,以及MAVEN进行对项目管理,并且前端具有粒子和点击爱心效果.后端的页面框 ...
- 一个 Vue + Node + MongoDB 博客系统
源码 耗时半载(半个月)的大项目终于完成了.这是一个博客系统,使用 Vue 做前端框架,Node + express 做后端,数据库使用的是 MongoDB.实现了用户注册.用户登录.博客管理(文章的 ...
随机推荐
- Saltstack_使用指南08_远程执行-返回程序
1. 主机规划 salt 版本 [root@salt100 ~]# salt --version salt (Oxygen) [root@salt100 ~]# salt-minion --versi ...
- [Go] 利用channel实现简单的工作池
先启动固定数量的goroutine,每个goroutine都在从channel中获取数据,如果这个channel为空,就阻塞等待在那里channel中传递一个Car类型,这个类型主要负责具体做的任务也 ...
- [Go] 分页计算页码的主要逻辑
当使用imap进行读取邮件体的时候,有个函数可以根据传入的开始和结束索引来一次读取多条邮件内容主要逻辑类似这样,从1开始, 1,10 11,20 21,30 或者 1,31 32,63 ...
- firewalld基础
firewalld是一个基于网络区域的动态管理防火墙的守护进程.在iptables中需要理解表,链等概念,而在firewalld中需要从理解区域的概念开始 防火墙依照特定的规则允许或限制输出的数据通过 ...
- July 13th, 2018. Friday, Week 28th.
Don't let the mistakes and disappointments of the past control and direct your future. 不要让你的未来被过去的错误 ...
- 【转】springboot结合swagger生成接口文档
前后台分离的开发渐渐已成趋势.那么前后端的沟通就成了问题,包括移动端,web端.如果有一个东西在我们写完代码的时候,自动将接口的所有注释,调用文档提供出来,是不是一件很美好的事情.那就是使用swagg ...
- office 2016 下载链接
[安装环境]:win7/win8/win10 [64位下载] 百度网盘链接:pan.baidu.com/s/1AkiLQtjhayGdx6mw1DQyqw 提取码:qyx9
- Django views 中的装饰器
关于装饰器 示例: 有返回值的装饰器:判断用户是否登录,如果登录继续执行函数,否则跳回登录界面 def auth(func): def inner(request, *args, **kwargs): ...
- hdu 6495 dp
http://acm.hdu.edu.cn/showproblem.php?pid=6495 题意 有n个挑战(1e3),假如接受,在挑战之前体力x会变成min(x,\(b[i]\)),然后会减去a[ ...
- jenkins配置自动部署java程序
任务背景 该项目包含4个程序包:a.jar,b.jar,c.jar,d.jar,每次启动前需要修改程序中的配置文件(修改数据源配置),然后按照先后顺序启动. 任务目标 1.利用jenkins拉取代码, ...