адрес проектаvue-admin-webappДобро пожаловать на звезду, вилка
предисловие
Я считаю, что многим людям, как и мне, очень скучно читать документы, когда они новичок в vue.После прочтения vue есть еще vueRouter, vuex, vue-cli, es6 (я не могу научиться...) После прочтения учебник, я не могу начать В реальных проектах я могу только написать несколько простых небольших демонстраций, которые должны отличаться от фактической производственной работы, поэтому я планирую создать систему управления фоном vue с нуля, используя новейший технологический стек. , и углубить мои теоретические знания. , и расширить возможности вашего проекта, поэтому я надеюсь, что эта серия руководств будет полезна для вас при разработке проектов Vue.
1. Основное введение в проект
vue-admin-webappспа-страница управления фоном, основанная наvueа такжеelement-uiДля реализации проверки авторизации при входе в систему, создания динамического маршрута и использования используется новейший стек передовых технологий.easy-mockЧтобы смоделировать данные запроса и реализовать типичный случай бизнес-модели, он может помочь вам быстро создать шаблон системы фонового управления и добавить маршруты в соответствии с фактическими потребностями бизнеса для реализации страниц управления на уровне предприятия.Я считаю, что этот проект определенно поможет вам.
- Предварительный просмотр онлайн - gitee(рекомендуется отечественным пользователям)
Текущая версия основана наwebpack 4.0+
а такжеvue-cli 3.x
сборка версии, требуетсяNode.jsВерсия 8.9 или выше (рекомендуется 8.11.0+), соответствующие знания можно найти на официальном сайте самостоятельно
Функция
- 登录 / 注销
- 登录仿GeeTest-极验安全策略
- 页面
- 初次进入引导用户
- sideBar收缩和展开
- 全屏控制
- 侧边栏
- 根据不同用户权限展示相应的动态左侧菜单
- 权限验证
- 管理员页面
- 权限设置
- 表格操作
- 涉及平常业务遇到的相关表格操作(参考)
- Excel
- Excel导出
- Excel导入
- 多级表头导出
- Echarts
- 滑动显示更多数据
- 动态切换charts
- map地图使用
- Icons
- element-icon
- 阿里iconfont
Готов к работе
Прежде чем начать, убедитесь, что у вас локально установлены node, webpack и git. Технологические стеки, задействованные в этом проекте, в основном включаютES6,vue,vuex,vue-router,vue-cli,axios,webpack,element-ui,easyMock, так что лучше заранее ознакомиться с этими знаниями, которые очень помогут вам понять и освоить проект
Структура каталогов
Ниже представлена структура каталогов всего проекта.
├── public # 静态资源
│ ├── favicon.ico # favicon图标
│ └── index.html # html模板
├── src # 源代码
│ ├── api # 所有请求
│ ├── assets # 图片、字体等静态资源
│ ├── components # 全局公用组件
│ ├── layout # 页面整体布局盒子
│ ├── mixins # 全局混入模块
│ ├── plugins # 全局插件部分
│ ├── router # 路由
│ ├── store # 全局store管理
│ ├── style # 全局样式
│ ├── utils # 全局公用方法
│ ├── vendor # 公用vendor(excel导入导出)
│ ├── views # views所有页面
│ ├── App.vue # 入口页面
│ ├── main.js # 入口文件 加载组件 初始化等
├── .borwserslistrc # 浏览器兼容相关
├── .env.xxx # 环境变量配置 
├── .eslintrc.js # eslint 配置项
├── .gitignore.js # git忽略文件设置
├── .babelrc.config.js # babel-loader 配置
├── package.json # package.json
├── postcss.config.js # postcss 配置
└── vue.config.js # vue-cli 配置
Установить
# 克隆项目
git clone git@github.com:gcddblue/vue-admin-webapp.git
# 进入项目目录
cd vue-admin-webapp
# 安装依赖
npm install
# 启动服务
npm run serve
После завершения запуска браузер будет открыт для доступаhttp://localhost:8080
, Затем вы можете добавлять или изменять маршруты и писать свой собственный бизнес-код в соответствии с вашими реальными потребностями.
2. Архитектура страницы
За исключением страницы входа, вся архитектура страницы состоит из трех частей.头部
侧边栏
右侧内容页
Инкапсулируйте эти три компонента в файл проекта @/layout/index.js и переключите правую сторону, щелкнув левое меню.router-view
Замена рута, соответствующий файл проекта выглядит следующим образом
3. пакет аксиос
В проекте vue мы обычно выбираем библиотеку axios для взаимодействия запроса с фоном, которая представляет собой http-библиотеку на основе обещаний, которая может работать на стороне браузера, и node.js. В этом проекте в основном реализованы перехват запросов и ответов, получение, инкапсуляция пост-запросов.
Настройка различных сред
Создавая файлы в разных средах в проекте, я создал здесь только среды разработки и продакшн, конечно, вы также можете создавать тестовые среды.env.test
файл в.env.production
Например:
ENV = 'production'
# base api
VUE_APP_BASE_API = 'https://www.easy-mock.com/mock/5cee951f11690b5261b75566/admin'
покаVUE_APP_
Переменные, начинающиеся сwebpack.DefinePlugin
Статически встраивается в пакет клиента. Вы можете получить к ним доступ следующим образом в коде вашего приложения, например, я инициализирую axios в @/api/index.js:
const $axios = axios.create({
timeout: 30000,
// 基础url,会在请求url中自动添加前置链接
baseURL: process.env.VUE_APP_BASE_API
})
Создавая папку api, все интерфейсы концентрируются в этой папке, а разные файлы js создаются в соответствии с разными бизнесами, чтобы лучше разделить функции интерфейсов.Код в index.js выглядит следующим образом:
import axios from 'axios'
import Qs from 'qs' // 处理post请求数据格式
import store from '@/store'
import router from '@/router'
import Vue from 'vue'
import { Loading, Message } from 'element-ui' // 引用element-ui的加载和消息提示组件
const $axios = axios.create({
// 设置超时时间
timeout: 30000,
// 基础url,会在请求url中自动添加前置链接
baseURL: process.env.VUE_APP_BASE_API
})
Vue.prototype.$http = axios // 这里并发请求以便在组件使用this.$http.all(),具体看dashborad页面
// 在全局请求和响应拦截器中添加请求状态
let loading = null
/**
* 请求拦截器
* 用于处理请求前添加loading、判断是否已保存token,并在每次请求头部添加token
*/
$axios.interceptors.request.use(
config => {
loading = Loading.service({ text: '拼命加载中' })
const token = store.getters.token
if (token) {
config.headers.Authorization = token // 请求头部添加token
}
return config
},
error => {
return Promise.reject(error)
}
)
/**
* 响应拦截器
* 用于处理loading状态关闭、请求成功回调、响应错误处理
*/
$axios.interceptors.response.use(
response => {
if (loading) {
loading.close()
}
const code = response.status
// 请求成功返回response.data
if ((code >= 200 && code < 300) || code === 304) {
return Promise.resolve(response.data)
} else {
return Promise.reject(response)
}
},
error => {
if (loading) {
loading.close()
}
console.log(error)
if (error.response) {
switch (error.response.status) {
case 401:
// 返回401 清除token信息并跳转到登陆页面
store.commit('DEL_TOKEN')
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
})
break
case 404:
Message.error('网络请求不存在')
break
default:
Message.error(error.response.data.message)
}
} else {
// 请求超时或者网络有问题
if (error.message.includes('timeout')) {
Message.error('请求超时!请检查网络是否正常')
} else {
Message.error('请求失败,请检查网络是否已连接')
}
}
return Promise.reject(error)
}
)
// get,post请求方法
export default {
post(url, data) {
return $axios({
method: 'post',
url,
data: Qs.stringify(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
},
get(url, params) {
return $axios({
method: 'get',
url,
params
})
}
}
Как и выше, вы можете обратиться к моим комментариям. Пакет конфигурации axios является очень важным модулем во всем проекте. На самом деле, в разных проектах пакет axios похож, поэтому, пока вы овладеваете навыком, вы сможет разработать новый проект в следующий раз.Легко завершить упаковку.
4. Проверка разрешений и боковая панель
маршрутизация
Маршрутизация - это ключ к организации проекта Vue. После анализа прототипа проекта следующим шагом будет написание маршрута. В этом проекте он в основном разделен на два маршрута.currencyRoutes
а такжеasyncRoutes
currencyRoutes
: представляет собой общую маршрутизацию, что означает, что не требуется никакого авторитетного решения, и страницы отображаются пользователями с разными ролями, такими как: целевая страница, 404 и т. д.
asyncRoutes
: Представляет динамическую маршрутизацию, которая должна динамически выделяться путем оценки разрешений.Метод оценки разрешений будет представлен далее.
Инструкции по настройке, связанные с маршрутизацией:
/**
* 路由相关属性说明
* hidden: 当设置hidden为true时,意思不在sideBars侧边栏中显示
* mete{
* title: xxx, 设置sideBars侧边栏名称
* icon: xxx, 设置ideBars侧边栏图标
* noCache: true 当设置为true时不缓存该路由页面
* }
*/
Проверка разрешения динамически добавлять боковую панель
Этот проект обновляет боковую панель с помощью привязки маршрутизации. Все настройки боковой панели выполняются во внешнем интерфейсе. Через интерфейс доступа серверная часть возвращает массив списка, связанный с разрешениями, где значением массива является значение атрибута имени маршрута, а передняя часть рекурсивно проходитasyncRoutes
Определяет, содержит ли список разрешений соответствующее имя маршрута, и, наконец, возвращает объект массива addRoutes, который содержит все страницы маршрута разрешений роли пользователя.
Конкретная реализация состоит в том, чтобы установить глобальную защиту навигации переднего плана в маршрутизации index.js.Конкретный процесс оценки выглядит следующим образом:
// 导航守卫
router.beforeEach(async (to, from, next) => {
document.title = getTitle(to.meta.title)
if (to.path === '/login') {
next()
} else {
if (store.getters.token) {
const hasRoles = store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
const { roles } = await store.dispatch('user/_getInfo')
const addRoutes = await store.dispatch(
'permission/getAsyncRoutes',
roles
)
router.addRoutes(addRoutes)
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true })
} catch (error) {
Message.error(error)
}
}
} else {
next({
path: '/login',
query: {
redirect: to.fullPath
}
})
}
}
})
Тут столкнулся с багом при добавлении маршрутов через addRoutes.При переключении ролей добавленные ранее динамические маршруты нельзя удалить, поэтому это переинициализацияrouter.matcher
Свойства способа достижения:
const creatRouter = () => {
return new Router({
routes: currencyRoutes,
scrollBehavior() {
return { x: 0, y: 0 }
}
})
}
const router = creatRouter()
// 解决addRoute不能删除动态路由问题
export function resetRouter() {
const reset = creatRouter()
router.matcher = reset.matcher
}
каждый раз, когда я выхожуresetRouter
метод для инициализации объекта маршрутизатора и удаления ранее добавленного динамически маршрута.
Наконец, рекурсивно пройдите по объекту маршрутизации, чтобы загрузить боковую панель через компонент el-menu элемента element-ui.
5. Имитация данных
Как фронтенд-разработчик, я считаю, что все знают фиктивные данные. Его основная функция — подделывать поддельные данные, чтобы команда могла развиваться параллельно. В этом проекте используются фиктивные данные.easy-mockЧтобы реализовать запрос данных интерфейса, вы можете перейти на официальный сайт, чтобы увидеть простой учебник,easy-mock
Его преимущество в том, что не нужно создавать фиктивную папку в проекте и перехватывать ajax для реализации поддельных запросов данных, таких как традиционные фиктивные данные.Это настоящий запрос API и разрешает любой междоменный запрос.Ниже приведены все интерфейсы этого проект
где все интерфейсы создаются_res
поле, чтобы определить, содержит ли запрос поле заголовка Authorzation или нет, чтобы определить, находится ли пользователь в состоянии входа в систему.Конфигурация интерфейса getCardsData следующая:
{
code: 0,
data: {
vistors: '@integer(10000, 100000)',
message: '@integer(100, 1000)',
order: '@integer(0, 1000)',
profit: '@integer(1000, 100000)'
},
_res: function({
_req,
Mock
}) {
if (!_req.header.authorization) {
return {
status: 401,
data: {
msg: '未授权'
}
}
} else {
return {
status: 200
}
}
}
}
Фальшивые данные могут сыграть роль в продвижении проекта при разработке проекта.Вы можете заранее договориться с обслуживающим персоналом и сначала получить поле фальшивых данных, а затем смоделировать свои собственные фальшивые данные, чтобы вы не Не нужно ждать, пока обслуживающий персонал разработает интерфейс, и проект застрянет. Как правило, в проекте создайте.env.development
а также.env.production
Файл представляет среды разработки и производства, в которых могут быть определены URL-адреса запросов различных интерфейсов среды.
# base api
VUE_APP_BASE_API = 'https://www.easy-mock.com/mock/5cee951f11690b5261b75566/admin'
Инициализируйте в аксиомах пакета, как это
const $axios = axios.create({
// 设置超时时间
timeout: 30000,
// 基础url,会在请求url中自动添加前置链接
baseURL: process.env.VUE_APP_BASE_API
})
Таким образом, адрес запроса может автоматически переключаться в соответствии с различными средами без изменения каждого интерфейса запроса по отдельности.
6. Войти
Инкапсулируя функцию входа в магазин, при нажатии на вход вызовитеthis.$store.dispatch('user/_login', this.ruleForm)
Этот метод действия, когда фоновая проверка интерфейса будет успешной, вернетtoken
поле, внешний интерфейс позвонитlocalStroage
интерфейс будет такимtoken
Сохраните его локально, и сохраняйте этот токен в перехватчике перед каждым запросом в будущемAuthorization
В этом поле заголовка фону нужно только проверить токен, чтобы узнать информацию о пользователе. Вы можете не только токенизировать студентов,Описание токена Crazy ClickОчень подробно описано, почему http должен добавлять toekn и token.
Здесь я также использовал имитациюgeetestПроверка поведения, проверьте реальную работу, сдвинув изображение. Принцип использует функцию рисования канв h5 для рисования нижнего изображения и изображения ползунка, а затем отслеживает событие mouseMove. Когда разница между координатой y скользящего блока и инициализированное изображение меньше 10, срабатывает функция проверки успеха.
7. Оптимизация и советы
Используйте миксины
Если ваши несколько компонентов используют один или несколько методов, нам не нужно каждый раз вставлять и копировать, разве это не очень мало, мы можем инкапсулировать эти методы в файл js, когда один из моих компонентов должен вызвать, когда этот метод
import aMixin from '@/mixins/a-mixin'
export default {
name: 'page1',
mixins: [newsMixin] //调用mixins属性,将aMixin这个模块的数据及方法等都添加进这个组建吧
}
Правила использования миксинов
Метод Object.freeze
Какая польза от этого метода? Он может заморозить объект, чтобы предотвратить изменение объекта. Каков эффект оптимизации этого метода в проекте Vue? Все знают, что Vue принимаетзахват данныхкаким-то образом обходить объекты данных, превращать эти свойства в методы получения и установки для отслеживания и уведомления об изменениях данных, поэтому, когда вы сталкиваетесь с огромным массивом или объектом и уверены, что данные не будут изменены, вы можете использоватьObject.freeze()
способ организовать преобразование Vue этих огромных данных, что может значительно повысить производительность, например:
new Vue({
data: {
// vue不会对list里的object做getter、setter绑定
list: Object.freeze([
{ value: 1 },
{ value: 2 }
])
},
mounted () {
// 界面不会有响应
this.list[0].value = 100;
// 下面两种做法,界面都会响应
this.list = [
{ value: 100 },
{ value: 200 }
];
this.list = Object.freeze([
{ value: 100 },
{ value: 200 }
]);
}
})
Автоматически импортировать модули
Когда нам нужно импортировать несколько модулей для компонента или js-файла, общепринятой практикой является импорт каждого модуля, что, очевидно, довольно громоздко.require.context
Функция пригодится.Как пользоваться этой функцией?Официальное введение здесьОн в основном используется для автоматизации импорта модулей.В интерфейсном проекте, если вы столкнетесь с ситуацией, когда многие модули импортируются из папки, вы можете использовать этот API.Он будет проходить указанные файлы в папке, а затем импортировать автоматически, так что вам не нужно каждый раз использовать этот API Явный вызов импорта для импорта модуля
require.context
Функция принимает три параметра:
- directory {String} - путь для чтения файла из
- useSubdirectories {Boolean} - Обходить ли подкаталоги файлов
- gExp {RegExp} - регулярное выражение для соответствия файлу
Такие как
require.context('./test', false, /.test.js$/)
#上面的代码遍历当前目录下的test文件夹的所有.test.js结尾的文件,不遍历子目录
require.context
После выполнения функция возвращает функцию, и эта функция содержит три свойства:
- разрешить {Function} — принимает запрос параметра, запрос представляет собой относительный путь соответствующего файла в тестовой папке и возвращает относительный путь соответствующего файла относительно всего проекта.
- keys {Function} - возвращает массив имен модулей, которые успешно совпадают
- id {String} - id среды исполнения, возвращает строку
Мы часто просматриваем массив, возвращаемый ключами, для обработки пути, что довольно удобно, и, наконец,require.context
Возвращаемая функция принимает элемент пути ключей, возвращенных в массив, в качестве параметра и возвращает модуль этого файла пути.
Ниже то, что я используюrequire.context
Функция динамически генерирует объект модуля.
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
const path = require('path')
Vue.use(Vuex)
const files = require.context('./modules', false, /\.js$/)
let modules = {}
files.keys().forEach(key => {
let name = path.basename(key, '.js')
modules[name] = files(key).default || files(key)
})
const store = new Vuex.Store({
modules,
getters
})
export default store
cdn импорт
Для некоторых редко изменяемых библиотек модулей, таких как:vue
vueRouter
vuex
echarts
element-ui
подожди, мы позволимwebpack
не упаковывать их, а передатьcdn
Введено, чтобы вы могли уменьшить размер кода, уменьшить пропускную способность сервера и кэшировать их через cdn для повышения производительности веб-сайта.
Конкретная реализация заключается в измененииvue.config.js
, добавить для объектного модуляexternals
Полная конфигурация выглядит следующим образом:
const cdn = {
css: [
// element-ui css
'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
],
js: [
// vue
'https://unpkg.com/vue/2.5.22/vue.min.js',
// element-ui
'https://unpkg.com/element-ui/lib/index.js',
// vue
'https://unpkg.com/vuex/3.1.0/vuex.min.js'
]
}
# 不打包vue、element-ui、vuex
module.exports = {
externals: {
vue: 'Vue',
'element-ui':'ELEMENT',
vuex: 'Vuex'
},
chainWebpack: config => {
config.plugin('html')
.tap(args => {
args[0].cdn = cdn
return args
})
}
}
Изменить следующийindex.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<% if (process.env.NODE_ENV === 'production') { %>
<!-- 引入样式 -->
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
<link rel="stylesheet" href="<%=css%>">
<% } %>
<!-- 引入js -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%=js%>"></script>
<% } %>
<% } %>
<title>vue-admin-webapp</title>
</head>
<body>
<noscript>
<strong>We're sorry but vue-admin-webapp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Хорошо, большое объявление
Многостраничная конфигурация vue cli3
Следите за другими моими статьямиПравильная поза для использования vue cli3 для настройки многостраничных проектов
проект инициализации vue cli3
Следите за другими моими статьямиСоздайте проект с vue cli3 в правильном положении
Суммировать
Я разрабатывал этот проект с перерывами, пока был на работе. Я не написал слишком много технических постов. Мои навыки письма и логической организации все еще довольно плохие. Пожалуйста, простите меня. Сначала я думал, что это должно быть довольно гладко, прежде чем я начал это делать.Я не ожидал, что когда я реализовывал это шаг за шагом, это все еще отличалось от моей первоначальной идеи.В течение этого периода я столкнулся с множеством ошибок , большинство из которых были вызваны невнимательностью к деталям.Хорошая память не так плоха, как плохое письмоВ этом предложении практика — это истина. Делайте больше и исследуйте больше. В конце концов, я бы подумал об использованииuni-appЭтот фреймворк используется для разработки мультиплатформенной (applet, android, ios, h5) мобильной версии системы управления фоном vue, с нетерпением жду...