第一天,准备好项目,先创建一个项目 vue create vue2pro 这里因为我是新手选择的是vue2,然后把目录中默认的一些文件不需要的删除,然后这个项目我放在gitte上,这里说下我是先再本地创建的git init 然后就去gitte官网创建一个仓库,然后再本地与远程连接起来,刚创建的时候是有命令提示的,照着那个来做就行,但一般的新手有可能会有一些报错,去网上搜哈,都是这样走过来的。
然后开始搭建页面和路由,搭建再views里面准备每一个大的路由准备每一个文件夹,然后再router里面配置路由 准备base.css 把默认重置样式都准备好
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}ul,
ol {
list-style: none;
}a {
text-decoration: none;
}img {
vertical-align: middle;
}
简单准备一下,再页面上看一下效果就行,准备一些要用的插件,这里主要是用的element-ui axios querystring ,可以去看官网https://element.eleme.cn/#/zh-CNs 这个是中国的地址,它默认地址再外网,跟GitHub一样,然后就说echarts,因为要用一些图标,非常的好用
在本次项目中要用到很多组件,其中布局有他的layout,但我觉得不咋样不如自己写的,在做侧边栏导航要用的组件的NavMenu导航侧栏,其中如果我们要修改样式,他的里面有一些可以修改,有一些就要我们自己强行去修改,刚开始的小伙伴应该看到了,比如给你这个el-xxxx 标签加个class,有的压根就不理你,虽然你写上去,但是优先级低,可以直接在页面检查获取他的class 在修改的时候加个/deep/ 穿透,非常好用,实在不行在来个!important 这直接上梁山。这里面的组件很多很多,有兴趣的小伙伴可以好好看看
然后主要的就是接口,我是准备一个api文件, 里面创建一个index.js 这里我准备了一个处理不同接口报错的问题,request.js ,然后再这个js文件里面写一个axios,然后暴露出来,导入就可以用了
接下来说下echarts图标
中间echarts图表
实现静态布局
使用echarts
第一步:安装
npm install echarts --save
yarn add echarts
第二步: xx.vue文件中引入
import * as echarts from 'echarts';
第三步: 准备容器
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="left" style="height: 320px"></div>
第四步: 生成图表
为不同的图表封装方法,到mounted生命周期方法中调用
mounted() {
// 画柱状图和折线图
this.drawBarAndLine();
// 画饼图
this.drawPie();
},
发请求拿数据,准备数据
echarts的注意点【面试题】:
1 如果是静态图表,那么就在mounted生命周期中书写代码。
2 如果是动态图表,那么就在created生命周期中写代码。
然后来说下其中的时间处理,其中如果是我们来处理就只能写js代码,但是有现成比如moment
日期格式处理
yarn add moment
import moment from "moment"
注册方法
methods: {
// fn:moment,
// moment:moment,
moment,
// 发请求,拿数据
}
模板中使用
<el-table-column prop="create_time" label="添加时间">
<template slot-scope="scope">
{{ moment(scope.row.create_time).format("YYYY-MM-DD HH:mm:ss") }}
</template>
</el-table-column>
把整个前面布局写完,再使用element-ui 组件的时候有个bug就说他的表格,再点击搜索的时候会出现底部滚动条,主要就说因为的他的样式问题,修改一下
解决产品列表页当左侧菜单收缩时表格不能自动缩放的问题
/deep/.el-table__header,
/deep/.el-table__body {
width: 100% !important;
table-layout: auto;
}
在使用这个页面也有一些问题要处理
删除单条数据之后的页面处理
// 最大的页码数 = 上一次的总数-1 / 每页的条数
let lastPageNum = Math.ceil((this.total - 1) / this.pageSize);
// 当前页
this.pageNum = this.pageNum< lastPageNum ? this.pageNum: lastPageNum ;
this.getProductList(); //重新加载数据
来说说编辑添加的页面这页面的功能有俩好玩的,一个就事上传图片,一个就说下面的富文本
上传组件
<!--
action 必选参数,上传的地址
list-type 文件列表的类型
:on-preview="handlePictureCardPreview" //预览
:on-remove="handleRemove" //删除
-->
<el-upload
:action="$api.upload"
list-type="picture-card"
>
<!-- 加号的图标 -->
<i class="el-icon-plus"></i>
</el-upload>
富文本编辑器
1 安装
yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save
yarn add @wangeditor/editor-for-vue
# 或者 npm install @wangeditor/editor-for-vue --save
2 引入
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
3 注册
components: { Editor, Toolbar },
然后我之前在博客上找到一个很不错的现在没找到
现在components中创建组件wangEditor.vue
代码如下
<template>
<div ref="editor"></div>
</template>
<script>
import E from 'wangeditor';
export default {
props: {
value: {
type: String,
default: '',
},
meanArray: {
// 自定义菜单
type: Array,
default: null,
},
},
model: {
prop: 'value',
event: 'change',
},
watch: {
value: function (value) {
if (value !== this.editor.txt.html()) {
this.editor.txt.html(this.value);
}
},
//value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
},
data() {
return {
// 默认有这么多菜单,meanArray有值以meanArray为准
defaultMeanus: [
'head',
'bold',
'fontSize',
'fontName',
'italic',
'underline',
'strikeThrough',
'indent',
'lineHeight',
'foreColor',
'backColor',
'link',
'list',
'justify',
'quote',
'emoticon',
'image',
'video',
'table',
'code',
'splitLine',
'undo',
'redo',
],
editor: '',
};
},
methods: {
init() {
const _this = this;
this.editor = new E(this.$refs.editor);
this.editor.config.uploadImgShowBase64 = true; // 使用 base64 保存图片
this.setMenus(); //设置菜单
this.editor.config.onchange = (html) => {
_this.$emit('change', html); // 将内容同步到父组件中
};
this.editor.create(); //创建编辑器
},
setMenus() {
// 设置菜单
if (this.meanArray) {
this.editor.config.menus = this.meanArray;
} else {
this.editor.config.menus = this.defaultMeanus;
}
},
getHtml() {
// 得到文本内容
return this.editor.txt.html();
},
setHtml(txt) {
// 设置富文本里面的值
this.editor.txt.html(txt);
},
},
mounted() {
let that = this;
that.$nextTick(function () {
that.init();
});
},
};
</script>
然后再父里面
import Editor from '@/components/wangEditor/wangEditor.vue'
components: { Editor },
这个我是简单来的,自己加到正确的地方
这里我把修改也写在这个页面,这个只需要跳转判断一个条件就行了,比如我们把数据放在vuex里面
修改产品
页面跳转
修改和添加共用同一个页面
1 点击编辑按钮时跳转到编辑页
2 携带当前行数据
1 动态路由
2 本地存储
3 vuex
把当前行的数据存入了vuex
1 store文件夹中新建modules文件夹 ,新建一个product.js
export default {
namespaced: true,
state: {
rowData: {},
tite:"商品添加"
},
getters: {
getRowData(state){
return state.rowData;
}
},
mutations: {
setRowData(state, payload) {
state.rowData = payload
}
},
}
2 store文件夹中的index.js中引入 product.js 并且添加到模块中
// 导入product.js 模块
import product from"./modules/product.js";
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
product,
}
})
然后就是这个页面的导出功能来说下,
导出为excel文件
1 安装插件
npm install -S vue-json-excel
2 注册插件到 vue 实例
main.js
import JsonExcel from "vue-json-excel";
Vue.component("DownloadExcel", JsonExcel);
3 使用
<!--
:data = 数据源 要导出的数据 []
:fields = 中文对照字段, 数据库中的英文字段对应的中文描述
:header="title" 表格的标题
name ="导出的文件名"
-->
<DownloadExcel
:data="ids"
:fields="json_fields"
header="产品列表"
name="产品信息表"
>
<el-button type="primary" size="small" >导出为excel</el-button>
</DownloadExcel>
json_fields:{
// 中文:英文
"商品编号":"id",
"商品名称":"title",
"商品价格":"price",
"商品类目":"category",
"添加时间":"create_time",
"商品卖点":"sellPoint",
"商品描述":"descs",
},
特殊字段的处理
"订单编号":{
field:"code",
callback:value=>{
return ' '+value;
}
},
然后来说下登录和全局路由前置守卫
全局路由前置守卫
/*
to: 即将要访问的路由对象
form:前一个路由对象
next:是一个函数继续执行
*/
router.beforeEach((to, from, next) => {
// 只有登录之后才能访问
console.log("to", to);
console.log("from", from);
if (to.path !== "/login") {
//判断用户是否登录 token ?
let token = localStorage.getItem("userinfo") ? JSON.parse(localStorage.getItem("userinfo")).token : "";
if(token){//如果以已经登录
//放行
next();
}else{//没有登录
router.push("/login")
}
} else {
next();
}
})
权限
要求不同的角色进行不同的操作。
1 可以由后端来实现:
登录之后,后端程序可以知道当前用户的角色,就可以把当前
用户可以做的事情(可以访问的路由信息)返回给前端,前端根据返回的数据
直接生成导航即可。
2 可以由前端来实现:
有点难点。要用到很多技术。
这里我来说个简单的方法,首先把主要的路由复制出来,作为处理数据原
给每个路由加个meta,title为名字,roles为权限
然后根据登录的用户来递归遍历出该用户能访问的页面,如果强行访问则是404页面,这个页面自己准备
const router = new VueRouter({
routes:constRoutes
})
console.log(router.options.routes[0].children);
router.beforeEach((to, from, next) => {
let role = localStorage.getItem('userinfo') ? JSON.parse(localStorage.getItem('userinfo')).role : false
console.log( '1',to);
console.log('2',role);
if (to.path == '/' ) {
next();
} else {
if (to.path !== '/login') {
if(to.path!='/404'&&!to.meta.roles.includes(role)){
console.log('404');
router.push('/404')
}
//登录
let user = JSON.parse(localStorage.getItem('userinfo'))
if (user) {
next()
} else {
router.push('/login')
console.log('要登录');
}
} else {
next()
}
}
})
//判断当前角色是否可以访问当前路由对象
const hasPermission = (item,role) => {
// console.log("当前角色:",item);
// console.log("当前路由对象",role);
if(item.meta && item.meta.roles){
//是否可以访问
return item.meta.roles.includes(role)
}else{
return true
}
}
const caclAccessRoutes = (role,dynamicRoutes) => {
let result = dynamicRoutes.filter((item) => {
if (hasPermission(item,role)) {
//计算当前角色可以访问的子路由
if(item.children){
item.children = caclAccessRoutes(role,item.children) //递归
}
return true
}else{
return false
}
})
// console.log("你能访问的地方result",result);
return result;
}
const calcMenus = (constRoutes,accessRoutes) => {
let menus = [...constRoutes,...accessRoutes].filter(item => item.path !="/login"&&item.path !="/404")
//存入本地
localStorage.menus = JSON.stringify(menus)
// console.log('menus',menus);
return menus
}
export const createDynamicRoutes = () => {
console.log('生成动态路由');
let role = localStorage.getItem('userinfo') ? JSON.parse(localStorage.getItem('userinfo')).role : false
if (!role) {
return;
}
let accessRoutes = caclAccessRoutes(role,dynamicRoutes)
// console.log('你能访问的地方',accessRoutes);
//计算当前的权限
calcMenus(constRoutes,accessRoutes)
}
createDynamicRoutes()
export default router
然后根据不同的用户就可以看见不同的页面了
这是普通用户的看见的页面(测试用的)
如果强制访问就会
但如果是管理员就可以访问所有,不同人有不同人的方法来呈现,左边的显示通过获取可以访问页面的数据来进行遍历
最后一次行展示一些页面吧
总结结束