UNPKG

q-antd

Version:

双绑形式的antd。受控组件的双绑、Form表单验证

522 lines (443 loc) 20 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _mobx = require('mobx'); var mobx = _interopRequireWildcard(_mobx); var _mobxReact = require('mobx-react'); var _moment = require('moment'); var _moment2 = _interopRequireDefault(_moment); var _warning = require('warning'); var _warning2 = _interopRequireDefault(_warning); var _coreDecorators = require('core-decorators'); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _antd = require('antd'); var _middlewareKeyCode = require('../middlewareKeyCode'); var _middlewareKeyCode2 = _interopRequireDefault(_middlewareKeyCode); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object['ke' + 'ys'](descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object['define' + 'Property'](target, property, desc); desc = null; } return desc; } /* * @Author: shiyong.yin * @Date: 2018-01-08 15:30:31 * @Last Modified by: shiyong.yin * @Description: 实现react双绑 */ /** * 思路:用mobx + hoc实现双绑 * * 问:如何解决双绑的问题 * 答:通过HOC给受控组件统一加上value和onChange回调 * * 问:关于组件联动呢 * 答:用mobx解决 * * 问:如何实现a.b.c这种动态结构的双绑 * 答:使用a.b.c作为key值新增到model中,最后输出model的时候将其扁平化即可 */ // import uniKeyProp from './uniKeyProp'; var toString = _antd.Mention.toString, toContentState = _antd.Mention.toContentState; function partOf(a, b) { return b.indexOf(a) === 0 && ['.', '['].indexOf(b[a.length]) !== -1; } function getValue(componentName, e, staticWith2Param) { var v = void 0; switch (componentName) { case 'Input': case 'TextArea': case 'RadioGroup': v = e.target.value; break; case 'Radio': case 'Checkbox': v = e.target.checked; break; case 'CheckboxGroup': case 'AutoComplete': case 'Cascader': case 'InputNumber': case 'Rate': case 'Select': case 'Slider': case 'Switch': case 'TreeSelect': case 'Transfer': v = e; break; case 'Mention': v = toString(e); break; case 'TimePicker': v = e.format('HH:mm:ss'); break; case 'PickerWrapper': if (!staticWith2Param) { v = e.format('YYYY-MM-DD'); } break; default: { v = e; var msg = '未捕获组件类型'; (0, _warning2.default)(true, msg + ': ' + componentName); break; } } return v; } exports.default = function (ComposedComponent) { var _desc, _value, _class; return (0, _mobxReact.inject)('model', 'duplexer', 'validateOnChange', 'validateOnBlur', 'getDuplexFromElement')((0, _mobxReact.observer)((_class = function (_React$Component) { _inherits(_class, _React$Component); function _class() { var _ref; var _temp, _this, _ret; _classCallCheck(this, _class); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = _class.__proto__ || Object.getPrototypeOf(_class)).call.apply(_ref, [this].concat(args))), _this), _this.expandedInitVal = '', _temp), _possibleConstructorReturn(_this, _ret); } _createClass(_class, [{ key: 'componentDidMount', value: function componentDidMount() { var _props = this.props, duplex = _props.duplex, model = _props.model; var duplexString = Array.isArray(duplex) ? duplex[0] : duplex; //向FormItem传递duplex属性 this.props.getDuplexFromElement(duplex); this.props.duplexer.push(duplexString); // 检测code是否存在 this.getKeyCodeFromProps(function (eventType, code) { (0, _middlewareKeyCode.testKeyCode)(code); }); var expanded = duplex.indexOf('.') > 0; if (expanded) { var _createKeyValueViaDot = this.createKeyValueViaDot(duplex, this.expandedInitVal), key = _createKeyValueViaDot.key, value = _createKeyValueViaDot.value; model.set(key, value); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { var duplex = this.props.duplex; var duplexString = Array.isArray(duplex) ? duplex[0] : duplex; this.props.duplexer.splice(this.props.duplexer.indexOf(duplexString), 1); } }, { key: 'isValidDuplexString', value: function isValidDuplexString(duplex) { var duplexString = Array.isArray(duplex) ? duplex[0] : duplex; return this.props.duplexer.every(function (n) { return !partOf(n, duplexString) && !partOf(duplexString, n); }); } }, { key: 'getKeyCodeFromProps', value: function getKeyCodeFromProps() { var func = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () { return 1; }; Object.keys(this.props).forEach(function (prop) { // 如果prop中含有-字符串,我们认为要进行修饰符相关的操作 if (prop.indexOf('-') > 0) { var _prop$split = prop.split('-'), _prop$split2 = _slicedToArray(_prop$split, 2), eventType = _prop$split2[0], code = _prop$split2[1]; func(eventType, code, prop); // addons[eventType] = middlewareKeyCode(code, this.props[prop]); } }); } /** * 将a.b.c形式的字符串转换成{key:a, value: {b: {c: initialValue}}} * 这样就可以set到model中了 * @param {*} str 输入字符串 * @param {*} initialValue 初始值 */ }, { key: 'createKeyValueViaDot', value: function createKeyValueViaDot(str, initialValue) { var model = this.props.model; var keys = str.split('.'); var initial = mobx.toJS(model.get(keys[0])); var middle = {}; var len = keys.length; if (len === 1) { return { key: keys[0], value: initialValue }; } for (var i = 1; i < len; i++) { var currKey = keys[i]; if (i === 1) { if (initial) { // 如果inital已经存在,也就是说model已经存在 if (initial[currKey]) { // 在现有model中已经存在currKey对象 if (len === 2) { initial[currKey] = initialValue; } // console.log(str, 'initial') middle = initial[currKey]; } else { // 处理len=2是的临界值 initial[currKey] = len === 2 ? initialValue : {}; middle = initial[currKey]; } } else { initial = {}; // 处理len=2是的临界值 initial[currKey] = len === 2 ? initialValue : {}; middle = initial[currKey]; } } else if (i === len - 1) { middle[currKey] = initialValue; } else if (middle[currKey]) { middle = middle[currKey]; } else { // console.log(str, '未定义分支') middle[currKey] = {}; middle = middle[currKey]; } } // console.log('这是', JSON.stringify(initial)) return { key: keys[0], value: initial }; } /** * 根据字符串a.b.c获取model中对应的model.a.b.c的值 * 如果是初次,取值initalValue * @param {*} str 字符创a.b.c * @param {*} originalObj js对象{a: {b: {c: ''}}} * @param {*} initialValue 初始值 */ }, { key: 'getExpandedMapValue', value: function getExpandedMapValue(str, originalObj, initialValue) { var keys = str.split('.'); var middle = null; var len = keys.length; if (len === 1) { return originalObj[keys[0]]; } for (var i = 0; i < len; i++) { var currKey = keys[i]; if (i === 0) { if (originalObj[currKey]) { middle = originalObj[currKey]; } else { middle = initialValue; break; } } else if (middle[currKey]) { middle = middle[currKey]; } else { middle = initialValue; } } return middle; } }, { key: 'render', value: function render() { var _this2 = this; /** * duplex的三种类型 * string 静态一个变量,用在Input等其中 * string, string 静态两个变量,用在rangePicker等其中 * [string, string|number] 动态两个变量,用在循环(动态增加Input等组件)中 */ var _props2 = this.props, duplex = _props2.duplex, model = _props2.model, children = _props2.children, _props2$onChange = _props2.onChange, _onChange = _props2$onChange === undefined ? function () { return 1; } : _props2$onChange, _props2$onBlur = _props2.onBlur, _onBlur = _props2$onBlur === undefined ? function () { return 1; } : _props2$onBlur, validateOnChange = _props2.validateOnChange, validateOnBlur = _props2.validateOnBlur, noDefault = _props2.noDefault, remain = _objectWithoutProperties(_props2, ['duplex', 'model', 'children', 'onChange', 'onBlur', 'validateOnChange', 'validateOnBlur', 'noDefault']); (0, _warning2.default)(this.isValidDuplexString(duplex), 'duplex的值不能是另一个duplex值得一部分,比如a和a.b不能出现在同一个form中'); // debugger var dynamic = Array.isArray(duplex); var staticWith2Param = false; var duplexValue = ''; var keys1 = void 0; var keys2 = void 0; var expanded = model.constructor.name.includes('Map'); if (dynamic) { // 动态两个变量 duplexValue = model[duplex[0]][duplex[1]]; } else if (expanded) { duplexValue = this.getExpandedMapValue(duplex, mobx.toJS(model), this.expandedInitVal); } else { // 静态一个变量 var keys = duplex.split(','); staticWith2Param = keys.length === 2; if (staticWith2Param) { keys1 = _lodash2.default.trim(keys[0]); keys2 = _lodash2.default.trim(keys[1]); } else { duplexValue = model[duplex]; } } var componentName = ComposedComponent.name; var addons = {}; var isStaticWith2Param = staticWith2Param ? Object.prototype.hasOwnProperty.call(model, keys1) && Object.prototype.hasOwnProperty.call(model, keys2) : Object.prototype.hasOwnProperty.call(model, duplex); var isDynamic = dynamic ? Object.prototype.hasOwnProperty.call(model, duplex[0]) : isStaticWith2Param; var existed = expanded ? true : isDynamic; (0, _warning2.default)(existed, duplex + ' \u4E0D\u5B58\u5728model\u4E2D'); // 注册键盘事件 this.getKeyCodeFromProps(function (eventType, code, prop) { addons[eventType] = (0, _middlewareKeyCode2.default)(code, _this2.props[prop]); }); // 双绑之去 switch (componentName) { // 双绑的是value case 'Input': case 'TextArea': case 'AutoComplete': case 'CheckboxGroup': case 'Cascader': case 'InputNumber': case 'Rate': case 'RadioGroup': case 'Select': case 'Slider': case 'TreeSelect': addons.value = mobx.toJS(duplexValue); break; // Checkbox双绑的是checked case 'Radio': case 'Checkbox': case 'Switch': addons.checked = duplexValue; break; case 'PickerWrapper': // 处理RangePicker_ if (staticWith2Param) { if (model[keys1] === '' || model[keys2] === '') { addons.value = []; } else { addons.value = [(0, _moment2.default)(model[keys1]), (0, _moment2.default)(model[keys2])]; } } else { addons.value = duplexValue ? (0, _moment2.default)(duplexValue) : duplexValue; } break; case 'TimePicker': addons.value = (0, _moment2.default)(duplexValue, 'HH:mm:ss'); break; case 'Mention': addons.value = toContentState(mobx.toJS(duplexValue)); break; case 'Transfer': addons.targetKeys = mobx.toJS(duplexValue); addons.render = function (item) { return item.title; }; break; default: { var msg = '未捕获组件类型'; (0, _warning2.default)(true, msg + ': ' + componentName); break; } } // 如果不设置默认值,将value属性清理掉,这和antd的实现有关 if (noDefault) { delete addons.value; } return _react2.default.createElement( ComposedComponent, _extends({}, remain, addons, { onBlur: function onBlur(e) { setTimeout(function () { validateOnBlur(); }); var v = void 0; if (!(componentName === 'PickerWrapper' || componentName === 'TimePicker')) { v = getValue(componentName, e, staticWith2Param); } _onBlur(v); }, onChange: function onChange(e, options) { setTimeout(function () { validateOnChange(); }); // 双绑之回 var v = getValue(componentName, e, staticWith2Param); if (staticWith2Param) { // 静态两个变量 model[keys1] = e[0] instanceof _moment2.default ? options[0] : e[0]; model[keys2] = e[1] instanceof _moment2.default ? options[1] : e[1]; } else if (dynamic) { // 动态两个变量 model[duplex[0]][duplex[1]] = v; } else if (expanded) { var _createKeyValueViaDot2 = _this2.createKeyValueViaDot(duplex, v), key = _createKeyValueViaDot2.key, value = _createKeyValueViaDot2.value; model.set(key, value); } else { // 静态一个变量或者是expanded类型 // 关于week例如2014-28th不好处理,先用date格式 model[duplex] = v; } _onChange(v); } }), _react2.default.Children.map(children, function (child, i) { /** * 当只有文本元素的时候,不能cloneElement,文本不属于Element,比如<Checkbox_>dd</Checkbox_> */ if (_react2.default.isValidElement(child)) { return _react2.default.cloneElement(child, { key: i }); } return child; }) ); } }]); return _class; }(_react2.default.Component), (_applyDecoratedDescriptor(_class.prototype, 'isValidDuplexString', [_coreDecorators.autobind], Object.getOwnPropertyDescriptor(_class.prototype, 'isValidDuplexString'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'getKeyCodeFromProps', [_coreDecorators.autobind], Object.getOwnPropertyDescriptor(_class.prototype, 'getKeyCodeFromProps'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'createKeyValueViaDot', [_coreDecorators.autobind], Object.getOwnPropertyDescriptor(_class.prototype, 'createKeyValueViaDot'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'getExpandedMapValue', [_coreDecorators.autobind], Object.getOwnPropertyDescriptor(_class.prototype, 'getExpandedMapValue'), _class.prototype)), _class))); };