day23笔记
一、后台管理项目(基于React)
1.1、启动数据库并启动接口项目
- 两个服务不能停
启动数据库命令: mongod --dbpath d:/mongo(文件所在目录)
启动接口项目: node app.js 默认端口号是3000
1.2、React脚手架项目进行准备工作
- 下载相关依赖
npm install(i) axios
npm instlall(i) antd
npm instlall(i) react-router-dom
- 初始化所有的整体项目(删除不必要的文件)
- 搭建所有基础的目录结构
- 创建一、二级路由
login 登录
index 主页
二级路由
manager管理员
user用户
notice通知
device 设备
1.3、一级路由的出口代码
- app.js
import React from 'react';
//引入antd.css
import 'antd/dist/antd.css'
import './App.css';
//引入一级路由
import Login from './components/pages/login'
import Index from './components/pages/index'
//引入路由插件
import {Switch,Route,Redirect } from 'react-router-dom'
function App() {
return (
<div className="App">
<Switch>
<Route path='/login' component={Login}></Route>
<Route path='/index' component={Index}></Route>
{/* 重定向到登录页面 */}
<Redirect to='/login'></Redirect>
</Switch>
</div>
);
}
export default App;
1.4、login登录页面
- login.js
import React from 'react';
//引入login.css文件
import '../../assets/css/login.css'
//引入接口文件
import api from '../../util/axios'
import { Form, Input, Button, Select,message } from 'antd';
const { Option } = Select;
class Login extends React.Component {
constructor() {
super()
this.state = {
layout: {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
},
tailLayout: {
wrapperCol: {
offset: 8,
span: 16,
},
}
}
}
//表单成功提交之后的回调函数
onFinish(values) {
console.log('Success:', values);
//调取登录接口
api.login(values)
.then(res=>{
if(res.isok){
//成功的时候跳转页面 跳转到index页面
message.success(res.info);
this.props.history.push('/index')
}else{
message.error(res.info);
}
console.log(res,'登录状态')
})
.catch(err=>{})
};
//表单失败提交之后的回调函数
onFinishFailed(errorInfo) {
console.log('Failed:', errorInfo);
};
render() {
const { layout, tailLayout } = this.state
return (
<div className="login">
<Form
{...layout}
name="basic"
initialValues={{
remember: true,
}}
onFinish={this.onFinish.bind(this)}
onFinishFailed={this.onFinishFailed.bind(this)}
className='login-form'
>
<Form.Item
name="type"
label="权限类型"
rules={[
{
required: true,
message: '请选择您的权限类型',
},
]}
>
<Select
placeholder="请选择您的权限类型"
allowClear
>
<Option value="0">超级管理员</Option>
<Option value="1">普通管理员</Option>
<Option value="2">普通用户</Option>
</Select>
</Form.Item>
<Form.Item
label="用户名"
name="name"
rules={[
{
required: true,
message: '请输入用户名!',
},
]}
>
<Input allowClear='true'/>
</Form.Item>
<Form.Item
label="密码"
name="pass"
rules={[
{
required: true,
message: '请输入你的密码!',
},
]}
>
<Input.Password allowClear='true' />
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
登录
</Button>
</Form.Item>
</Form>
</div>
);
}
}
export default Login;
1.5、index页面
- index.js
import React from 'react';
import '../../assets/css/index.css';
//引入二级路由组件
import Manager from '../views/manager'
import User from '../views/user'
import Notice from '../views/notice'
import Device from '../views/device'
//引入路由插件
import {Switch,Route,Redirect} from 'react-router-dom'
import { Layout, Menu, } from 'antd';
import {
MenuUnfoldOutlined,
MenuFoldOutlined,
UserOutlined,
VideoCameraOutlined,
SoundOutlined ,
TeamOutlined
} from '@ant-design/icons';
const { SubMenu } = Menu;
const { Header, Content, Sider } = Layout;
class Index extends React.Component {
constructor() {
super()
this.state = {
collapsed: false,
}
}
//展开收齐侧边栏
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
};
//渲染内容
getInfo(path){
this.props.history.push(path)
}
render() {
return (
<div className="index">
<Layout>
<Header className="header">
<h1 className='title'>
{React.createElement(this.state.collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
className: 'trigger',
onClick: this.toggle,
})}
<span style={{ "marginLeft": "10px" }}>后台管理系统</span>
</h1>
</Header>
<Layout className='con'>
<Sider className='sider' trigger={null} collapsible collapsed={this.state.collapsed}>
<div className="logo" />
<Menu className='sider' mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1" onClick={this.getInfo.bind(this,'/index/manager')}>
<TeamOutlined />
<span>管理员管理</span>
</Menu.Item>
<Menu.Item key="2" onClick={this.getInfo.bind(this,'/index/user')}>
<UserOutlined />
<span>用户管理</span>
</Menu.Item>
<Menu.Item key="3" onClick={this.getInfo.bind(this,'/index/notice')}>
<SoundOutlined />
<span>通知</span>
</Menu.Item>
<Menu.Item key="4" onClick={this.getInfo.bind(this,'/index/device')}>
<VideoCameraOutlined />
<span>设备</span>
</Menu.Item>
</Menu>
</Sider>
<Content
className="site-layout-background"
style={{
padding: 24,
margin: 0,
minHeight: 280,
}}
>
<Switch>
<Route path='/index/manager' component={Manager}></Route>
<Route path='/index/user' component={User}></Route>
<Route path='/index/notice' component={Notice}></Route>
<Route path='/index/device' component={Device}></Route>
<Redirect to='/index/manager'></Redirect>
</Switch>
</Content>
</Layout>
</Layout>
</div>
);
}
}
export default Index;
1.6、Manager页面
import React from 'react';
import api from '../../util/axios'
import { Table, Button ,message} from 'antd';
class manager extends React.Component {
constructor() {
super()
this.state = {
columns: [
{ title: '账户', dataIndex: 'name', key: 'name' },
{ title: '密码', dataIndex: 'pass', key: 'pass' },
{ title: '属性', dataIndex: 'prop', key: 'prop' },
{ title: '时间', dataIndex: 'time', key: 'time' },
{
title: '操作',
dataIndex: '',
key: 'x',
render: () => <div>
<Button type="primary" >
查看
</Button>
<Button type="primary" danger>
删除
</Button>
</div>
},
],
data: []
}
}
componentDidMount(){//挂载的生命周期函数
api.findManager()
.then(res=>{
if(res.isok){
message.success(res.info);
this.setState({
data:res.data
})
}else{
message.error(res.info);
}
})
.catch(err=>{
})
}
render() {
const { columns, data } = this.state
return (
<div className="App">
<Button type="primary" >
新增
</Button>
<Table
columns={columns}
dataSource={data}
/>
</div>
);
}
}
export default manager;
二、UI库(移动端)
antd-mobile 是 Ant Design 的移动规范的 React 实现,服务于蚂蚁及口碑无线业务。
- 特点和优势
UI 样式高度可配置,拓展性更强,轻松适应各类产品风格
基于 React Native 的 iOS / Android / Web 多平台支持,组件丰富、能全面覆盖各类场景 (antd-mobile-rn)
提供 “组件按需加载” / “Web 页面高清显示” / “SVG Icon” 等优化方案,一体式开发
使用 TypeScript 开发,提供类型定义文件,支持类型及属性智能提示,方便业务开发
全面兼容 react / preact
- 适用场景
适合于中大型产品应用
适合于基于 react / preact / react-native 的多终端应用
适合不同 UI 风格的高度定制需求的应用
- 安装方式
npm install(i) antd-mobile
- 官网地址
https://mobile.ant.design/index-cn
三、Flux
- 回顾vuex(大型状态管理)
- store
state 状态
getters 相当于计算属性
mutation 转变 它是唯一修改state状态的方法 同步方法
actions 行动,这里面调用了大量异步操作(接口)action =>dispatch =>commit(mutation)
modules 都含有所有的vuex的属性
- 流程
state=> getters(view) => action发起一个行动(dispatch)=>commit (mutation) =>mutate(state) =>view(变更)
- 下载并安装
npm install(i) flux
- flux
flux是一种设计模式或者说是框架。
以mvc模式来划分的话react是mvc中的view, flux相当于mc,m就是model c就是control
flux包含四个部分 Store、Dispatch、Action、View,其中Store就对应着model,Dispatch、Action就组合成了Control
Store => state =>view
修改 state状态
发起一个行动action =>dispatch(type类型 行动的名称或者叫类型,payload参数)
3.2创建一个 flux模型(不成立)
- 创建一个仓库(Store=>index.js)
③ 引入派发器
import {Dispatcher} from 'flux'
④//实例化派发器
const dispatcher = new Dispatcher()
⑤//注册行动 action(type,payload) 行动我分成类型和参数 行动具体有多少不确定 用来区分每一个行动 我们可以用switch case
dispatcher.register((action) => {
switch (action.type) {
case 'changeMsg':
state.msg = action.payload//'是和你一起躲过的屋檐'
break;
default:
break;
}
})
① 创建一个 state状态
const state = {
msg:''
}
②暴露出
export default {
state,
dispatcher
}
3.3创建一个 flux模型(成立)
//1、引用一个派发器
import { Dispatcher } from 'flux'
//4、引用事件触发器
import EventEmitter from 'events'
//5、创建一个子类去继承EventEmitter所有的属性和方法
class State extends EventEmitter {
constructor() {
super()
this.msg = '最美不是下雨天'
this.num = 10
this.likeList = []
}
}
//6、实例化这个子类
const state = new State()
//2、实例化派发器
const dispatcher = new Dispatcher()
console.log(dispatcher, '实例化之后的内容')
//3、注册行动 action(type,payload) 行动我分成类型和参数 行动具体有多少不确定 用来区分每一个行动 我们可以用switch case
dispatcher.register((action) => {
console.log(action, '组件派发的行动')
switch (action.type) {
case 'changeMsg':
console.log(state, '拥有触发器的属性和方法')
state.msg = action.payload//'是和你一起躲过的屋檐'
state.emit('change')
break;
case 'cNum':
state.num += action.payload
state.emit('change')
break;
case 'like':
//判断这个喜欢的列表是否已存在,如果已存在就返回
if (state.likeList.some(item => item.id === action.payload.id)) {
alert('当前歌曲已存在')
return
}
state.likeList.push(action.payload)
state.emit('liked')
break;
case 'nolike':
//获取当前数据对象的id
let id = action.payload
//获取不喜欢数据索引
let index = state.likeList.findIndex(item=>item.id ==id)
//删除
state.likeList.splice(index,1)
state.emit('liked')
break;
default:
break;
}
})
//8、getter(假装)
export let getNum = () => state.num
export let getLikeList = state.likeList
//7、导出state状态
export default {
state,
dispatcher
}
Redux
Redux 是 JavaScript 状态容器,提供可预测化的状态管理.
1.单一数据源(state)
整个应用状态,都应该被存储在单一store的对象树中。
2.只读状态
唯一可以修改状态的方式,就是发送(dispatch)一个动作(Action),通俗来讲,就是说只有getter,没有setter。
3.使用纯函数去修改状态