mcya / JavaScriptExperience

👮 JavaScript Experience for web(JavaScript归类:简单入门+数组+经典循环+字符串+函数+Date日期+简单对象+BOM+DOM) +[ Issues(js实用技巧)]
28 stars 8 forks source link

react+antd 碎片化 #42

Open mcya opened 6 years ago

mcya commented 6 years ago

react+antd 碎片化

mcya commented 6 years ago

通过一个变量去声明函数/遍历数据

const disabledDate = (current) => {
      return current && current.valueOf() < Date.now();
    };
const loopVal = (data = []) => ((data==null || data=='' || data=='null' || data.length==0) ? null : data.map(item => {
      return (<span><span style={{ }}>{item.val}</span><br /><br /></span>);
}));

下拉框

genOptions(data = []) {
   const Option = Select.Option;
   if (data==null || data=="" || data==[] || data.length==0) {
     return
   }
   return data instanceof Array && data.length>0 && data.map((v, k) => {
     return <Option key={v.payformid} value={v.payformid}>{v.payformname}</Option>
   })
 }
{getFieldDecorator('xxa')(
      <Select>
            {::this.genOptions(this.props.queryPayFormResult.data.pay || [])}
      </Select>
 )}

树形遍历

树形遍历-项目树

mcya commented 6 years ago

关于form表单

this.props.form.setFieldsValue({}) //赋值

this.props.form.getFieldsValue() //取值

this.props.form.resetFields() //重置表单


返回清除表单内容函数

onCancel() {

  this.setState({ selectedRowKeys: [] }) //相关数据,如已勾选的数据去掉勾选

  this.props.form.resetFields(); // 重置表单
  this.props.form.setFieldsValue({ //针对性重置,如时间相关组件需针对清空方可清空
    dep_date: "", reqtime: ""
  })

  this.props.onCancel() //返回
}

验证必填选项

<Row gutter={20}>
          <Col span={20}>
            <FormItem required label="应缴团费" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
              {getFieldDecorator('seat_spay', {
                rules: [{ required: true, message: '必填!' }]
              })(
                <InputNumber step={0.0001} onChange={::this.shijiaoMoney} style={{ width: "100%" }} />
              )}
            </FormItem>
          </Col>
      </Row>

{ rules: [{ required: true, message: '必填!' }] } { rules: [{ type:number, required: true, message: '必填!' }] } { initialValue: 1, rules: [{ required: true, message: '必填!' }] }

// demo
checkSubmit() {
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.formSubmit()
      }
   })
  }
fromSubmit() {
   const formValues = this.props.form.getFieldsValue();
 }

关于onChange实时更新方案

在表单中,如果在onChange中通过this.props.form.getFieldsValue来获取change改变的值会延时一步,即取不到试试更新的值。

解决方案如下:

/* 
<Col span={12}>
  <FormItem label="客户数" labelCol={{ span: 10 }} wrapperCol={{ span: 12 }} required>
    {getFieldDecorator('cust_ownnum', { rules: [{ required: true, message: '必填!' }] })(
        <Input onChange={::this.custownnum} />
    )}
  </FormItem>
</Col>
*/

custownnum(e) { //通过 e.target.value 取值
  this.getFormChangeAction({ cust_ownnum: e.target.value })
}

getFormChangeAction(paramsObj) {
  var values = this.props.form.getFieldsValue(); //获取表单值
  var actionParams = {
    ...values,
    ...paramsObj, //覆盖取最新值
  }
}

表单日期选择,默认选择当前时间。 - {initialValue:moment(new Date(), "YYYYMM")}

<FormItem label="年月" labelCol={{ span: 10 }} wrapperCol={{ span: 12 }}>
  {getFieldDecorator('yearmonth',{initialValue:moment(new Date(), "YYYYMM")})(
    <MonthPicker size="large" format="YYYYMM" />
  )}
</FormItem>
mcya commented 5 years ago

添加多个class


<div className={value.class + " " + value.class2}>{value.value}</div>

//or
// 字符串模板
<div className={`${value.class} ${value.class2}`}>{value.value}</div>
mcya commented 5 years ago

关于时间的处理

赋值

// 赋值 - moment

// import moment from 'moment';
// package.json - "dependencies": { "moment": "^2.15.2" }

this.props.form.setFieldsValue({
  ...msgData,
  grouptype: msgData.grouptype ? Number(msgData.grouptype) : "",//select value值为数字的
  expiredate: msgData.expiredate ? moment(msgData.expiredate.split(" ")[0], "YYYY-MM-DD") : "", //年月日
  dep_period1: msgData.dep_period ? moment(msgData.dep_period.split("-")[0], 'HH:mm') : "",//时分秒
});

表单日期选择,默认选择当前时间。 - {initialValue:moment(new Date(), "YYYYMM")}

<FormItem label="年月" labelCol={{ span: 10 }} wrapperCol={{ span: 12 }}>
  {getFieldDecorator('yearmonth',{initialValue:moment(new Date(), "YYYYMM")})(
    <MonthPicker size="large" format="YYYYMM" />
  )}
</FormItem>

取值

// 取值 - format

// import _isEmpty from 'lodash/isEmpty';
// package.json - "dependencies": { "lodash": "^4.13.1" }
const values = this.props.form.getFieldsValue();

values.ret_date = (values && _isEmpty(values.ret_date)) ? "" : values.ret_date.format("YYYY-MM-DD");
values.ret_period = _isEmpty(values.ret_period) ? "" : (values.ret_period.format("HH:mm") ;
// 时间范围组件 RangePicker

// 取值 - format - [0] [1] 两部分
const value = this.props.form.getFieldsValue();
const RangePassOn = value.RangePassOn;
var endTime = '', begTime = '';
if (_isEmpty(RangePassOn) === false) {
  begTime = RangePassOn[0].format('YYYY-MM-DD');
  endTime = RangePassOn[1].format('YYYY-MM-DD');
}
mcya commented 5 years ago

关于导出的处理

// 导出demo

exportBtList({ item, key }) {
    var exportUrl = "", exportTitle = "";
    const params = this.getFormParams(); //getFormParams自定义获取参数的函数
    if (key==1) {
      exportUrl = "meansof/exportBttow.do";
      exportTitle = "报团信息"
    } else if (key==2) {
      exportUrl = "meansof/exportLxs.do";
      exportTitle = "旅行社信息"
    }
    MsgBox.confirm({
      title: '提示',
      content: '确定要导出'+exportTitle+'吗?',
      onOk: () => {
        const url =generateExportURLWeb(exportUrl, params); //提交服务端的
        // const url = generateExportURLLocal(exportUrl, params); //本地
        window.location.href = url
      }
    })
  }
// 本地导出测试

const generateExportURL = (url, params) => {
  //生成链接,uri,前面没有斜杠,也不要?号结尾,例如afterSale/loanServ/list.do
  var href = window.location.href, prefix = '';
  if (/(localhost)|(127.0.0.1)/.test(href)) { //本地
    prefix = 'http://127.0.0.1:8080/BackGround/'
  } else {
    const index = href.search('#/');
    prefix = href.substring(0, index);
  }
  let URL = prefix + url + '?';
  for (let key in params) {
    URL += key + '=' + (params[key] || '') + '&';
  }
  URL = URL.substring(0, URL.length - 1);
  return URL;
}
// 服务器上导出 - 即 打包后的

generateExportURL:(url, params)=>{ //适配https - 只在服务器上可以用
 let URL = url + '?';
 if (params && params instanceof Object) {
   for (let key in params) {
     URL += key + '=' + (params[key] || '') + '&';
   }
 }
 URL = URL.substring(0, URL.length - 1);
 return URL;
},
mcya commented 5 years ago

关于 action 多函数处理

// 调用 getRoomAndUserInfos 即执行 getRoomInfos 和 getRoomUserInfos

export function getRoomAndUserInfos(params) {
  const promise = Promise.all([Api.getRoomInfos(params), Api.getRoomUserInfos({ bldid: params.bldid })])
  return {
    type: 'afterSer.contractClaim.getRoomAndUserInfos',
    payload: {
      promise
    },
    params: {
      queryCondition: params //把查询条件传给recuder
    }
  }
}
mcya commented 5 years ago

New Menu

目录(api+action+reducer+index.js) -> router -> reducer -> index.html

1. 目录结构

├─demoSystem        #父级菜单
├─api.js 
├─action.js 
├─reducer.js 
├─demo1             #子集菜单
│ ├─index.js        #index.js必不可少
├─demo2             #子集菜单
│ ├─index.js
// api

import { Get, Post } from '../../util/xFetch';
export function actionApi(params) {
  return Post('/mulu/actionApi.do', params)
}
// action
import * as Api from './api'

export function actionApi(params) {
  return {
    type: 'demoSystem.actionApi',
    payload: {
      promise: Api.actionApi(params)
    },
    params: {
      queryCondition: params //传给reduce
    }
  }
}

// 无api
export function selfAction(params) {
  return {
    type: 'demoSystem.selfAction',
    params
  }
}
// reduce

import { createReducer } from '../../util';
import Immutable, { Map } from 'immutable';
import MsgBox from 'MsgBox';
import { message } from 'antd'

const initialState = Map({
  loading: false, //统一的 loading
  selfActionResult: {},
  actionApiResult: { success: false, data: {}, message: '', code: 0 },
})

export default createReducer(initialState, {

  'demoSystem.actionApi_PENDING': (state, data) => {
   return state.set('loading', true);
  },
  'demoSystem.actionApi_ERROR': (state, data) => {
    MsgBox.error({ content: data })
    return state.set('loading', false).set('actionApiResult', { success: false, message: data, data: {} });
  },
  'demoSystem.actionApi_SUCCESS': (state, data, params) => {
    if (params.queryCondition && params.queryCondition.searchFlage && params.queryCondition.searchFlage=="true") {
      message.success(  data.jsonResult.message )
    }
    // message.success(  data.jsonResult.message )
    return state.set('loading', false).set('actionApiResult', data.jsonResult);
  },

 'demoSystem.selfAction': (state, data, params) => {
   return state.set('selfActionResult', { success: false, message: null, data: null });
 },

});

2. routes - src/routes

// result.push
import React, { PropTypes } from 'react';
import { Route } from 'react-router';

export const generateRoutes = () => {

  const result = [];

  result.push(
    <Route key="demoSystem/demo1" path="demoSystem/demo1" getComponent={(location, cb) => {
      require.ensure([], require => {
          cb(null, require('../apps/demoSystem/demo1'))
        }, 'demoSystem')
      }}
    />
  );
  return result;
}

3. reducers - src/reducers

import AppReducer from '../apps/reducer';
import Immutable from 'immutable';
import { combineReducers } from 'redux-immutable';
import _isEmpty from 'lodash/isEmpty';
import _clone from 'lodash/clone';

const appPaths = {};
const modules = {};
const context = require.context('../apps/', true, /^\.\/.+(reducer)\.js$/);
const appkeys = context.keys();
const logModuleLoad = (name, module, isReload) => console.log(`module ${name} ${isReload ? 're' : ''}loaded !`);

appkeys.forEach((item) => {
  const parts = item.split('/');
  const module = context(item);
  modules[item] = module;
  // logModuleLoad(item,module,false);
  parts.forEach((part, index) => {
    if (part !== '.') {
      let cps = appPaths;//当前路径对象
      const cpath = ['.'];
      for (let i = 1; i < index; i++) {
        const pi = parts[i];
        cpath.push(pi);
        if (!cps[pi]) cps[pi] = {};
        cps = cps[pi];
      }
      if (index == parts.length - 1) {
        cps['reducer'] = cpath.join('/')+`/${parts[index]}`;
      }
    }
  })
});
const reducerPathMap = Immutable.fromJS(appPaths);

const getReducer = (path) => {
  const reducer = reducerPathMap.getIn(path);
  if (!reducer) {
    console.error('reducer不存在!', path)
  }
  return reducer;
}

//这里设置reducer对象树
const reducerTree = {

  demoSystem: context(getReducer(['demoSystem', 'reducer'])),

  // 子集菜单配置
  // demoSystem: combineReducers({
  //   count: context(getReducer(['demoSystem', 'demo1', 'reducer'])),
  //   reportManage: context(getReducer(['demoSystem', 'demo2', 'reducer']))
  // }),
}

export default { APP: AppReducer, ...reducerTree };

index.html

//add

<script src="./demoSystem/fkMgr.js"></script>
mcya commented 5 years ago

删除table中的某列或者删除数组中符合条件的元素

删除table中的某列或者删除数组中符合条件的元素

mcya commented 5 years ago

关于组件声明 alias.js

常规的 - 使用react的语法生成一个带dom结构的组件

class -> render() {  return ()  }

函数库 - 对象式声明

const DictUtil = {};

//订单服务状态
DictUtil.getOrderCrsstatus = function (statusCode) {
    let status;
    switch (statusCode) {
      case 'Recognitionchip':
        status = '认筹'
        break;
      case 'Reserved':
        status = '预留'
        break;
      default:
          status = ''
    }
    return status;
}

//时间格式化函数
DictUtil.dateformat = function (date, format) {
  if (date === null || date === undefined) {
    return null;
  }
  if (!(date instanceof Date)) { // date非日期对象时,自动转化为日期对象
    //解决ie和firefox浏览器下的兼容性问题
    //ps: ie和firefox下new Date()构造器不支持yyyy-mm-dd hh:mm:ss,但是支持yyyy/mm/dd hh:mm:ss
    if (typeof(date) === 'string') {
      const formatDate = date.replace(/\-/g, '/');
      date = new Date(formatDate)
    } else {
      date = new Date(date)
    }
  }
  var o = {
    "M+": date.getMonth() + 1,
    "d+": date.getDate(),
    "h+": date.getHours(),
    "m+": date.getMinutes(),
    "s+": date.getSeconds(),
    "q+": Math.floor((date.getMonth() + 3) / 3),
    "S": date.getMilliseconds()
  }
  if (/(y+)/.test(format)) {
    format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
    }
  }
  //console.log(format);
  return format;
}

export default DictUtil;
mcya commented 5 years ago

table分页参数

const pagination = {
      total: this.props.subdata.data.totalRecord,
      showSizeChanger: true,
      pageSizeOptions: ['10', '20', '30', '40', '100', '200', '500'],
      current: this.props.subpanam.currentPage,
      pageSize: this.props.subpanam.pageSize,
      showTotal: (total) => `共 ${total} 条`,
      onShowSizeChange(current, pageSize) {
        this.curr.currentPage = current;
        this.curr.pageSize = pageSize;
        // this.orderSub();
      },
      onChange(current) {
        this.curr.currentPage = current;
        // this.orderSub();
      },
      orderSub: this.props.getOrderListSub,
      curr: this.props.subpanam
    }
 pageSizeOptions: ['10', '20', '30', '40', '100', '200', '500'],