diff --git a/package.json b/package.json
index 5034f63..eaf7823 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "serve": "webpack serve --open --config webpack.dev.js",
+ "start": "webpack serve --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js",
"pre-commit": "lint-staged"
},
diff --git a/public/index.html b/public/index.html
index fecfdf5..539ace7 100644
--- a/public/index.html
+++ b/public/index.html
@@ -5,7 +5,7 @@
-
+
<%= htmlWebpackPlugin.options.title %>
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 0000000..476100a
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import Router from './router'
+
+const App = () => {
+ return
+}
+
+export default App
diff --git a/src/config/defaultApp.js b/src/config/defaultApp.js
new file mode 100644
index 0000000..a577904
--- /dev/null
+++ b/src/config/defaultApp.js
@@ -0,0 +1,15 @@
+const { RouteCode } = require('./routeConstants')
+
+module.exports = {
+ name: 'app',
+ urls: {
+ loginUrl: '/passport/login',
+ defaultUrl: '/home/index',
+ },
+ redirects: [
+ {
+ from: RouteCode.ROOT,
+ to: RouteCode.PAGE_HOME,
+ },
+ ],
+}
diff --git a/src/config/routeConstants.js b/src/config/routeConstants.js
new file mode 100644
index 0000000..f92c1d4
--- /dev/null
+++ b/src/config/routeConstants.js
@@ -0,0 +1,11 @@
+export const RoutePath = {
+ ROOT: 'layout',
+ LAYOUT_BASIC: 'layout/basic',
+ PAGE_HOME: 'page/home',
+}
+
+export const RouteCode = {
+ ROOT: 'LAYOUT',
+ LAYOUT_BASIC: 'LAYOUT_BASIC',
+ PAGE_HOME: 'PAGE_HOME',
+}
diff --git a/src/index.js b/src/index.js
index ea97850..7935655 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,13 +3,13 @@ import 'regenerator-runtime'
import React from 'react'
import ReactDOM from 'react-dom'
-import Router from './router'
+import App from './App'
import { Provider } from 'react-redux'
import store from './store'
const element = (
-
+
)
diff --git a/src/layout/index.js b/src/layout/index.js
new file mode 100644
index 0000000..15865db
--- /dev/null
+++ b/src/layout/index.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import { Outlet } from 'react-router-dom'
+
+const Layout = () => {
+ return
+}
+
+export default Layout
diff --git a/src/router/index.js b/src/router/index.js
index 77c2013..aaba76c 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,15 +1,47 @@
-import React from 'react'
-import { BrowserRouter, Route, Routes } from 'react-router-dom'
-import BasicLayout from '../layout/basic'
-import Home from '../page/home'
+import React, { lazy, Suspense } from 'react'
+import { useSelector } from 'react-redux'
+import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom'
+import Redirect from './redirect'
+import { defaultRoutes } from './routes'
+import { routerTool } from '../util/router'
const Router = () => {
+ const appUrls = useSelector((state) => state.app.urls)
+ const redirects = useSelector((state) => state.app.redirects)
+
+ const processRoutes = (params) => {
+ if (!params) return []
+ let allRedirects = routerTool.processRoutes(defaultRoutes, redirects)
+ let routes = params.map((item) => {
+ let Component = lazy(() => import(`src/${item.component}`))
+ let redirect = allRedirects.find((p) => p.from === item.code)
+ let props = {
+ element: (
+ loading}>
+
+
+
+
+ ),
+ path: item.path,
+ }
+ return (
+
+ {processRoutes(item.children)}
+
+ )
+ })
+ return routes
+ }
+
return (
- }>
- } index />
-
+ {processRoutes(defaultRoutes)}
+ }
+ />
)
diff --git a/src/router/redirect.js b/src/router/redirect.js
new file mode 100644
index 0000000..a8f8bf8
--- /dev/null
+++ b/src/router/redirect.js
@@ -0,0 +1,20 @@
+/* eslint-disable react/prop-types */
+import React, { useEffect } from 'react'
+import { generatePath, useMatch, useNavigate } from 'react-router-dom'
+
+const Redirect = (props) => {
+ const match = useMatch(props.redirect)
+ const navigate = useNavigate()
+ useEffect(() => {
+ if (props.redirect) {
+ if (match) {
+ navigate(generatePath(props.redirect, match.params))
+ } else {
+ navigate(props.redirect)
+ }
+ }
+ }, [])
+ return <>{props.children}>
+}
+
+export default Redirect
diff --git a/src/router/routes.js b/src/router/routes.js
new file mode 100644
index 0000000..52ba3ec
--- /dev/null
+++ b/src/router/routes.js
@@ -0,0 +1,26 @@
+import { RouteCode, RoutePath } from '../config/routeConstants'
+
+export const defaultRoutes = [
+ {
+ code: RouteCode.ROOT,
+ title: 'root',
+ path: '/',
+ component: RoutePath.ROOT,
+ children: [
+ {
+ code: RouteCode.LAYOUT_BASIC,
+ title: 'home',
+ path: 'home',
+ component: RoutePath.LAYOUT_BASIC,
+ children: [
+ {
+ code: RouteCode.PAGE_HOME,
+ title: 'index',
+ path: 'index',
+ component: RoutePath.PAGE_HOME,
+ },
+ ],
+ },
+ ],
+ },
+]
diff --git a/src/store/index.js b/src/store/index.js
index 4f0729c..5344590 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -2,11 +2,11 @@ import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import storageEnhancer from './enhancer/storage'
import loggerMiddleware from './middleware/logger'
+import appReducer from './reducer/app'
import countReducer from './reducer/count'
-import todoReducer from './reducer/todo'
const reducer = combineReducers({
- todo: todoReducer,
+ app: appReducer,
count: countReducer,
})
const middlewareEnhancer = applyMiddleware(loggerMiddleware, thunk)
diff --git a/src/store/reducer/app.js b/src/store/reducer/app.js
new file mode 100644
index 0000000..aca504e
--- /dev/null
+++ b/src/store/reducer/app.js
@@ -0,0 +1,18 @@
+import defaultApp from '../../config/defaultApp'
+import { copyTool } from '../../util/copy'
+import { storeTool } from '../../util/store'
+
+const fetch = async (state) => {
+ return state
+}
+
+const update = async (state, ...props) => {
+ return copyTool.merger(state, ...props)()
+}
+
+const appReducer = storeTool.createReducer(defaultApp, {
+ APP_FETCH: fetch,
+ APP_UPDATE: update,
+})
+
+export default appReducer
diff --git a/src/store/reducer/count.js b/src/store/reducer/count.js
index 53f68dd..7c2caf1 100644
--- a/src/store/reducer/count.js
+++ b/src/store/reducer/count.js
@@ -1,15 +1,15 @@
import { storeTool } from '../../util/store'
-const addCount = (countState) => {
- return countState + 1
+const addCount = (state) => {
+ return state + 1
}
-const setCount = (countState, param) => {
+const setCount = (state, param) => {
return param
}
-const delCount = (countState) => {
- return countState <= 0 ? 0 : countState - 1
+const delCount = (state) => {
+ return state <= 0 ? 0 : state - 1
}
const countReducer = storeTool.createReducer(0, {
diff --git a/src/store/reducer/todo.js b/src/store/reducer/todo.js
deleted file mode 100644
index 9a150e2..0000000
--- a/src/store/reducer/todo.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { storeTool } from '../../util/store'
-
-const addTodo = (todoState, param) => {
- const newTodo = todoState.concat(param)
- return newTodo
-}
-
-const editTodo = (todoState, param) => {
- const _index = todoState.findIndex((item) => item.id === param.id)
- if (_index < 0) return newTodo
- const newTodo = storeTool.updateItemInArray(todoState, _index, (item) => {
- return storeTool.updateObject(item, param)
- })
- return newTodo
-}
-
-const delTodo = (todoState, param) => {
- const _index = todoState.findIndex((item) => item.id === param.id)
- if (_index < 0) return newTodo
- const newTodo = todoState.splice(_index, 1)
- return newTodo
-}
-
-const todoReducer = storeTool.createReducer([{ id: 1, name: 'hello' }], {
- ADD_TODO: addTodo,
- EDIT_TODO: editTodo,
- DEL_TODO: delTodo,
-})
-
-export default todoReducer
diff --git a/src/util/copy.js b/src/util/copy.js
new file mode 100644
index 0000000..adfb6c0
--- /dev/null
+++ b/src/util/copy.js
@@ -0,0 +1,74 @@
+const defineType = (param) => {
+ let type = Object.prototype.toString.call(param)
+ return type.split(' ')[1].split(']')[0]
+}
+
+const mergeObject = (target = {}, source, isJoin, isReplace, isFilter) => {
+ for (const key in source) {
+ if (Object.hasOwnProperty.call(target, key)) {
+ if (isReplace) {
+ target[key] = source[key]
+ } else {
+ target[key] = merger(target[key], source[key])(
+ isJoin,
+ isReplace,
+ isFilter
+ )
+ }
+ } else {
+ if (isJoin) {
+ target[key] = merger(target[key], source[key])(
+ isJoin,
+ isReplace,
+ isFilter
+ )
+ }
+ }
+ }
+ return target
+}
+
+const mergeArray = (target = [], source, isJoin, isReplace, isFilter) => {
+ if (isJoin) {
+ target = [...target, ...source]
+ } else {
+ for (let i = 0; i < source.length; i++) {
+ if (isReplace) {
+ target[i] = source[i]
+ } else {
+ target[i] = merger((target && target[i]) || undefined, source[i])(
+ isJoin,
+ isReplace,
+ isFilter
+ )
+ }
+ }
+ }
+ if (isFilter) {
+ target = [...new Set(target)]
+ }
+ return target
+}
+
+const merger = (...props) => {
+ let res
+ const merge = (isJoin = true, isReplace = false, isFilter = true) => {
+ for (let i = 0; i < props.length; i++) {
+ switch (defineType(props[i])) {
+ case 'Array':
+ res = mergeArray(res, props[i], isJoin, isReplace, isFilter)
+ break
+ case 'Object':
+ res = mergeObject(res, props[i], isJoin, isReplace, isFilter)
+ break
+ default:
+ res = props[i]
+ break
+ }
+ }
+ return res
+ }
+ return merge
+}
+
+export const copyTool = { merger }
diff --git a/src/util/router.js b/src/util/router.js
new file mode 100644
index 0000000..0c4523e
--- /dev/null
+++ b/src/util/router.js
@@ -0,0 +1,33 @@
+const findPath = (params, code) => {
+ for (let i = 0; i < params.length; i++) {
+ if (params[i].code === code) {
+ return [params[i].path]
+ } else {
+ if (params[i].children) {
+ let childPath = findPath(params[i].children, code)
+ return childPath ? [params[i].path, ...childPath] : []
+ }
+ return []
+ }
+ }
+}
+
+const processRoutes = (routes, redirects) => {
+ return redirects.map((item) => {
+ let fromUrl = findPath(routes, item.from)
+ if (fromUrl.length > 0) {
+ fromUrl = fromUrl.join('/').replace('//', '/')
+ }
+ let toUrl = findPath(routes, item.to)
+ if (toUrl.length > 0) {
+ toUrl = toUrl.join('/').replace('//', '/')
+ }
+ return {
+ ...item,
+ fromUrl,
+ toUrl,
+ }
+ })
+}
+
+export const routerTool = { processRoutes }
diff --git a/src/util/store.js b/src/util/store.js
index a0146e7..ba2b944 100644
--- a/src/util/store.js
+++ b/src/util/store.js
@@ -1,20 +1,3 @@
-const updateObject = (oldVal, newVal) => {
- return Object.assign({}, oldVal, newVal)
-}
-
-const updateItemInArray = (array, index, updateCallback) => {
- const updatedArray = array.map((_item, _index) => {
- if (_index !== index) {
- return _item
- }
-
- const updatedItem = updateCallback(_item)
- return updatedItem
- })
-
- return updatedArray
-}
-
const createReducer = (initialState, handlers) => {
return function reducer(state = initialState, action) {
if (Object.prototype.hasOwnProperty.call(handlers, action.type)) {
@@ -25,4 +8,4 @@ const createReducer = (initialState, handlers) => {
}
}
-export const storeTool = { createReducer, updateObject, updateItemInArray }
+export const storeTool = { createReducer }
diff --git a/webpack.dev.js b/webpack.dev.js
index 070ef67..0bcae59 100644
--- a/webpack.dev.js
+++ b/webpack.dev.js
@@ -1,3 +1,4 @@
+const path = require('path')
const CaseSensitivePathsWebpackPlugin = require('case-sensitive-paths-webpack-plugin')
const { merge } = require('webpack-merge')
const common = require('./webpack.common')