zoukankan      html  css  js  c++  java
  • mirrorx

    1、什么是MirrorX?

    MirrorX是基于Redux封装的一种状态机。比如实际使用的时候假设我们要从后台读取值班信息、把接口返回的数据做一些处理(按对象的类型进行分类渲染),然后将处理好的数据显示在界面上。想想就得用很多代码,而且都要放在组件的里
    要是有一个框架,组件里只需要调一行代码就能解决,是不是很不错?MirrorX就是用来做这件事的。

    2、怎么能做到1行解决?

    学过面向对象编程的,应该都知道封装性可以使控制层代码更加简练。但是React里如果要处理刚才说的那件事,既需要state和props控制权,也要知道来来往往的上下文(比如当前用户是谁、VIP等级是多少),最令React程序员难受的是,当前用户信息在UserView组件里,当前的GoodsView组件没有对UserView组件的访问权。因此,需要有一个统一的地方来跨越组件的障碍,存储这些信息,把这个机制封装好了,就可以实现一行解决。

    3、具体是怎样的机制?

    网上有很多文章讲Redux,看完Redux,再搜索MirroX就可以知道具体的机制。简单的来说,就是系统有若干个状态仓库,我们可以把上下文变量都分门别类放在不同仓库里,比如用户信息、商品信息;放入的时候都是调用动作来实现,比如读取商品信息、更改商品数量。而动作可以选择是否调用服务,如果前台更改商品数量,直接改状态仓库里的数值即可,无需调用服务;如果调用了服务,则一般来说是功能是需要服务器交互的。

     配置默认的路由方式
    mirror.defaults({ historyMode: 'hash' });

    一、简单的Model层,包含动作和模型

    model.js

    import { actions } from "mirrorx";
    import * as api from "./HttpUtils"; // 把自定义的请求文件HttpUtils.js引入进来,名称定为api
    
    export default {
        name: "GoodsManager", // 这里写的名字将会成为状态仓库的名称
        initialState: { // 这里可以写初始化时状态机里的初始状态
            userId: "0001"
        },
        // reducer:状态机处理函数
        reducers: {
            // 这个updateState是默认的,它用来主动更新状态机里的各种状态
            // state和data都是Object对象
            // state是框架传入的,开发者调用的时候,data才是对应的第一个参数
            // ...是ES6的对象扩展运算符,后面...data会自动覆盖...state的同名属性
            updateState: (state, data) => ({ ...state, ...data })
            // 后面还可以写其他的reducer,切记第一个参数一定是state
        },
        effects: {
            // 动作处理函数:获取商品
            // param是对象,getState是框架传入的函数对象,用来方便获取当前状态机的状态
            // 开发者调用的时候,不用给getState形参赋值
            async GetGoods(param, getState) {
                // Promise的同步操作运算,获取Axios返回的data
                let { data } = await api.GetGoodsApi(param);
                // 调用当前状态机的updateState方法(也就是上面写的那个函数)
                // 由调用可见,只放了一个Object类型的参数
                actions.GoodsManager.updateState({ goods: data.data });
            }
        }
    };

    实例  

    import { actions } from "mirrorx";
    import * as authService from "../services/auth";
    import Toolkit from "../utils/Toolkit";
    import set from "lodash/set";
    import "antd-mobile/lib/toast/style/css";
    import Toast from "antd-mobile/lib/toast";
    import 'antd-mobile/lib/modal/style/css';
    import Modal from 'antd-mobile/lib/modal';
    
    
    const alert = Modal.alert;
    const defaultState = {
      hddngrTypeList: [],
      msgTypeList: [],
      hiddenTrouble: null,
      isShowNextStep: false,
      isShowSelectPerson: false,
      isShowMeetHouse: false,
      getFlowCnfg: null,
      NextLink: null,
      naturalDisastersList: [],
    };
    
    export default {
      name: "report",
      initialState: defaultState,
      reducers: {
        change: (state, data) => {
          return { ...state, ...data };
        },
        reset: (state, data) => {
          return defaultState;
        },
      },
      effects: {
        // 获取编号
        async getHddngrcodes(params, getState) {
          let request = {
            project: "ccep",
            model: "model:com.chinacreator.flwmgr.base.noRule.noRule",
            action: "getBusicode",
            rtype: "e ",
            data: params,
          };
          return authService
            .postPeople(request)
            .then((data) => {
              if (data.status === "1") {
                if (data.response.flag) {
                  return data.response.value;
                }
              }
            })
            .catch((err) => {
              return { err };
            });
        },
        // 获取隐患列表
        async getNaturalDisastersList2(params, getState) {
          const loading = Toast.loading("加载中...", 30);
    
          let request = {
            project: "ccep",
            model:
              "model:com.chinacreator.xtyjoa.emergency.hddngrInfo.model.hddngrInfo",
            action: "hddngrInfoQuery",
            rtype: "e ",
            data: params,
          };
          let { naturalDisastersList } = getState().report;
    
          authService
            .postPeople(request)
            .then((data) => {
              Toast.hide(loading);
              if (data.status === "1") {
                let list = [];
                if (data.response.datas) {
                  list = naturalDisastersList;
                  if (params.pageIndex === 1) {
                    list = data.response.datas;
                  }
                  if (data.response.totalSize <= list.length) {
                    if (params.pageIndex !== 1) {
                      Toolkit.handleError({ message: "滑动到底" });
                    }
                  } else {
                    if (params.pageIndex !== 1) {
                      data.response.datas.map((item, key) => {
                        list.push(item);
                      });
                    }
                  }
                  actions.report.change({
                    naturalDisastersList: list,
                  });
                }
              }
            })
            .catch((err) => {
              Toolkit.handleError(err);
            });
        },
        // 获取自然灾害列表
        async getNaturalDisastersList(params, getState) {
            const loading = Toast.loading("加载中...", 30);
      
            let request = {
              project: "ccep",
              model:
                "model:com.chinacreator.xtyjoa.emergency.hddngrInfo.model.hddngrInfo",
              action: "hddngrInfoQuery",
              rtype: "e ",
              data: params,
            };
            let { naturalDisastersList } = getState().report;
      
            authService
              .postPeople(request)
              .then((data) => {
                Toast.hide(loading);
                let totalSize = data.response.totalSize
                if (data.status === "1") {
                  let list = [];
                  if (data.response.datas) {
                    list = naturalDisastersList;
                    if (params.pageIndex === 1) {
                      list = data.response.datas;
                    }
                    if (data.response.totalSize <= list.length) {
                      if (params.pageIndex !== 1) {
                        Toolkit.handleError({ message: "滑动到底" });
                      }
                    } else {
                      if (params.pageIndex !== 1) {
                        data.response.datas.map((item, key) => {
                          list.push(item);
                        });
                      }
                    }
                    actions.report.change({
                      naturalDisastersList: list,
                    });
                  }else {
                    if(totalSize === 0 ){
                      actions.report.change({
                        naturalDisastersList: [],
                      });
                    }
                  }
                }
              })
              .catch((err) => {
                Toolkit.handleError(err);
              });
          },
        /**
         * 隐患保存
         * @returns {Promise.<void>}
         */
        async saveHddngrData2(params, getState) {
          let savelist = {
            project: "ccep",
            model:
              "model:com.chinacreator.xtyjoa.emergency.hddngrInfo.model.hddngrInfo",
            action: params.apply_id ? "modify" : "add",
            rtype: "o",
            data: params,
          };
          authService
            .postPeople(savelist)
            .then((data) => {
              const { model } = getState().report;
              if (data.status === "1") {
                Toolkit.message("保存成功");
                set(model, "apply_id", data.response.apply_id);
                actions.report.change({
                  hiddenTrouble: data.response,
                  model,
                });
              }
            })
            .catch((err) => {
              Toolkit.handleError(err);
            });
        },
           /**
         * 自然灾害保存
         * @returns {Promise.<void>}
         */
        async saveHddngrData(params, getState) {
            let savelist = {
              project: "ccep",
              model:
                "model:com.chinacreator.xtyjoa.emergency.hddngrInfo.model.hddngrInfo",
              action: params.modify ? "modify" : "add",
              rtype: "e",
              data: params,
            };
            authService
              .postPeople(savelist)
              .then((data) => {
                const { model } = getState().report;
                if (data.status === "1") {
                  // Toolkit.message("保存成功");
                  set(model, "apply_id", data.response.apply_id);
                  actions.report.change({
                    hiddenTrouble: data.response,
                    model,
                  });
                  alert('提示', `保存成功!`, [
                    {
                        text: '确定', onPress: () => {
                         Toolkit.routeBack()
                        }
                    },
                ]);
                }
              })
              .catch((err) => {
                Toolkit.handleError(err);
              });
          },
           /**
         * 隐患删除
         * @returns {Promise.<void>}
         */
        async deleteHddngrData(params, getState) {
            let savelist = {
              project: "ccep",
              model:"model:com.chinacreator.xtyjoa.emergency.hddngrInfo.model.hddngrInfo",
              action: "remove",
              rtype: "e",
              data: params,
            };
            authService
              .postPeople(savelist)
              .then((data) => {
                const { model } = getState().report;
                if (data.status === "1") {
                  Toolkit.message("删除成功");
                }
              })
              .catch((err) => {
                Toolkit.handleError(err);
              });
          },
        /**
         * 隐患 送下一环节配置数据
         * @returns {Promise.<void>}
         */
        async getFlowStartConfig(params, getState) {
          authService
            .getFlowStartConfig(params)
            .then((data) => {
              if (data.success) {
                if (data.response != {}) {
                  actions.report.getFlowNextLink({ flowId: data.response.flow_id });
                  // actions.report.dict()
                  actions.report.getFlowCnfgs(data.response.flow_id);
                }
              }
            })
            .catch((err) => {
              Toolkit.handleError(err);
            });
        },
        /**
         * 查询流程下一环节(下一环节及处理人)
         * @returns {Promise.<void>}
         */
        async getFlowNextLink(params, getState) {
          authService
            .getFlowNextLink(params)
            .then((data) => {
              actions.report.change({
                NextLink: data.output,
              });
            })
            .catch((err) => {
              Toolkit.handleError(err);
            });
        },
        /**
         * getFlowCnfg
         * @returns {Promise.<void>}
         */
        async getFlowCnfgs(params, getState) {
          authService
            .getFlowCnfg(params)
            .then((data) => {
              if (data.status === 1) {
                actions.report.change({
                  isShowNextStep: true,
                  getFlowCnfg: data.output,
                });
              }
            })
            .catch((err) => {
              Toolkit.handleError(err);
            });
        },
        /**
         * 送下一环节提交
         * @returns {Promise.<void>}
         */
        async startFlowInst(params, getState) {
          authService
            .startFlowInst(params)
            .then((data) => {
              if (data.status === 1) {
                Toolkit.message("送下一环节成功");
                actions.report.change({
                  isShowNextStep: false,
                  hiddenTrouble: null,
                  NextLink: null,
                });
                Toolkit.routeBack();
              }
            })
            .catch((err) => {
              Toolkit.handleError(err);
            });
        },
      },
    };
    model实例

     二、改造组件,变成由MirrorX托管组件

    第一步、在项目入口的地方添加(比如在app.js上添加在内存中创建状态机的代码):

    // 引入MirrorX的组件
    import mirror from 'mirrorx';
    // 引入刚刚写的model,注意路径
    import model from './model';
    // 调用MirrorX,根据模型创建状态机
    mirror.model(model);

    实例

    import 'antd-mobile/lib/modal/style/css';
    import './index.css'
    import './assets/iconfont/iconfont.css';
    import './react-block-ui.css'
    import React from 'react'
    import mirror, { render, Router, actions } from 'mirrorx'
    import EventEmitter from 'eventemitter3'
    import VConsole from 'vconsole'
    
    import App from './App'
    import registerServiceWorker from './registerServiceWorker'
    
    import application from './models/application'
    import auth from './models/auth'
    import applyMeeting from './models/applyMeeting'
    import applyCar from './models/applyCar'
    import applyBussiTrip from './models/applyBussiTrip'
    import applyAnnualLeave from './models/applyAnnualLeave'
    import applyLeave from './models/applyLeave'
    import capitalSpending from './models/capitalSpending'
    import report from './models/report'
    import nextLink from './models/nextlink'
    // 配置默认的路由方式
    mirror.defaults({ historyMode: 'hash' });
    // 加载模型
    mirror.model(application);
    mirror.model(auth);
    mirror.model(applyMeeting);
    mirror.model(capitalSpending);
    mirror.model(applyCar);
    mirror.model(applyBussiTrip);
    mirror.model(applyAnnualLeave);
    mirror.model(applyLeave);
    mirror.model(report);
    mirror.model(nextLink);
    // 监听action 
    mirror.hook((action) => {
        const platformId = (window.cordova && window.cordova.platformId) ? window.cordova.platformId : 'windows';
        if (platformId === 'android') {
            console.log('调用方法:' + action.type);
        } else {
            console.log('%c调用方法:%s', 'color: #FF9800;font-family:source code pro;', action.type);
        }
        if (action.data) {
            if (platformId === 'android') {
                console.log('更新数据:');
            } else {
                console.log('%c更新数据:', 'color: #9C27B0;font-family:source code pro;');
            }
            console.log(action.data);
        }
        if (action.type === '@@router/LOCATION_CHANGE' && action.payload.pathname !== '/login') {
            actions.auth.change({ from: action.payload.pathname });
        }
    });
    // 初始化事件总线
    const emitter = window.emitter = new EventEmitter();
    emitter.on('RENDER', function (params) {
        if (params && params.vconsole) new VConsole();
        // 渲染到DOM节点
        render(<Router><App /></Router>, document.getElementById('root'));
    });
    registerServiceWorker();
    index.js

    第二步、在受状态机托管的组件上改一下代码

    // 增加对MirrorX的引用
    import {connect} from 'mirrorx';
    // 这里面GoodsView就是当前受状态机托管组件的class名称,GoodsManager就是第二步里name写的名字
    export default connect(state => state.GoodsManager)(GoodsView);

    实例

    import '../../../common/FormStyle.scss';
    import '../ApplyMeal/ApplyMeal.scss';
    import React, { Component } from 'react';
    import { connect, actions, model } from 'mirrorx'
    import loadable from 'common/Loadables';
    import { Flex, Box } from 'reflexbox';
    import set from 'lodash/set';
    import get from 'lodash/get';
    import map from 'lodash/map';
    
    import 'antd-mobile/lib/button/style/css';
    
    import Toolkit from "../../../utils/Toolkit";
    import moment from 'moment';
    
    import 'antd-mobile/lib/modal/style/css';
    import Modal from 'antd-mobile/lib/modal';
    // title组件
    import TitleComp from '../ApplyCommon/TitleComp';
    // 输入框
    import TextComp from '../ApplyCommon/TextComp';
    // 底部按钮
    import BottomButton from '../ApplyCommon/BottomButton';
    // 弹出窗-下一环节
    import NextStep from '../ApplyCommon/NextStep';
    
    
    const alert = Modal.alert;
    
    const NavBars = loadable(() => import('components/NavBar/index'));
    
    
    class ApplyAnnualLeave extends Component {
        constructor() {
            super();
            const userInfo = Toolkit.userInfo();
            this.state = {
                model: {
                    apply_no: '',
                    creator_account: userInfo.user_account,
                    creator_name: userInfo.user_name,
                    org_code: userInfo.org_code,
                    create_departname: userInfo.oorg_name,
                    apply_date: moment().format('YYYY-MM-DD'), //申请日期
                    join_date: '',
                    work_years: '',
                    cleave_days: '',
                    aleave_days: 0,
                    nleave_days: '',
                    leave_days: '',
                    start_date: '',
                    end_date: '',
                    is_lateleave: ['0'],
                    apply_reason: '',
                    apply_title:`${userInfo.user_name}同志${moment(new Date()).format('YYYY年MM月份')}年假审批表`
                },
                web: true,
                node: false,
                nextStepUser: [] //下一环节人
            }
        }
    
        clearData = () => {
            actions.applyAnnualLeave.change({
                isShowNextStep: false
            })
    
        }
    
        getText = (str) => {
            switch(str){
                case '0': return '草稿';
                case '1': return '进行';
            }
        }
    
        async queryAleaveDays(params) {
            const {model} = this.state;
            Toolkit.callAction({
                model: 'model:com.chinacreator.xtyjoa.vacation.model.vacationApplication',
                action: 'queryAleaveDays',
                data: params,  
            }).then((res) => {
                if(res.status === '1'){
                    let forbidArr = res.response.filter(item=>{
                        return (item.operaState === '0' && item.days > 0) || item.operaState === '1' && item.days > 0
                    })
                    if(forbidArr.length > 0){
                        alert('提示', `您当前存在${this.getText(forbidArr[0].operaState)}中的休假申请,请处理完再重新申请!`, [
                            {
                                text: '确定', onPress: () => {
                                 Toolkit.routeBack()
                                }
                            },
                        ]);
                    }else {
                        let arr = res.response.filter(item=>{
                            return item.operaState === '2'
                        })
                        this.setState({
                            model:{
                                ...model,
                                aleave_days:arr[0].days
                            }
                        })
                    }
    
                }
            }).catch((err) => {
                return err
            });
        }
    
        async componentDidMount() {
            const userInfo = Toolkit.userInfo()
            this.queryAleaveDays({
                creator_account:userInfo.user_account
            })
            this.clearData()
            actions.auth.change({
                tabTitle: '年假申请'
            })
            // 用车类型
            const carTypeList = await Toolkit.requestDict('dataenty:dataitem_root.driveType');
            map(carTypeList, item => {
                return item.label = item.text
            })
            actions.applyAnnualLeave.change({ carTypeList });
        }
    
        componentWillUnmount() {
            actions.applyAnnualLeave.reset();
        }
    
        save = async () => {
            const { model } = this.state;
    
            // 表单验证
            if(!model.join_date){
                alert('提示', `请选择参加工作时间!`, [{text: '确定', onPress: () => {}}]);
                return
            }
            if(!model.leave_days){
                alert('提示', `请填写拟休天数!`, [{text: '确定', onPress: () => {}}]);
                return
            }
            if(!model.start_date){
                alert('提示', `请选择拟休开始时间!`, [{text: '确定', onPress: () => {}}]);
                return
            }
            if(!model.end_date){
                alert('提示', `请选择拟休结束时间!`, [{text: '确定', onPress: () => {}}]);
                return
            }
            if(!model.apply_reason){
                alert('提示', `请填写申请原因!`, [{text: '确定', onPress: () => {}}]);
                return
            }
    
            if(moment(model.start_date).diff(moment(model.end_date), 'seconds') > 0){
                alert('提示', `结束时间不能小于开始时间!`, [{text: '确定', onPress: () => {}}]);
                return
            }
            const {annualLeave} = this.props.applyAnnualLeave
    
            const userInfo = Toolkit.userInfo();
            let params = {
                is_lateleave:model.is_lateleave[0],
                apply_type: '1',
                creator_name:model.creator_name,
                create_departname:model.create_departname,
                work_years:model.work_years,
                cleave_days:model.cleave_days,
                aleave_days:model.aleave_days,
                nleave_days:model.nleave_days,
                leave_days:model.leave_days,
                join_date:moment(model.join_date).format('YYYY-MM-DD'),
                start_date:moment(model.start_date).format('YYYY-MM-DD'),
                end_date:moment(model.end_date).format('YYYY-MM-DD'),
                apply_no: model.apply_no, 
                apply_reason:model.apply_reason,
                apply_date: moment().format('YYYY-MM-DD'), //申请日期
                apply_title:`${userInfo.user_name}同志${moment(new Date()).format('YYYY年MM月份')}年假审批表`,
                apply_id: annualLeave&&annualLeave.apply_id,
    
            }
    
            if(!annualLeave){
                //生成编号  
                const busiParams = {
                    no_rule_code: 'a_l_apply_no',
                    params: {
                        year: moment().format('YYYY'),
                        month: moment().format('MM'),
                        org_code: userInfo.org_code
                    }
                }
                const busicodes = await actions.applyAnnualLeave.getAnnualcodes(busiParams);
    
                if (busicodes.err) return Toolkit.handleError(busicodes.err);
                set(model, 'apply_no', busicodes);
                actions.applyAnnualLeave.change({ model })
                params = {
                    ...params,
                    apply_no: busicodes
                }
            }
    
           
            actions.applyAnnualLeave.saveAnnualData(params)
        }
    
        sendNextStep = () => {
            const userInfo = Toolkit.userInfo();
            actions.applyAnnualLeave.getFlowStartConfig({ 'flow_class_code': '0607', 'org_code': `${userInfo.org_code}` })
        }
    
        componentWillReceiveProps(newProps, newContext) {
            if (newProps.applyAnnualLeave.NextLink != this.props.applyAnnualLeave.NextLink) {
                let next_link = []
                let next_handler = []
                newProps.applyAnnualLeave.NextLink ? newProps.applyAnnualLeave.NextLink.next_link ? newProps.applyAnnualLeave.NextLink.next_link.map((item, key) => {
                    next_link.push({
                        value: item.link_id,
                        label: item.link_name,
                        id: item.link_code,
                        key: key
                    })
    
                    newProps.applyAnnualLeave.NextLink.next_handler[item.link_id].map((item, key) => {
                        next_handler.push({
                            value: item.user_account,
                            label: item.user_name,
                            id: item.user_account,
                            key: key
                        })
                    })
                }) : '' : ''
    
                this.setState({
                    next_link_value: [next_link[0].value],
                    next_link: next_link,
                    next_handler: next_handler,
                    nextStepUser: [
                        { value: next_handler[0].value, label: next_handler[0].label }
                    ]
                })
            }
        }
    
        endSave = () => {
            const { getFlowCnfg, annualLeave } = this.props.applyAnnualLeave;
            const { nextStepUser, next_link_value, note, web, model } = this.state;
    
            let transferChannels = "";
            if (note && web) {
                transferChannels = "note,web"
            } else if (note && !web) {
                transferChannels = "note"
            } else if (!note && web) {
                transferChannels = "web"
            }
            let data = {
                messageData: {
                    messageContent: JSON.stringify({
                        content: "接收到一条新的请假审批,请及时处理!",
                        action: "open_menu",
                        params: {
                            text: "请假审批",
                            url: "com.chinacreator.xtyjoa.vacation.forms.vacationAppr.html"
                        }
                    }),
                    transferChannels: transferChannels
                },
                flowData: {
                    flowId: getFlowCnfg.flow_id,
                    flowCode: getFlowCnfg.flow_code,
                    flowClass: getFlowCnfg.flow_class_code.flow_class_code,
                    flowClassSname: getFlowCnfg.flow_class_code.flow_class_shortname,
                    flowInstName: `${annualLeave.creator_name}同志年假申请表`,
                    businessId: `${annualLeave.apply_id}`,
                    businessClass: "ApproveExecuteServiceImpl",
                    businessParam: JSON.stringify({
                        election_date_time: annualLeave.election_date_time,
                        creator_name: annualLeave.creator_name,
                        apply_reason: annualLeave.apply_reason,
                        apply_id: annualLeave.apply_id,
                        flow_id: getFlowCnfg.flow_id,
                        flow_code: getFlowCnfg.flow_code,
                        flow_name: getFlowCnfg.flow_name,
                        flow_class_code: getFlowCnfg.flow_class_code.flow_class_code,
                        opera_state: '1'
                    })
                },
                approveData: {
                    nextStepLink: next_link_value[0],
                    nextStepUser: [{
                        userAccount: nextStepUser[0].value,
                        userName: nextStepUser[0].label
                    }]
                }
            }
            actions.auth.startFlowInst(data)
        }
    
        onChangeCheckboxItem = (v) => {
            const { web, note } = this.state;
            switch (v) {
                case 'web':
                    this.setState({
                        web: !web
                    })
                    break;
                case 'note':
                    this.setState({
                        note: !note
                    })
                    break;
                default:
                    break
    
            }
        }
        hideModel = () => {
            actions.applyAnnualLeave.change({
                isShowNextStep: false,
            })
        }
    
        funCallBack = () => {
            this.clearData()
            Toolkit.routeBack()
        }
    
        // 计算休假天数
        calculateDays = (year) => {
    
            if(year>=1 && year<10){
                return 5;
            }else  if(year>=10 && year<20){
                return 10;
            }else  if(year>=20){
                return 15;
            }else {
                return 0
            }
        }
    
        // 改变modeldata
        changeModelData = (v, name) => {
            const { model } = this.state;
            set(model, [name], v)
            this.setState({ model },()=>{
                if(moment(model.start_date).diff(moment(model.end_date), 'seconds') > 0){
                    alert('提示', `结束时间不能小于开始时间!`, [{text: '确定', onPress: () => {}}]);
                    return
                }
            })
    
            if (name === "join_date") {
            //计算工作年限相关
            let work_years = moment(new Date()).diff(moment(v), "years");
            this.setState({
                model: {
                ...model,
                work_years, //工作年限
                cleave_days:this.calculateDays(work_years) ,//可休
                nleave_days:work_years > 0 ?  this.calculateDays(work_years) - model.aleave_days : 0,//未休
                },
            });
            }
            
        }
        // 改变state
        changeState = (name, v) => {
            this.setState({
                [name]: v
            })
        }
        render() {
    
            const {
                model: {
                    apply_no, creator_name, create_departname,
                    join_date, work_years, cleave_days, aleave_days,
                    nleave_days, leave_days, start_date, end_date,
                    is_lateleave, apply_reason
                }, next_link, next_link_value, next_handler,
                 note, web,nextStepUser
            } = this.state;
            const {
                isShowNextStep, annualLeave,
            } = this.props.applyAnnualLeave;
    
            const isBuxiuList = [
                { value: '0', label: '' },
                { value: '1', label: '' }
            ]
            const renderData = [
                { title: '编号', type: 'readOnly', value: apply_no, name: 'apply_no' },
                { title: '姓名', type: 'readOnly', value: creator_name, name: 'creator_name' },
                { title: '科室(部门)', type: 'readOnly', value: create_departname, name: 'create_departname' },
                { title: '参加工作时间', type: 'datetime', value: join_date, name: 'join_date', mode: 'date' , required:true},
                { title: '工作年限', type: 'readOnly', value: work_years, name: 'work_years' },
                { title: '可休天数', type: 'readOnly', value: cleave_days, name: 'cleave_days' },
                { title: '已休天数', type: 'readOnly', value: aleave_days, name: 'aleave_days' },
                { title: '未休天数', type: 'readOnly', value: nleave_days, name: 'nleave_days' },
                { title: '拟休天数', type: 'input', value: leave_days, name: 'leave_days', required:true },
                { title: '拟休开始时间', type: 'datetime', value: start_date, name: 'start_date',  mode: 'date' , required:true },
                { title: '拟休结束时间', type: 'datetime', value: end_date, name: 'end_date', mode: 'date', required:true },
                { title: '是否补休', type: 'select', value: is_lateleave, name: 'is_lateleave', configs: { options: isBuxiuList }, required:true },
                { title: '申请原因', type: 'textarea', value: apply_reason, name: 'apply_reason', required:true },
            ];
            return (
                <div className={'pageMain relative FormStyle ApplyMeal'}>
                    <NavBars />
    
                    <div className={"ApplyMealBox"}>
                        <Flex>
                            <TitleComp
                                // w={2 / 8}
                                data={renderData}
                            />
                            <TextComp
                                // w={6 / 8}
                                data={renderData}
                                change={(v, name) => this.changeModelData(v, name)}
                            />
                        </Flex>
                    </div>
    
                    <NextStep
                        isShow={isShowNextStep}
                        next_link={next_link}
                        next_link_value={next_link_value}
                        next_handler={next_handler}
                        nextStepUser={nextStepUser}
                        note={note}
                        web={web}
                        onChangeCheckboxItem={this.onChangeCheckboxItem}
                        hideModel={this.hideModel}
                        endSave={this.endSave}
                        changeState={this.changeState}
                    />
    
                    <BottomButton
                        isShow={!isShowNextStep}
                        isAdd={!get(annualLeave, 'apply_id')}
                        save={this.save}
                        sendNextStep={this.sendNextStep}
                        funCallBack={this.funCallBack}
                    />
                </div>
            )
        }
    }
    
    function dispatch(state) {
        return {
            applyAnnualLeave: state.applyAnnualLeave
        }
    }
    
    export default connect(dispatch)(ApplyAnnualLeave);
    ApplyAnnualLeave.js

    三、在需要调用的地方写下如下代码:

    // 引入MirrorX的组件
    import mirror from 'mirrorx';
    // 引入刚刚写的model,注意路径
    import model from './model';
    // 调用MirrorX,根据模型创建状态机
    mirror.model(model);

    这里因为GoodsView只要一加载就需要显示商品列表,因此,我们可以把代码写在constructor(props)函数里:

    四、补充说明

    1. 状态机里所有的状态值都会被自动写在托管组件的props里,当发生变化时,也是可以从props里取出来,因此不要尝试去获取或更新组件的state。
    2. 只要状态机里的值变化,受到托管的组件会重新执行render方法,实现自动刷新。
    3. 实际开发时由于存在组件嵌套、组件元素属性值与状态机里的状态名称冲突,各种疑难杂症随之而来。介于我对于Antd、UCF等成熟框架的分析和实战,得出一个结论,大型系统的model.js、service.js一般不会超过5个,而且大多都有命名规范。
    4. 如果是看别人的代码,倒着按顺序找一遍即可,从此前端大神的代码不再难懂
  • 相关阅读:
    Ruby on Rails中的Rake教程(Rake如何把我灌醉!)
    十一、Spring Boot 集成Shiro和CAS
    Spring Boot 快速入门
    一位创业者的血泪史----献给85前创业者的反思
    罗振宇送给新员工的四句话
    Axure 入门
    XMind常用快捷方式汇总
    CAS 单点登陆
    mysql互换表中两列数据
    mysql默认安装目录说明
  • 原文地址:https://www.cnblogs.com/it-Ren/p/13660880.html
Copyright © 2011-2022 走看看