Быстро создайте систему управления реагирующим фоном

React.js

Адрес предварительного просмотра проекта

предисловие

Я считаю, что многие мелкие партнеры могут столкнуться с необходимостью разработки системы фонового управления, так как же мы можем быстро выполнить это требование?

Эта статья будетreactВ качестве отправной точки запишите процесс создания базового шаблона системы управления, чтобы углубить пониманиеreactСтек технологий и понимание реального проекта, надеюсь, вам будет полезно разработать такой проект

Если в статье есть какие-либо недостатки или ошибки, пожалуйста, дайте мне больше советов от друзей, которые ее увидят, заранее спасибо

Описание Проекта

react-adminОтcreate-react-appЛеса строятся быстро, на основеReactШаблон системы фонового управления, созданный экосистемой. Реализован вход/выход из системы, маршрутизация отложенной загрузки,axiosИнкапсуляция, простое управление правами и другие функции, это может помочь вам быстро создать шаблоны системы управления, вам нужно только добавить определенные бизнес-коды

Адрес онлайн-просмотраадрес предварительного просмотра

GitHubкодкодовый адрес

стек технологий

Технологический стек, задействованный в этом проекте, в основном включаетes6,react,react-router,redux,react-redux,Create React App,react-loadable,axiosи т. д., так что вам может понадобиться знать эти знания заранее, это очень поможет вам понять проект

основные навыки

  • Отложенная загрузка маршрута
  • Панировочные сухари
  • Обычно используетсяUIэкспонат
  • echartsполноэкранный режим
  • функция входа/выхода
  • axiosупаковка
  • Простое управление правами

Структура проекта

├── public                   # 不参与编译的资源文件
├── src                      # 主程序目录
│   ├── api                     # axios 封装
│   ├── assets                  # 资源文件
│   │   ├── font                    # 字体文件
│   │   └── images                  # 图片资源
│   ├── components              # 全局公共组件
│   │   ├── CustomBreadcrumb        # 面包屑导航
│   │   └── CustomMenu              # menu 菜单
│   ├── contatiners             # 页面结构组件
│   ├── routes                  # 路由目录
│   ├── store                   # redux 配置
│   ├── style                   # 样式目录
│   ├── utils                   # 工具类
│   ├── views                   # UI 页面
│   ├── APP.js                  # App.js
│   └── index.js                # index.js
├── .prettierrc.js           # 代码规范
├── config-overrides.js      # antd 样式按需加载

вся идея

Чтобы построить любой проект, помимо аудитории, которую нужно учитывать на ранней стадии (собственно, совместимость...), плюс технический отбор, а затем уже уровень архитектуры страницы. В данном проекте ранняя стадия нам не рассматривается (установлено, что есть дрова), поэтому начинаем со структуры страницы

Проект фонового управления, независимо от того, имеет ли он функцию проверки разрешений или нет, но есть некоторые общие части, которые должны быть там. Например, целевые страницы, общедоступные заголовки, боковая панель навигации, нижняя часть и страницы ошибок. Эти общие части и разрешения特有части системы вместе составляют

После разделения такого модуля базовая структура страницы проекта завершена, потому что эта часть связана с нашим определением маршрутизации страниц в будущем, поэтому я думаю, что это очень важная часть.

маршрутизация

на основеreact-router@5.1.1

Функцию маршрутизации можно назватьReactКлюч к проекту, через предыдущее разделение архитектуры страницы, мы можем плавно прописать маршрутизацию

базовый

существуетreact-adminВ этом проекте используется<HashRouter>

Во-первых, нам нужно различать общедоступные страницы и, возможно, уникальные страницы.

<Router>
    <Switch>
        <!--精确匹配是不是在首页-->
        <Route path='/' exact render={() => <Redirect to='/index' />} /> 
        <!-- 错误页面 -->
        <Route path='/500' component={View500} />
        <Route path='/login' component={Login} />
        <Route path='/404' component={View404} />
        <!-- UI页面 -->
        <Route path='/' component={DefaultLayout} />
    </Switch>
</Router>

Затем мы можем зарегистрировать таблицу маршрутизации и зациклить ее на нашей странице области просмотра. Возможно, вы также обнаружили循环遍历Это слово, работа с массивом, означает, что мы можем выполнить ряд фильтров для него, чтобы реализовать контроль разрешений маршрутизации (мы поговорим об этом позже).

Ленивая загрузка

какSPAУ него много преимуществ (быстрая скорость отклика, хорошее разделение фронтенда и бекенда и т. д.), но есть и много недостатков.Слишком долгое время первой загрузки, с чем нам и приходится сталкиваться.

На самом деле изwebpack4.0В начале он реализовал компоненты загрузки по запросу, но также имеет некоторые свои правила (например, размер файла), поэтому нам все еще нужно выполнить некоторую обработку при первой загрузке страницы, и маршрутизация является хорошим точка входа

Этот проект используетreact-loadable, он может очень просто реализовать ленивую загрузку маршрутизации, устанавливая время задержки, загружая анимацию, рендеринг на стороне сервера и другие функции.

import Loadable from 'react-loadable';
import Loading from './my-loading-component'; // 这里可以放置你的 loading

const LoadableComponent = Loadable({
  loader: () => import('./my-component'),
  loading: Loading,
});

export default class App extends React.Component {
  render() {
    return <LoadableComponent/>;
  }
}

Конечно, вы также можете использоватьReact.lazyиSuspenseТехнологии(портал), однако он не поддерживает рендеринг на стороне сервера.

Авторизоваться

Логика входа в систему также очень проста:

Домашняя страница нашего проекта обычноindexстраница, в это время нам нужно сначала определить, находится ли пользователь в состоянии входа в систему при загрузке, если да, отобразить его в обычном режиме, если нет, он должен перейти на страницу входа.

Этот проект использует информацию для входа пользователя, хранящуюся вlocalStorageвойти, очистить при выходеlocalStorage

оtokenЕго можно хранить непосредственно локально, а время истечения срока действия можно установить в фоновом режиме.

Другая ситуация – после входа пользователя в систему, но из-за длительного бездействияtokenСрок истек, на этот раз может быть два варианта:

  • Позвольте пользователю перейти прямо на страницу входа, чтобы снова войти в систему.
  • Проверьте, сохраняется ли информация о локальном пользователе, если вы обновляетеtoken, дайте продолжить, в противном случае перейдите на страницу входа (это зависит от того, где вы храните информацию о пользователе)

Конечно, как это сделать, зависит от потребностей продукта, вот только идея.

пакет аксиом

Основная операция

Использование проектаaxiosВзаимодействуя с фоном, инкапсулированные части включают добавление перехватчиков запросов, перехватчиков ответов, настройку времени отклика и добавлениеtokenДобавить в заголовок запроса и т.д.

import axios from 'axios'

// 这里取决于登录的时候将 token 存储在哪里
const token = localStorage.getItem('token')

const instance = axios.create({
    timeout: 5000
})

// 设置post请求头
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

// 添加请求拦截器
instance.interceptors.request.use(
    config => {
        // 将 token 添加到请求头
        token && (config.headers.Authorization = token)
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

// 添加响应拦截器
instance.interceptors.response.use(
    response => {
        if (response.status === 200) {
            return Promise.resolve(response)
        } else {
            return Promise.reject(response)
        }
    },
    error => {
        // 相应错误处理
        // 比如: token 过期, 无权限访问, 路径不存在, 服务器问题等
        switch (error.response.status) {
            case 401:
                break
            case 403:
                break
            case 404:
                break
            case 500:
                break
            default:
                console.log('其他错误信息')
        }
        return Promise.reject(error)
    }
)

export default instance

не здесьbaseUrlНастроил, в основном с учетом того, что в проекте может быть не одинurl, такие как изображения, эти ресурсы могут существовать на таких серверах, как Qiniu Cloud или Alibaba Cloud, а фоновый интерфейс — это другое.url. поэтому добавилconfigфайл, экспортировать каждыйurl

// 考虑到网站可能有好几个域名,所以单独提出来

export const API = 'http://rap2api.taobao.org/app/mock/234047'

export const URLAPI = ''

При вызове интерфейса вы можете сделать это напрямую

import {API} from './api/config'
import axios from './api'

axios.get({
    url: API + '/login'
})

Конечно, если у вас нет такой необходимости, вы можете отменить его полностьюconfigЭтот файл будетbaseUrlупакованы вместе

Точно так же нет часто используемых запросов, таких какget,postИ так далее до инкапсуляции, потому что при использовании этих методов вы можете выполнять какие-то специфические операции с данными, типа сериализации и т.д., так что личное ощущение не очень значимо

перекрестный домен

Вот, кстати, запишите решение междоменной проблемы:

если вы не используетеnpm run ejectбудетwebpackКонфигурация выставлена ​​и может быть непосредственноpackage.jsonСредняя конфигурацияproxy

"proxy": {
    "/api": {
      "target": "http://100.100.100.100", //后端地址
      "changeOrigin": true
    }
 }

Это нужно толькоbaseUrlДобавьте позже/apiпросто хорошо

Конечно, если вы будетеwebpackКонфигурация в выставлена, то можно и прямо вconfigТого же эффекта можно добиться, задав настройки в файле

разрешение

Функция разрешения является неотъемлемой частью проекта управления фоном.

При нормальных обстоятельствах контроль разрешений отражается на уровне страницы и кнопки (может ли пользователь получить доступ к странице или использовать кнопку, например, добавить или удалить), это разрешение регистрируется, назначается или изменяется суперадминистратором позже. , Конечно

Реализация проекта

Используя простой контроль разрешений в этом проекте, я надеюсь дать вам некоторые идеи, конкретный метод реализации:

  • Пользователь входит в систему и получает роль (идентификатор органа) во время регистрации из фона.
  • Через идентификацию органа зарегистрированныйmenuМеню фильтруется и отображается на странице
getMenu = menu => {
        let newMenu,
            auth = JSON.parse(localStorage.getItem('user')).auth // 获取存储的用户权限标识
        if (!auth) {
            return menu
        } else {
            // 过滤注册的 menu
            newMenu = menu.filter(res => res.auth && res.auth.indexOf(auth) !== -1)
            return newMenu
        }
    }
  • Отфильтровать зарегистрированный массив маршрутов по идентификатору разрешения
{routes.map(item => {
    return (
        <Route
            key={item.path}
            path={item.path}
            exact={item.exact}
            render={props =>
                !auth ? (
                    <item.component {...props} />
                ) : item.auth && item.auth.indexOf(auth) !== -1 ? (
                    <item.component {...props} />
                ) : (
                    // 这里也可以跳转到 403 页面
                    <Redirect to='/404' {...props} />
                )
            }></Route>
    )
})}
  • Разрешение кнопки, напрямую используйте логотип разрешения, чтобы определить, можно ли выполнить операцию, скрыть или отобразить ее.

Описание: Здесь объясняется этап фильтрации зарегистрированного массива маршрутов.Как правило, интерфейсные маршруты регистрируются заранее, даже если нетmenuНавигация по меню, если мы напрямую вводим путь в адресной строке, также доступна, этого можно избежать после фильтра здесь. Конечно, мы также можем установитьМассив доступных путей, сравнивая адрес переходасуществует в этом массивеотображать соответственно

Фоновый контроль

Здесь также кратко поговорим о разрешении фонового управления, которое намного проще для внешнего интерфейса.

  • Пользователь входит в систему и получает то, что нужно отобразитьmenuМассив, отображаемый непосредственно на странице (фильтрация меню выполняется в фоновом режиме)
  • Определить, есть ли у пользователя полномочия на управление кнопкой, с помощью идентификатора разрешения.

Что касается непосредственного ввода пользователем адреса в адресной строке для доступа, то возможны две ситуации:

  • Если у пользователя нет разрешения на доступ к странице, используйте ееtokenПри запросе фоновых данных он должен быть неудачным. Мы можем инкапсулировать эту операцию вaxiosВо время запроса страница перескакивает через разные коды состояния
  • Я только что посетил незапрошенную страницу (эта страница пока недоступна для людей без разрешения), то мы блокируем ее работу, фильтруя массив разрешений

Конечно, второй случай здесь редкость...

разное

В проект также включены некоторые функциональные требования, которые могут возникнуть в обычное время.

анимация

Анимация используетAnimate.cssБиблиотека анимации, как ею пользоваться

// 下载
yarn add animate.css

// link标签引入
<link rel="stylesheet" href="animate.min.css">

// 或者 import 引入
import 'animate.css'

Затем добавьте соответствующее имя класса в нужное поле, вы можете установить анимацию входа и выхода, вы также можете установить время анимации, задержку и т. Д.

богатый текст

Редактор форматированного текста используетAntdофициально рекомендуетсяbraft-editor

на основеdraft-jsизWebБогатый текстовый редактор дляReactФреймворк, совместимый с основными современными браузерами

Как пользоваться:

// 引入
import BraftEditor from 'braft-editor'

// 可以使用 BraftEditor.createEditorState 方法来将 raw 或者 html 格式的数据转换成 editorState 数据
editorState: BraftEditor.createEditorState('你好,<b>可爱的人! 很幸运在这里与你相遇!</b>')

Для более конкретных свойств компонента и методов экземпляра вы можете обратиться к его документации.портал

echarts

echartsЯ думаю, что вы не будете незнакомы, и документация Baidu также очень понятна.Здесь предлагается в основном зафиксировать проблему, возникшую в процессе разработки.

В случае изменения окна страницы мы можем использовать

window.addEventListener('resize', function() {
    myChart.resize()
})

Этот способ гарантируетechartsнормальная адаптация

Но он не срабатывает, когда мы нажимаем кнопку уменьшения и расширения меню.window.resizeметод, на самом деле ширина поля страницы изменилась, простоechartsизresizeСобытие было инициировано и завершено. В настоящее время нам нужно толькоcomponentDidUpdateЗарегистрируйте триггер задержки таймера в этом жизненном циклеresizeИнцидент исчерпан, только не забудьтеcomponentWillUnmountОчистить этот таймер в течение жизненного цикла

индикатор загрузки

Индикатор загрузки используетnprogress, он также очень прост в использовании

// 下载
yarn add nprogress

// 引入
import NProgress from 'nprogress'

// 开始加载
NProgress.start();

// 加载结束
NProgress.done();

// 移除进度条
NProgress.remove();

полноэкранный плагин

Полноэкранная функция используетscreenfullплагин

Как пользоваться

// 下载
yarn add screenfull

if (screenfull.isEnabled) {
	screenfull.request(); // 全屏
}

.exit() // 退出
.toggle() // 可切换

Вы также можете зарегистрировать егоchangeсобытие

if (screenfull.isEnabled) {
	screenfull.on('change', () => {
		console.log('Am I fullscreen?', screenfull.isFullscreen ? 'Yes' : 'No');
	});
}

Но не забудьте удалить это событие

screenfull.off('change', callback);

Единый формат кода

Create React AppПредоставляет набор наиболее распространенных правил ошибок, при выполнении кода будут появляться сообщения об ошибках, поэтомуEslintПравила здесь не обязательны, если вы хотите еще и выдать ошибку при написании кода, то можно сделать следующие шаги:

скачатьeslint

yarn add eslint

добавить одну.eslintrc.jsфайл или вpackage.jsonв файлеeslintConfigДобавляйте нужные вам правила прямо в объект

больше правил можетобратитесь сюда

не используется в проектеeslint, только что добавленноеpretterЕдиный стиль кодирования для проектов

Как интегрироваться в проектpretter, конкретное использование может относиться кофициальная документация, здесь не описано

расширение веб-пакета

Я считаю, что при разработке такого проекта должны быть более-менее кастомизированные вещи, которые нужно дорабатыватьwebpckКонфигурация

когда мы используемcreate react appПри создании проекта,webpackКонфигурация не отображается по умолчанию. Если мы хотим изменить ее конфигурацию, мы можем использоватьyarn ejectилиnpm run ejectкоманда, чтобы открыть его, а затем изменить

Но если мы не хотим разоблачатьwebpackконфигурация, что мне делать, если я хочу ее настроить?

antdТаким образом достигается загрузка стилей по запросу.

react-app-rewiredдаreactМодификация сообщества с открытым исходным кодомCRAНастроенные инструменты, такие как расширенияCreate React AppизWebpackконфигурация, при этомcustomize-craПредоставляет набор для пользовательских эксплойтовreact-app-rewiredосновная функциональностьCreate React Appнастройку можно выполнить черезconfig-overrides.jsправо файлаwebpackконфиг для расширения

Просто: используйтеreact-app-rewiredиcustomize-craможет удовлетворить наши потребности

Как пользоваться:

  • Прежде всего, вы должны сначала загрузить эти два пакета.
  • Затем в корневом каталоге нашего проекта создайтеconfig-overrides.jsдокумент
// 文件里面这么写,比如说我们设置一个绝对路径

const { override, addWebpackAlias } = require('customize-cra')
const path = require('path')

module.exports = override(    
   addWebpackAlias({        
       ['@']: path.resolve(__dirname, 'src')   
   })
)
  • Последний отзывpackage.jsonв файлеscripts
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
}

так что мы можем с радостью использовать это в наших проектах@охватывать

Конечно,customize-craЭтот пакет также предоставляет нам множество упакованныхAPI, пожалуйстаглянь сюда

Наконец

Этот проект разрабатывается в свободное время, в основном для ознакомления сreactПроцесс разработки и использование окружающей среды, проект по-прежнему относительно прост, и на более позднем этапе будет выполняться итеративная разработка, чтобы сделать его более практичным шаблоном управления фоном.

Если вы чувствуете себя хорошо или у вас есть небольшая помощь, добро пожаловатьstar, или у вас лучше реализация, интересноidea, также можете оставить сообщение для обмена

Заинтересованные партнеры могуткликните сюда, вы также можете отсканировать QR-код ниже, чтобы подписаться на мою общедоступную учетную запись WeChat, чтобы увидеть больше видеоклипов, добро пожаловатьstarобрати внимание на

image