项目总结介绍

核心提示一、项目环境搭建1.vue-element-admin的了解和介绍vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,

一、项目环境搭建

1.vue-element-admin的了解和介绍

vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。

2.项目模板启动和目录介绍

2.1 git拉取基础项目模板

$ git clone https://github.com/PanJiaChen/vue-admin-template.git shop

2.2 安装项目依赖

npm install #安装依赖

2.3 启动项目

npm run dev #启动开发模式的服务

项目运行完毕,浏览器会自动打开基础模板的登录页,如上图

2.4 目录结构

├── build # 构建相关├── mock  # 项目mock 模拟数据├── public# 静态资源│   │── favicon.ico     # favicon图标│   └── index.html      # html模板├── src   # 源代码│   ├── api      # 所有请求│   ├── assets   # 主题 字体等静态资源│   ├── components      # 全局公用组件│   ├── icons    # 项目所有 svg icons│   ├── layout   # 全局 layout│   ├── router   # 路由│   ├── store    # 全局 store管理│   ├── styles   # 全局样式│   ├── utils    # 全局公用方法│   ├── vendor   # 公用vendor│   ├── views    # views 所有页面│   ├── App.vue  # 入口页面│   ├── main.js  # 入口文件 加载组件 初始化等│   └── permission.js   # 权限管理│   └── settings.js   # 配置文件├── tests # 测试├── .env.xxx     # 环境变量配置├── .eslintrc.js # eslint 配置项├── .babelrc     # babel-loader 配置├── .travis.yml  # 自动化CI配置├── vue.config.js# vue-cli 配置├── postcss.config.js   # postcss 配置└── package.json # package.json

我们在做项目时 其中最关注的就是src目录, 里面是所有的源代码和资源, 至于其他目录, 都是对项目的环境和工具的配置。

3.API模块和请求封装模块介绍

axios的拦截器原理如下

3.1 axios拦截器

const service = axios.create

3.2 请求拦截器

service.interceptors.request.use {      config.headers['X-Token'] = getToken    }    return config  },  error => {    return Promise.reject  })

3.3 响应拦截器

service.interceptors.response.use {      Message      if  { MessageBox./confirm/i.then => {   store.dispatch.then => {     location.reload   }) })      }      return Promise.reject)    } else {      return res    }  },  error => {    Message    return Promise.reject  })

3.4 api模块的单独封装

import request from '@/utils/request'export function login {  return request}export function logout {  return request}

二、登录模块

1.设置固定的本地访问端口和网站名称

1.1 本地服务端口:在 vue.config.js 中进行设置

vue.config.js 就是vue项目相关的编译,配置,打包,启动服务相关的配置文件,它的核心在于webpack,但是又不同于webpack,相当于改良版的webpack。 在项目下, 我们发现了 .env.development 和 .env.production 两个文件 development => 开发环境 production => 生产环境 当我们运行npm run dev进行开发调试的时候,此时会加载执行 .env.development 文件内容 当我们运行npm run build:prod进行生产环境打包的时候,会加载执行 .env.production 文件内容

1.2 网站名称

网站名称实际在configureWebpack选项中的name选项,通过阅读代码,我们会发现name实际上来源于src目录下的 settings.js 文件。

module.exports = {  title: '小优电商后台管理系统',  sidebarLogo: true}

2.登录页面的基础布局

2.1 设置头部背景

2.2 设置背景图片

.login-container {  background-image: url;  background-position: center;  background-size: 100% 100%;}

3.登录表单的校验

3.1 用户名和密码的校验

loginRules: {  username: [{ required: true, trigger: 'blur', validator: validateUsername }],  password: [    { required: true, trigger: 'blur' },    { min: 6, max: 12, trigger: 'blur', message: '密码长度应该在6-12位之间' }  ]},

3.2 关于修饰符

@keyup.enter属于按键修饰符,如果我们想监听在按回车键的时候触发,可以如下编写

4.Vue-Cl.i配置跨域代理

4.1 为什么会出现跨域?

当下,最流行的就是前后分离项目,也就是前端项目和后端接口并不在一个域名之下,那么前端项目访问后端接口必然存在跨域的行为.

4.2 解决开发环境的跨域问题

开发环境的跨域,也就是在vue-cli脚手架环境下开发启动服务时,我们访问接口所遇到的跨域问题,vue-cli为我们在本地开启了一个服务,可以通过这个服务帮我们代理请求,解决跨域问题

proxy: {  '/api/private/v1/': {    target: 'http://127.0.0.1:8888', // 跨域请求的地址    changeOrigin: true // 只有这个值为true的情况下 才表示开启跨域  }}

5.封装单独的登录接口

export function login {  return request}

6.封装Vuex的登录Action并处理token

6.1 实现store/modules/user.js基本配置

// 状态const state = {}// 修改状态const mutations = {}// 执行异步const actions = {}export default {  namespaced: true,  state,  mutations,  actions}

6.2 设置 token 的共享状态

const state = {  token: null}

6.3 操作 token

在 utils/auth.js 中,基础模板已经为我们提供了获取 token ,设置 token ,删除 token 的方法,可以直接使用

const TokenKey = 'xiaoyou'export function getToken {  return localStorage.getItem}export function setToken {  return localStorage.setItem}export function removeToken {  return localStorage.removeItem}

6.4 初始化token状态 - store/modules/user.js

import { getToken, setToken, removeToken } from '@/utils/auth'const state = {  token: getToken // 设置token初始状态   token持久化 => 放到缓存中}

6.5 提供修改token的mutations

const mutations = {  setToken {    state.token = token // 设置token  只是修改state的数据  123 =》 1234    setToken // vuex和 缓存数据的同步  },  removeToken {    state.token = null // 删除vuex的token    removeToken // 先清除 vuex  再清除缓存 vuex和 缓存数据的同步  }}

6.6 封装登录的Action

登录action要做的事情,调用登录接口,成功后设置token到vuex,失败则返回失败

const actions = {  async login {    const result = await login // 实际上就是一个promise  result就是执行的结果    if  {      context.commit    }  }}

6.7 区分axios在不同环境中的请求基础地址

为什么会有环境变量之分 如图 可以在 .env.development 和 .env.production 定义变量,变量自动就为当前环境的值 基础模板在以上文件定义了变量VUE_APP_base_API,该变量可以作为axios请求的baseURL 在模板中,两个值分别为/dev-api 和 /prod-api

6.8 处理axios的响应拦截器

service.interceptors.response.use {    return data  } else {    Message.error // 提示错误消息    return Promise.reject)  }}, error => {  Message.error // 提示错误信息  return Promise.reject // 返回执行错误 让当前的执行链跳出成功 直接进入 catch})

三、主页模块

1.主页的左侧导航样式

左侧导航组件的样式文件 styles/siderbar.scss

1.1 设置左侧导航背景图片

.scrollbar-wrapper {     background: url no-repeat 0 100%;}

1.2 显示左侧logo图片 src/setttings.js

module.exports = {  title: '小优电商后台管理系统',  fixedHeader: false,  sidebarLogo: true // 显示logo}

1.3 设置头部图片结构 src/layout/components/Sidebar/Logo.vue

ink key="collapse" to="/"> ink>

2.设置头部内容的布局和样式

需要把页面设置成如图样式

2.1 头部组件位置 layout/components/Navbar.vue

北京小优智慧城市科技有限公司 V1.0

2.2 右侧下拉菜单设置

pdown trigger="click">

管理员

ink to="/"> 首页 ink>项目地址 退出登录

3. 存储用户信息

3.1 新增变量 userInfo action src/store/modules/user.js

state: {  token: getToken,  userInfo: {} // 用于存储用户对象信息},

3.2 设置和删除用户资料 mutations

// 设置用户信息setUserInfo {  state.userInfo = userInfo},// 删除用户信息removeUserInfo {  state.userInfo = {}}

3.3 建立用户名的映射 src/store/getters.js

const getters = {    token: state => state.user.token,  username: state => state.user.userInfo.username}export default getters

3.4 将头部菜单中的名称换成真实的用户名

{ { username }}

4.自定义指令

全局注册自定义指令语法 - 获取焦点指令

Vue.directive {    console.log    el.children[0].focus  }})

在登录组件中使用此指令

5. 实现登出功能

5.1 登出 action src/store/modules/user.js

logout {  // 删除token  context.commit // 不仅仅删除了vuex中的 还删除了缓存中的  // 删除用户资料  context.commit // 删除用户信息}

5.2 mutation

removeToken {  state.token = null // 将vuex的数据置空  removeToken // 同步到缓存},removeUseInfo {  state.userInfo = {}}

5.3 头部菜单调用 action src/layout/components/Navbar.vue

async logout {  await this.$store.dispatch // 这里不论写不写 await 登出方法都是同步的  this.$router.push // 跳到登录}

6.Token失效的主动介入

6.1 流程图转化代码

src/utils/request.js

const timeKey = 'hrsaas-timestamp-key' // 设置一个独一无二的key// 获取时间戳export function getTimeStamp {  return cookies.get}// 设置时间戳export function setTimeStamp {  cookies.set)}

src/utils/request.js

import axios from 'axios'import store from '@/store'import router from '@/router'import { Message } from 'element-ui'import { getTimeStamp } from '@/utils/auth'const TimeOut = 3600 // 定义超时时间const service = axios.create// 请求拦截器service.interceptors.request.use {    // 只有在有token的情况下 才有必要去检查时间戳是否超时    if ) {      // 如果它为true表示 过期了      // token没用了 因为超时了      store.dispatch // 登出操作      // 跳转到登录页      router.push      return Promise.reject)    }    config.headers['Authorization'] = store.getters.token  }  return config // 必须要返回的}, error => {  return Promise.reject})// 响应拦截器service.interceptors.response.use {    return data  } else {    // 业务已经错误了 还能进then   不能 ! 应该进catch    Message.error // 提示错误消息    return Promise.reject)  }}, error => {  Message.error // 提示错误信息  return Promise.reject // 返回执行错误 让当前的执行链跳出成功 直接进入 catch})// 超时逻辑   是否大于 时间差function IsCheckTimeOut {  var currentTime = Date.now // 当前时间戳  var timeStamp = getTimeStamp // 缓存时间戳  return  / 1000 > TimeOut}export default service

6.2 同理,在登录的时候,如果登录成功,设置时间戳

async login {  const result = await login // 实际上就是一个promise  result就是执行的结果  context.commit  setTimeStamp // 将当前的最新时间写入缓存}

四、路由和页面

因为复杂中台项目的页面众多,不可能把所有的业务都集中在一个文件上进行管理和维护,并且还有最重要的,前端的页面中主要分为两部分,一部分是所有人都可以访问的, 一部分是只有有权限的人才可以访问的,拆分多个模块便于更好的控制

1.新建路由

在 router 目录下新建目录 modules,在此目录中新建各个路由模块 路由模块目录结构

2.设置每个模块的路由规则

// 导出属于用户的路由规则import Layout from '@/layout'export default {  path: '/user', // 路径  name: '', // 给路由规则加一个name  component: Layout, // 组件  // 配置二级路的路由表  children: [{    path: '', // 这里当二级路由的path什么都不写的时候 表示该路由为当前二级路由的默认路由    name: 'user', // 给路由规则加一个name    component:  => import,    // 路由元信息  其实就是存储数据的对象 我们可以在这里放置一些信息    meta: {      title: '用户管理' // meta属性的里面的属性 随意定义    }  }]}

3.静态路由和动态路由临时合并,形成左侧菜单

什么叫临时合并? 动态路由是需要权限进行访问的,但是权限的动态路由访问是很复杂的,我们可以先将 静态路由和动态路由进行合并,不考虑权限问题,后面再解决这个问题路由主文件 src/router/index.js

// 引入多个模块的规则import Layout from '@/layout'import userRouter from './modules/user'import roleRouter from './modules/role'import rightsRouter from './modules/right'import goodsRouter from './modules/goods'import categoryRouter from './modules/category'import reportsRouter from './modules/report'// 动态路由export const asyncRoutes = [  userRouter, roleRouter, rightsRouter, goodsRouter, categoryRouter, reportsRouter]const createRouter =  => new Router => , // 管理滚动行为 如果出现滚动 切换就让 让页面回到顶部  routes: [...constantRoutes, ...asyncRoutes]})

五、内容模块

1.过滤器解决时间格式的处理

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 。过滤器应该被添加在 Javascript 表达式的尾部,由“管道”符号指示:

    

安装 moment

npm i moment

编写过滤器函数

import moment from 'moment'export function formatTime {  return moment.format}

在 main.js 中全局注册过滤器

import * as filters from '@/filters'Object.keys.forEach})

2.新增用户

在 views/user 目录下新建一个弹层组件 src/views/user/components/add-user.vue

父组件中引用,弹出层

import AddUser from './components/add-user'

点击 新增用户 按钮,弹出弹出层

新增用户

点击按钮展示弹出层的关键,就是设置组件中 el-dialog 组件中的如下属性的值

:visible.sync="dialogVisible"

按钮在父组件,变量 dialogVisible在子组件,如何改变? 可以在子组件中的 props 中新建属性

dialogVisible

然后父组件中为其赋值

最后在父组件的 data 中定义变量

addDialogVisible:false

但是上面的解决方案有一个问题:点击对话框右上角的 X ,或者“取消”按钮,或者点击其他区域关闭对话框时,会抛出如下错误 **错误原因:**进行上面的几个操作时,会导致自动修改 props 中的 dialogVisible 变量的值,但这是不允许的 **解决方案:**参考上面的实现,直接在父组件中操作子组件中的 data 变量的值

3.用户导入组件封装

3.1 excel导入功能需要使用npm包 xlsx,所以需要安装xlsx 插件

$ npm i xlsx

3.2 将vue-element-admin提供的导入功能新建一个组件,位置:src/components/UploadExcel

3.3 注册全局的导入excel组件

import CommonTools from './CommonTools'import UploadExcel from './UploadExcel'export default {  install {    Vue.component // 注册工具栏组件    Vue.component // 注册导入excel组件  }}

3.4 新建一个公共的导入页面,挂载路由 src/router/index.js

{  path: '/import',  component: Layout,  hidden: true, // 隐藏在左侧菜单中  children: [{    path: '', // 二级路由path什么都不写 表示二级默认路由    component:  => import  }]},

3.5 创建import路由组件 src/views/import/index.vue

3.6 获取导入的excel数据, 导入excel接口

async  success {  // 如果是导入用户     const userRelations = {'入职日期': 'create_time','手机号': 'mobile','用户名': 'username','密码': 'password','邮箱': 'email','部门':'部门'     }     const arr = []     results.forEach.forEacharr.push      })     await importUser // 调用导入接口     this.$router.back}

六、语言、主题和全屏切换

1.全屏插件的引用

第一步,安装全局插件screenfull

$ npm i screenfull

第二步,封装全屏显示的插件src/components/ScreenFull/index.vue

第三步,全局注册该组件 src/components/index.js

import ScreenFull from './ScreenFull'Vue.component // 注册全屏组件

第四步,放置于layout/navbar.vue

.right-menu-item {   vertical-align: middle;}

2.动态主题的设置

第一步, 封装颜色选择组件 ThemePicker 代码地址:@/components/ThemePicker

import ThemePicker from './ThemePicker'Vue.component

第二步, 放置于layout/navbar.vue

3.多语言实现

第一步,我们需要首先国际化的包

$ npm i vue-i18n

第二步,需要单独一个多语言的实例化文件 src/lang/index.js

import customZH from './zh' // 引入自定义中文包import customEN from './en' // 引入自定义英文包Vue.use // 全局注册国际化包export default new VueI18n || 'zh', // 从cookie中获取语言类型 获取不到就是中文  messages: {    en: {      ...elementEN, // 将饿了么的英文语言包引入      ...customEN    },    zh: {      ...elementZH, // 将饿了么的中文语言包引入      ...customZH    }  }})

第三步,在main.js中对挂载 i18n的插件,并设置element为当前的语言

Vue.use => i18n.t})new Vue})

第四步,在左侧菜单应用

第五步,封装多语言组件 src/components/lang/index.vue

第六步,在Navbar组件中引入

 

七、打包上线

1.打包之前的路由模式

hash模式 : #后面是路由路径,特点是前端访问,#后面的变化不会经过服务器

history模式:正常的/访问模式,特点是后端访问,任意地址的变化都会访问服务器

改成history模式非常简单,只需要将路由的mode类型改成history即可

const createRouter =  => new Router => , // 管理滚动行为 如果出现滚动 切换就让 让页面回到顶部  routes: [...constantRoutes] // 改成只有静态路由})

2.webpack排除打包

先找到 vue.config.js, 添加 externalswebpack 不打包 xlsxelement

externals:   {      'vue': 'Vue',      'element-ui': 'ELEMENT',      'xlsx': 'XLSX'   }

3.CDN文件配置

const cdn = {  css: [    // element-ui css    'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // 样式表  ],  js: [    'https://unpkg.com/vue/dist/vue.js',     'https://unpkg.com/element-ui/lib/index.js',     'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js', 'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js'  ]}

但是请注意,这时的配置实际上是对开发环境和生产环境都生效的,在开发环境时,没有必要使用CDN,此时我们可以使用环境变量来进行区分

let cdn = { css: [], js: [] }// 通过环境变量 来区分是否使用cdnconst isProd = process.env.NODE_ENV === 'production' // 判断是否是生产环境let externals = {}if  {  // 如果是生产环境 就排除打包 否则不排除  externals = {    // key / value    'vue': 'Vue', // 后面的名字不能随便起 应该是 js中的全局对象名    'element-ui': 'ELEMENT', // 都是js中全局定义的    'xlsx': 'XLSX' // 都是js中全局定义的  }  cdn = {    css: [      'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // 提前引入elementUI样式    ], // 放置css文件目录    js: [      'https://unpkg.com/vue/dist/vue.js', // vuejs      'https://unpkg.com/element-ui/lib/index.js', // element      'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js', // xlsx 相关      'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js' // xlsx 相关    ] // 放置js文件目录  }}

4.注入CDN文件到模板

之后通过 html-webpack-plugin注入到 index.html之中:

config.plugin.tap

找到 public/index.html。通过你配置的CDN Config 依次注入 css 和 js。

    <% for { %>    ink rel="stylesheet" href="<%=css%>">  <% } %><% for { %>  <% } %>

最后,进行打包

$ npm run build:prod

,https://blog.csdn.net/chuenst/article/details/117065028

 
友情链接
鄂ICP备19019357号-22