一、Ant Design Pro 介绍
1、访问地址:https://pro.ant.design/zh-CN/
2、开箱即用的中台前端/设计解决方案
二、使用Vue CLI3快速创建项目
1、创建步骤:
vue create ant-design 依据需要选择相应的依赖
cd ant-design 打开项目文件
npm i ant-design moment 安装项目中的依赖,依据moment时间安装
2、自定义Webpack和babel配置
依据 vue CLI 相关 webpack 配置进行对 vue.config.js 进行修改
ant-design-vue 组件库的按需加载 在babel.config.js文件中加入下面代码:
{
"plugins": [
["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
]
}
3、设计一个高扩展性的路由
公共页面设计统一引入 的挂载项 的三种方式:
(1)、通过公共组件的形式引入
Header.vue 组件中:
<template>
<div>
//即将相应的页面在此显示
<router-view></router-view>
</div>
</template>
import Header from '@/src/components/header/index'
export default new Router({
mode:'history',
base:process.env.BASE_URL,
routes:[
{
path:'/user',
component: Header,
children:[
{
path:'/user/login',
name:'login',
component: () => import( /* webpackChunkName: "user" */ '@/src/views/User/Login')
}
]
}
]
})
(2)、通过render函数的形式引入
export default new Router({
mode:'history',
base:process.env.BASE_URL,
routes:[
{
path:'/user',
component: { render: h => h('router-view')},
children:[
{
path:'/user/login',
name:'login',
component: () => import( /* webpackChunkName: "user" */ '@/src/views/User/Login')
}
]
}
]
})
(3)、通过layout文件的形式引入带样式的 挂载项
新建的layout 文件夹中的 index.vue 组件 书写样式
<template>
<div>
//即将相应的页面样式在此显示
<div> Ant Design Vue</div>
<div>公用头部样式</div>
<router-view></router-view>
</div>
</template>
import Header from '@/src/components/header/index'
export default new Router({
mode:'history',
base:process.env.BASE_URL,
routes:[
{
path:'/user',
component: () => import( /* webpackChunkName: "layout" */ '@/src/layout/index'), //异步加载组件内容
children:[
{
path:'/user/login',
name:'login',
component: () => import( /* webpackChunkName: "user" */ '@/src/views/User/Login')
}
]
}
]
})
4、实现一个可动态改变的页面布局
(1)、依据布局引入各个组件
(2)、依据框架主题,传入变化的参数,设置不同的class样式,以及theme主题的选择
(3)、依据router的设置即可更换主题样式以及相应细节的修改
5、菜单与路由的结合
(1)、设置路由相关参数 如:title、menu、name、标志属性等
(2)、递归的方式获取路由list[]数据
export default {
data() {
const menuData = this.getMenuData(this.$router.options.routes)
return {
collapsed:false,
menuData,
selectedKeys: this.selectedKeysMap[this.$route.path],
openKeys: this.collapsed?[]:this.openKeysMap[this.$route.path],
}
},
watch:{
'$route.path':function(val){
this.selectedKeys = this.selectedKeysMap[val];
this.openKeys = this.collapsed?[]:this.openKeysMap[val];
}
},
methods: {
getMenuData(routes = [], parentsKeys = [], selectedKey){
const menuData = [];
routes.forEach(item => {
if(item.name && !item.hideInMenu) {
this.openKeysMap[item.path] = parentKeys;
this.selectedKeysMap[item.path] = [item.path || selectedKey];
const newItem = { ...item };
delete newItem.children;
if(item.children && !item.hideChildrenMenu) {
newItem.children = this.getMenuData(item.children,[...parentKeys,item.path]);
}else {
this.getMenuData(item.children,selectedKey? parentKeys:[...parentKeys,item.path],selectedKey || item.path);
}
menuData.push(newItem);
}else if (
!item.hideInMenu &&
!item.hideChildrenInMenu &&
item.children
){
menuData.push(...this.getMenuData(item.children))
}
});
return menuData;
}
}
}
(3)、路由跳转与菜单组件点击事件相关联,从而使点击菜单,路由跟着变换
添加点击事件:
@click="() => $router.push({path :item.path})"
或者:
@click="() => parent.$router.push({path :item.path})"
不同的框架获取路由的方式不同,点击事件绑定也不同,可根据数据接口获取路由数据,然后依据框架需要,处理菜单点击事件与路由跳转的关系
6、路由管理用户权限
(1)、建立验证权限的js文件,依据需求写验证规则
utils ---> auth.js
//获取权限--依据后台数据返回确定相应权限
export function getCurrentAuthority(){
return ["admin"]
}
//权限验证--检查当前用户是否拥有此页面的查看权限
export function check(authority){
const current = getCurrentAuthority()
return current.some(item => authority.includes(item));
}
//判断是否登录
export function isLogin(){
const current = getCurrentAuthority();
return current && current[0] != "guest"
}
(2)、通过设置路由参数,进而判断权限
//在路由中设置meta参数
{
path:'/',
name:'index',
meta:{
title:'首页'
authority:['admin','user']
}
component:Home,
},
{
path:'/form',
name:'form',
meta:{
title:'表单'
authority:['user']
}
component:Home,
}
。。。
router.beforeEach((to,from,next)) => {
if(to.path !== from.path){
NProgress.start();
}
// 获取当前路由最近的用户权限,并记录下来 findLast是一个依赖,下载即可
const record = findLast(to.matched,record => record.meta.authority);
//对当前路由用户权限进行验证,若有相应权限,及展示列表项,若没有则登录
if(record && !check(record.meta.authority)) {
if(!isLogin() && to.path !== "/user/login"){
next({
path:'/user/login'
})
}else if( to.path != '/403'){
notification.error({
message:'403',
description:"请联系管理员"
});
next({
path:'/403'
})
}
NProgress.done()
}
next()
}
7、如何在组件中使用EChart、Antv等图表插件
(1)、下载echart依赖
npm install echart -S -D
yarn add echart
(2)、设置图表展示样式响应式
npm install resize-detector
在组件中引用
import { addListener, removeListener } from 'resize-detector'
使用:
monted(){
this.chart = echarts.init(this.$refs.chartDom,this.resize)
//在图表生成时依据屏幕自适应宽度、高度
addListener(this.$refs.chartDom,this.resize)
},
//在组件销毁时,移除图表自适应事件,并将图表数据销毁
beforeDestory(){
removeListener(this.$refs.chartDom,this.resize)
this.chart.dispose() //移除图表Dom
this.chart = null
},
methods:{
//图表自适应事件
resize(){
this.chart.resize()
}
}
(3)、设置图表自适应防抖事件
下载debounce
npm install debounce
引入:
import debounce from 'lodash/debounce'
使用:
created(){
this.resize = debounce(this.resize,300);
}
(4)、实时更改传入组件的图表值
方法一:watch深度监听图表options
//组件中
watch:{
options:{
handler(val){
this.chart.setOptions(val);
},
deep:true
}
}
//使用组件的.vue中
mounted(){
this.interval = setInterval(() => {
this.chartOption.series[0].data = this.chartOption.series[0].data.map(() => random(100))
}, 3000);
},
beforeDestory(){
clearInterval(this.interval);
}
方法二:直接监听option,更改之后直接付新值
//组件中
watch:{
option(val){
this.chart.setOptions(val);
}
}
//使用组件的.vue中
mounted(){
this.interval = setInterval(() => {
this.chartOption.series[0].data = this.chartOption.series[0].data.map(() => random(100))
this.chartOption = { ...this.chartOption }
}, 3000);
}
8、高效使用 Mock 数据进行开发
(1)、下载axios,并书写接口
npm install axios
import axios from 'axios'
getChartData(){
axios.get('/api/dashboard/chart',{ params:{ ID: 12345 }}).then((res) => {
this.chartOption = { ... }
})
}
(2)、在mock文件中设置数据返回规则
dashboard_chart.js文件中
function chart(method){
let res = null;
switch(method){
case 'GET':
res = [100, 20, 60, 120, 80, 70 ];
break;
default:
res = null
}
return res
}
//模块化输出:
module.export = chart
(3)、在vue.config.js文件中,修改接口处理方式,接口反向代理模式,对接口进行统一处理
module.export = {
devServer:{
proxy:{
"/api":{
target:"http://localhost:3000",
bypass:function(req,res){
if(req.headers.accept.indexOf("html") !== -1){
console.log("...")
return '.index.html';
}else{
const name = req.path.split("/api/")[1].split('/').join('_');
const mock = require(`./mock/${name}`);
const result = mock(req.method);
//赋值前清一下之前的数据缓存
delete require.cache[require.resolve(`./mock/${name}`)]
return res.send(result);
}
}
}
}
}
}
9、与服务端进行交互
(1)、后台服务端接口与前端创建的mock环境进行切换,方便随时切换环境
在 package.json文件中,修改项目启动方式
scripts:{
'serve':'vue-cli-service serve',
'serve:no-mock':'corss-env MOCK=none vue-cli-service serve',
'build':'vue-cli-service build',
'lint':'vue-cli-service lint',
'test:unit':'vue-cli-service test:unit'
}
修改一下vue.config.js 文件
module.export = {
devServer:{
proxy:{
"/api":{
target:"http://localhost:3000",
bypass:function(req,res){
if(req.headers.accept.indexOf("html") !== -1){
console.log("...")
return '.index.html';
//判断一下,项目运行环境不是MOCK的时候就切换到MOGK数据模式
}else if( process.env.MOCK !== 'none'){
const name = req.path.split("/api/")[1].split('/').join('_');
const mock = require(`./mock/${name}`);
const result = mock(req.method);
//赋值前清一下之前的数据缓存
delete require.cache[require.resolve(`./mock/${name}`)]
return res.send(result);
}
}
}
}
}
}
(2)、在utils文件中建立request.js 文件,对请求接口axios进行header、token、method等参数的封装,以及对返回数据的封装处理
10、管理系统中使用图标的方式
(1)、各个小图标拼接在一张图片上
(2)、使用字体图标
(3)、SVG形式使用图标
方法一:使用iconfont网站中的svg图标
const MyIcon = Icon.createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', // generated by iconfont.cn
});
Vue.component('MyIcon',MyIcon)
//使用:
<my-icon type="icon-example" />
方法二:直接引入SVG形式的图片
将SVG图片放入项目中存放,一般放在assets文件夹下面,vue中会将svg图片解析成url形式的字符串
//引入图片
import logoSvg from '@/assets/logoSvg.svg'
//通过img标签引入
<img :src="logoSvg" alt >
方法三:配置 vue-svg-loader 组件
安装 vue-svg-loader 依赖
添加vue-cli配置,在vue.config.js中设置:
// vue.config.js
module.exports = {
chainWebpack: config => {
const svgRule = config.module.rule('svg')
// 清除已有的所有 loader。
// 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
svgRule.uses.clear()
// 添加要替换的 loader
svgRule
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
}
使用:
import logoSvg from '@/assets/logoSvg.svg'
components:{
logoSvg
}
<logoSvg />
11、将全部this.$route的参数传过去,然后传入其他参数
this.$router.push({query: {...this.$route.query, local:key} })
vue i18n 是vue.js 的国际化插件库,可以实现组件语言切换
12、高效构建打包发布
A:图标按需加载是将所用的图标先下载在本地,然后采用别名,将图标请求直接请求本地图标。
vue.config.js文件中:
configuerWebpack:{
plugins:[themePlugin],
resolve:{
alise:{
"@ant-design/icons/lib/dist$":path.resolve(_dirname,"./src/icons")
}
}
}
B:moment配置优化:将moment引入的包全部隐藏掉
configuerWebpack:{
plugins:[themePlugin, new webpack.IgnorePlugin(/^\.\/locale$/,/moment$s/)],
resolve:{
alise:{
"@ant-design/icons/lib/dist$":path.resolve(_dirname,"./src/icons")
}
}
}
C:此时moment语言包需要手动的引入进来
import "moment/locale/zh-cn"
D:echarts按需引入:如只引进柱状图插件
import echarts from "echarts/lib/echarts";
import "echarts/lib/chart/bar";
import "echarts/lib/component/title";
13、构建可交互的组件文档
1、vue-highlightjs 使代码高亮显示
//下载依赖
npm install --save vue-highlightjs
//main.js中使用:
import Vue from 'vue'
import VueHighlightJS from 'vue-highlightjs'
vue.use(VueHighlightJS)
//页面中使用:
//先引入代码,利用raw-loader将代码处理成字符串加载出来
import chartCode from "!!raw-loder!../../components/Chart"
//在组建中将代码字符串加载出来
<pre v-highlightjs="chartCode"><code class="html"></code></pre>
//引入highlightjs样式组件 main.js中引入:
import "highlight.js/style/github.css"
14、将组件发布到npm上
1、需要一个npm账号
2、组件本地要有package.json文件 —最小要有name、version两个字段
3、在npm或者公司私有的开发源发布即可 推荐 nrm
来管理开发源