16 changed files with 422 additions and 1684 deletions
File diff suppressed because it is too large
@ -1,14 +1,19 @@ |
|||||
|
import "@/assets/style/common.scss"; |
||||
|
import store from "@/store"; |
||||
import React from "react"; |
import React from "react"; |
||||
import ReactDOM from "react-dom"; |
import ReactDOM from "react-dom"; |
||||
import "@/assets/style/common.scss"; |
|
||||
import "virtual:windi.css"; |
import {Provider} from 'react-redux' |
||||
import "virtual:windi-devtools"; |
import "virtual:windi-devtools"; |
||||
|
import "virtual:windi.css"; |
||||
|
|
||||
import Router from "./AppRouter"; |
import Router from "./AppRouter"; |
||||
|
|
||||
ReactDOM.render( |
ReactDOM.render( |
||||
<React.StrictMode> |
<React.StrictMode> |
||||
|
<Provider store={store}> |
||||
<Router></Router> |
<Router></Router> |
||||
|
</Provider> |
||||
</React.StrictMode>, |
</React.StrictMode>, |
||||
document.getElementById("root") |
document.getElementById("root") |
||||
); |
); |
||||
|
@ -0,0 +1 @@ |
|||||
|
export * from "./todo" |
@ -0,0 +1,17 @@ |
|||||
|
import {ADD, REMOVE} from "@/store/constant/todo" |
||||
|
|
||||
|
let nextTodoId = 0 |
||||
|
|
||||
|
type Action = (param: any) => IAction |
||||
|
|
||||
|
export const addTodo: Action = text => ({ |
||||
|
type: ADD, |
||||
|
id: nextTodoId++, |
||||
|
text |
||||
|
}) |
||||
|
|
||||
|
export const removeTodo: Action = id => ({ |
||||
|
type: REMOVE, |
||||
|
id: id |
||||
|
}) |
||||
|
|
@ -0,0 +1,2 @@ |
|||||
|
export const ADD = "ADD_TODO" |
||||
|
export const REMOVE = "REMOVE_TODO" |
@ -0,0 +1,8 @@ |
|||||
|
import {combineReducers, createStore} from 'redux' |
||||
|
import reducer from "./reducer" |
||||
|
|
||||
|
const reduces = combineReducers(reducer) |
||||
|
const store = createStore(reduces) |
||||
|
|
||||
|
|
||||
|
export default store |
@ -0,0 +1,5 @@ |
|||||
|
import todo from "./todo" |
||||
|
|
||||
|
export default { |
||||
|
todo |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
import {ADD, REMOVE} from "@/store/constant/todo" |
||||
|
import {combineReducers} from "redux"; |
||||
|
|
||||
|
let initData: ITodo[] = [] |
||||
|
|
||||
|
const todos = (state = initData, action: IAction) => { |
||||
|
switch (action.type) { |
||||
|
case ADD: |
||||
|
return [ |
||||
|
...state, |
||||
|
{ |
||||
|
id: action.id, |
||||
|
text: action.text |
||||
|
} |
||||
|
] |
||||
|
case REMOVE: |
||||
|
const list = state.filter(v => v.id != action.id) |
||||
|
return [ |
||||
|
...list |
||||
|
] |
||||
|
default: |
||||
|
return state |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default todos; |
@ -0,0 +1,4 @@ |
|||||
|
interface ITodo { |
||||
|
id: number; |
||||
|
text: string; |
||||
|
} |
@ -1,33 +1,94 @@ |
|||||
import React from "react"; |
import React, {useState} from "react"; |
||||
import cs from "classnames"; |
|
||||
import style from "./index.module.scss"; |
|
||||
import { Link } from "react-router-dom"; |
|
||||
|
|
||||
export default () => { |
export default () => { |
||||
console.log(style); |
const title = "秦时明月"; |
||||
|
const [leftMenuList, setLeftMenuList] = useState<any[]>([ |
||||
|
{title: "首页", path: "/"}, |
||||
|
{title: "角色", children: [{title: "月儿", path: "/about"}]}, |
||||
|
]); |
||||
|
|
||||
|
const [rightMenuList, setRightMenuList] = useState<any[]>([ |
||||
|
{ |
||||
|
title: "登录/注册", |
||||
|
click: true |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
|
function onLeftClick(e: any, menu: any, allMenu: any) { |
||||
|
if (menu.click || !menu.path) { |
||||
|
e.preventDefault(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function onRightClick(e: any, menu: any, allMenu: any) { |
||||
|
if (menu.click || !menu.path) { |
||||
|
e.preventDefault(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div className=""> |
||||
|
<div className="shadow bg-white h-12 leading-12 fixed top-0 left-0 right-0"> |
||||
|
<div className="container h-full clearfix mx-auto"> |
||||
|
<div className="h-full float-left cursor-pointer text-size-25px flex items-center"> |
||||
|
{title} |
||||
|
</div> |
||||
|
<ul className="h-full float-left ml-10"> |
||||
|
{leftMenuList.map((menu, index) => { |
||||
|
return ( |
||||
|
<li className="h-full float-left group relative" key={index}> |
||||
|
<a |
||||
|
href={menu.path ? menu.path : '#'} |
||||
|
onClick={(e) => onLeftClick(e, menu, leftMenuList)} |
||||
|
className="h-full px-5 hover:(bg-cool-gray-200 text-black) text-gray-400 text-size-14px flex items-center" |
||||
|
> |
||||
|
{menu.title} |
||||
|
</a> |
||||
|
{menu.children && menu.children.length && ( |
||||
|
<ul |
||||
|
className="absolute overflow-hidden transition-all duration-150 max-h-0 group-hover:max-h-500px left-0 top-full shadow"> |
||||
|
{menu.children.map((subMenu: any, jndex: number) => { |
||||
return ( |
return ( |
||||
<div className="h-36px leading-36px shadow bg-white fixed top-0 left-0 right-0"> |
<li key={jndex} className="float-left relative"> |
||||
<div className="container clearfix mx-auto"> |
<a |
||||
<div className={cs(style.logo, "text-size-20px leading-36px")}>秦时明月</div> |
href={subMenu.path ? subMenu.path : '#'} |
||||
<ul className={cs(style.menu, style.left)}> |
onClick={(e) => |
||||
<li className={cs(style.menuItem, style.hover)}> |
onLeftClick(e, subMenu, leftMenuList) |
||||
<div className={cs(style.menuItemText)}>首页</div> |
} |
||||
|
className="h-12 px-5 hover:(bg-cool-gray-200 text-black) text-gray-400 text-size-14px flex items-center" |
||||
|
> |
||||
|
{subMenu.title} |
||||
|
</a> |
||||
</li> |
</li> |
||||
<li className={cs(style.menuItem, style.hover)}> |
); |
||||
<div className={cs(style.menuItemText)}>主角</div> |
})} |
||||
<ul className={cs(style.subMenu)}> |
|
||||
<li className={cs(style.subMenuItem, style.hover)}>荆天明</li> |
|
||||
<li className={cs(style.subMnuItem, style.hover)}>月儿(姬如千泷)</li> |
|
||||
</ul> |
</ul> |
||||
|
)} |
||||
</li> |
</li> |
||||
|
); |
||||
|
})} |
||||
</ul> |
</ul> |
||||
<ul className={cs(style.menu, style.right)}> |
<ul className="float-right h-full"> |
||||
<li className={cs(style.menuItem)}> |
{rightMenuList.map((menu, index) => { |
||||
<div className={cs(style.menuItemText)} title="点击登录注册">登录/注册</div> |
return ( |
||||
|
<li |
||||
|
key={index} |
||||
|
className="h-full float-left relative cursor-pointer" |
||||
|
> |
||||
|
<a |
||||
|
href={menu.path ? menu.path : '#'} |
||||
|
className="h-full px-5 text-size-14px flex items-center" |
||||
|
onClick={(e) => onRightClick(e, menu, rightMenuList)} |
||||
|
> |
||||
|
{menu.title} |
||||
|
</a> |
||||
</li> |
</li> |
||||
|
); |
||||
|
})} |
||||
</ul> |
</ul> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
<div className="h-12"></div> |
||||
|
</div> |
||||
); |
); |
||||
}; |
}; |
||||
|
@ -1,42 +0,0 @@ |
|||||
.logo { |
|
||||
@apply float-left font-bold inline-block cursor-pointer; |
|
||||
} |
|
||||
|
|
||||
.menu { |
|
||||
@apply ml-[30px]; |
|
||||
} |
|
||||
|
|
||||
.menu.left { |
|
||||
@apply float-left; |
|
||||
} |
|
||||
.menu.right { |
|
||||
@apply float-right; |
|
||||
} |
|
||||
.menuItem { |
|
||||
@apply relative float-left text-gray-800; |
|
||||
} |
|
||||
|
|
||||
.menuItem.hover{ |
|
||||
@apply hover:bg-cool-gray-200 hover:text-gray-600; |
|
||||
} |
|
||||
|
|
||||
.menuItemText { |
|
||||
@apply whitespace-nowrap block px-3 cursor-pointer; |
|
||||
} |
|
||||
|
|
||||
.subMenu { |
|
||||
@apply hidden cursor-pointer rounded-b overflow-hidden; |
|
||||
} |
|
||||
.menuItem:hover { |
|
||||
.subMenu { |
|
||||
@apply absolute left-0 top-full block bg-white shadow; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.subMenuItem { |
|
||||
@apply whitespace-nowrap block px-20px text-gray-800; |
|
||||
} |
|
||||
|
|
||||
.subMenuItem.hover{ |
|
||||
@apply hover:bg-cool-gray-200 hover:text-gray-600; |
|
||||
} |
|
@ -1,30 +1,69 @@ |
|||||
import React from "react"; |
import {addTodo, removeTodo} from "@/store/action/todo"; |
||||
import style from "./index.module.scss"; |
import PropTypes from 'prop-types' |
||||
|
import React, {FormEvent, useRef} from "react"; |
||||
|
import {connect} from "react-redux"; |
||||
import Header from "./Header"; |
import Header from "./Header"; |
||||
|
|
||||
export default function (props: any) { |
function Home(props: any) { |
||||
console.log(props); |
|
||||
|
const {todo, add, remove} = props |
||||
|
const inputRef = useRef<HTMLInputElement>(null); |
||||
|
|
||||
|
function addOne(e: FormEvent) { |
||||
|
e.preventDefault() |
||||
|
let text = inputRef.current!.value |
||||
|
if (text) { |
||||
|
inputRef.current!.value = "" |
||||
|
add(text) |
||||
|
} |
||||
|
} |
||||
|
|
||||
return ( |
return ( |
||||
<div> |
<div> |
||||
<Header></Header> |
<Header></Header> |
||||
<div className="mt-36px"> |
<div> |
||||
<div className="bg-white min-h-100vh"> |
<div className="bg-white min-h-100vh"> |
||||
<div className="container clearfix mx-auto h-500px">box</div> |
<div className="container clearfix mx-auto h-500px"> |
||||
|
<form onSubmit={(e) => addOne(e)}> |
||||
|
<input ref={inputRef} type="text"/> |
||||
|
<button type="submit">添加</button> |
||||
|
</form> |
||||
|
{todo |
||||
|
.map((v: ITodo) => { |
||||
|
return <p onClick={() => remove(v.id)} key={v.id}>{v.text}{v.id}</p>; |
||||
|
})} |
||||
</div> |
</div> |
||||
<div className="min-h-100vh"> |
|
||||
|
|
||||
</div> |
</div> |
||||
|
<div className="min-h-100vh"></div> |
||||
<div className="bg-white min-h-100vh"> |
<div className="bg-white min-h-100vh"> |
||||
<div className="container clearfix mx-auto"> |
<div className="container clearfix mx-auto"> |
||||
{[...Array(100)] |
|
||||
.map((v, i) => i) |
|
||||
.map((v) => { |
|
||||
return <p key={v}>v</p>; |
|
||||
})} |
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
); |
); |
||||
} |
} |
||||
|
|
||||
|
Home.propTypes = { |
||||
|
todo: PropTypes.arrayOf(PropTypes.shape({ |
||||
|
id: PropTypes.number.isRequired, |
||||
|
text: PropTypes.string.isRequired |
||||
|
}).isRequired).isRequired, |
||||
|
add: PropTypes.func.isRequired, |
||||
|
remove: PropTypes.func.isRequired |
||||
|
} |
||||
|
|
||||
|
const mapStateToProps = (state: any) => { |
||||
|
console.log(state) |
||||
|
return { |
||||
|
todo: state.todo |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const mapDispatchToProps = (dispatch: any) => ({ |
||||
|
add: (text: string) => dispatch(addTodo(text)), |
||||
|
remove: (id: string | number) => dispatch(removeTodo(id)), |
||||
|
}) |
||||
|
|
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Home); |
||||
|
@ -0,0 +1,8 @@ |
|||||
|
|
||||
|
interface IAny{ |
||||
|
[props: string]: any; |
||||
|
} |
||||
|
|
||||
|
interface IAction extends IAny{ |
||||
|
type: string |
||||
|
} |
Loading…
Reference in new issue