day06 react创建一个后台管理项目和flux状态管理

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.使用纯函数去修改状态


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值