前言
一眨眼就是100天, 距离上次更次文章已经是三个月前的事了😂,惰性大于自觉了这三个月实在是颓废,再加上工作上稍微有些忙,就把是不是更新文章的习惯给搁置掉了,虽然文笔技术都不咋地,最起码习惯还是好的,在不动动我恐怕是要废了,刚好今天有空把之前完成一大半的东西,删删改改的整理出来,给大家分享一下;
这篇文章其实就是我之前后端项目的前端管理系统,如果大家有兴趣可以去看看 koa+mysql 项目实战 前端项目地址在这里 👉 点我跳转
为什么我不去实现客户端系统而去实现管理后台呢?😥其实有些事情并不是你想咋样就咋样的,开始的时候我以为会了Node
会了 Vue
我就可以自己写项目了(求轻喷),不用再像刚学习前端的时候再某宝,某鱼看到的课一样,没有后端地址全是自己 mock
,其实不然,自己做项目最大的难度是造数据,数据从何来,况且客户端对数据的要求还是比较高的,要想做出来看的过去并不是随随便便弄点就可以了,我没有那个耐心也没有那个精力 so 就先做了后台管理。
项目预览
说了这么久嘴都干了,先给掘友们看看这个管理系统大致长什么样子
项目结构
目录结构是仿 vue-element-admin
设计的,不得不说大佬就是大佬很强,大部分文件夹应该一眼就能看出来是用来放什么的,下面就列举一些不好确认和分辨的
libs
:放了一些工具方法,请求二次封装的layout
:除去中心的表格区域的其他区域内容plugins
:目前里面就是按需引入的element
后续可以放一些其他三方插件
项目重点
开始重要环节,半斤教八两😂,我敢讲看你敢听不?
国际化
Vue
项目的国际化主要是靠 i18n
这个插件 👉 这里 ,大家可以把代码 clone
下来看一下 local
文件夹;我这边的做法是把中英文分别维护然后在一个文件里面整合,最后放到 main.js
中去注册这个插件;
// 目录:local/lang/en-US.js
export default {
button: "button"
}
// 目录:local/lang/zh-CN.js
export default {
button: "按钮"
}
// local/index.js
// 先把插件导入进来
import Vue from "vue";
import VueI18n from "vue-i18n";
// 国际化内容导入进来
import customZhCn from "./lang/zh-CN";
import customUsEn from "./lang/en-US";
// element 按需加载就要这样搞,官网有写
import enLocale from "element-ui/lib/locale/lang/en";
import zhLocale from "element-ui/lib/locale/lang/zh-CN";
import ElementLocale from "element-ui/lib/locale";
Vue.use(VueI18n);
// 这里是获取浏览器的语言
const navLang = navigator.language;
// 如果有就用浏览器的没有就是一个 false
const localLang = navLang === "zh-CN" || navLang === "en-US" ? navLang : false;
let lang = localLang ? lang = localLang : "zh-CN";
// 把语言对象都合并一下
const messages = {
"zh-CN": Object.assign(zhLocale, customZhCn),
"en-US": Object.assign(enLocale, customUsEn)
};
const i18n = new VueI18n({
locale: lang,
messages
});
// element 官网操作
ElementLocale.i18n((key, value) => i18n.t(key, value));
// 暴露出去最后在main.js中去注册
export default i18n;
在使用的时候,比如我们要使用 button
在模板中就是 {{ $t('button') }}
在脚本中就是 this.$t('button')
递归侧边栏
在 /layout/Sidebar/index.vue
中把 路由信息传递到 sidenar-item
组件中
<sildebar-item
v-for="route in routes"
:key="route.path"
:item="route"
:base-path="route.path"
></sildebar-item>
用到递归的代码在 /layout/Sidebar/SidebarItem.vue
中;这里我把代码 copy
出来一份,去掉与递归无效的加上注释讲解;
<template>
<!-- hide其实是路由信息用来判断这个是否显示 -->
<div v-if="!item.hide">
<!-- 这里乍一看可能比较晦涩没关系,咱们先看方法 methods
1, 有children并且没有hide的时候 返回 true
2, showingChildren的length为0的时候 true
3, 以上两种情况的前提都是 isHasOneChild 会返回 true
4, 一直循环到没有children了就进去else阶段
-->
<template
v-if="
isHasOneChild(item.children, item) &&
(!onlyOneChild.children || onlyOneChild.noShowingChildren)
"
>
<!-- 条件成立一直执行这里的代码 -->
<el-menu-item :index="resolvePath(onlyOneChild.path)"></el-menu-item>
</template>
<el-submenu v-else :index="resolvePath(item.path)">
<!-- 本质就是自己调用自己,但是要记得组件必须有name属性
5, else 这里呢又是调用了自己,并且是一个循环,所以就会一直递归的调用循环数据以及children,知道全部走一遍为空的时候,终止了
-->
<sidebar-item
v-for="child in item.children"
:key="child.path"
:item="child"
:base-path="resolvePath(child.path)"
/>
</el-submenu>
</div>
</template>
<script>
import { isExternal } from "@/libs/util";
export default {
name: "SidebarItem",
props: {
// route object
item: {
type: Object,
required: true
},
basePath: {
type: String,
default: ""
}
},
data() {
return {
onlyOneChild: {}
};
},
methods: {
// 接口子路由数组和路由item
isHasOneChild(children = [], route) {
const showingChildren = children.filter(item => {
if (item.hide) {
return false;
} else {
this.onlyOneChild = item;
return true;
}
});
// 如果 children 只有一个 默认显示 children
if (showingChildren.length === 1) {
return true;
}
// 如果没有 children 显示自身
if (showingChildren.length === 0) {
this.onlyOneChild = { ...route, path: "", noShowingChildren: true };
return true;
}
return false;
// 总结:
// 1, 子路由(children)有 hide 返回 fasle
// 2, 子路由(children)没有 hide 返回 true 并且把 路由信息赋值给 onlyOneChild
// 3, showingChildren的length为1 是 true
// 4,showingChildren的length为0 是 true 但是给 onlyOneChild 又赋值了
},
resolvePath(routePath) {
if (isExternal(routePath)) {
return routePath;
}
if (isExternal(this.basePath)) {
return this.basePath;
}
return path.resolve(this.basePath, routePath);
}
}
};
elementTable 二次封装
table的二次封装主要实现,就是接收一个对象,在初始化的时候,给 table
把基本的默认值设置上 ,如果外部传递过来的参数有变化,就用外部的,并且把 pagination
组件所需要的参数也和 table
进行合并封装,这样下次用的时候,就默认会带分页功能了,组件内部暴露一些方法,在传递数据,或者数据更改之后调用此方法更新 table
内容;大家可以看一下代码,个人感觉注释很详细的😂 /components/proTable/index.vue
/components/proTable/Pagination.vue
项目启动
由于这个项目是个纯前端项目没有 mock
所以掘友们如果想启动恐怕,还要去把我那个后端项目一块 clone
下来,强烈建议先启动后端,自己随意创建几条数据,然后再启动前端;
前端启动的时候注意修改一下 vue.config.js
文件中的代理地址;然后执行前端项目启动两件套 npm install
npm run serve
最后感觉掘友观看,并自觉点赞 手动滑稽 完结撒花!!!