diff --git a/babel.config.js b/babel.config.js index 95e2df65..77b540ae 100644 --- a/babel.config.js +++ b/babel.config.js @@ -13,7 +13,11 @@ module.exports = function (api) { } ] ]; - const plugins = ['transform-vue-jsx', '@babel/plugin-transform-runtime']; + const plugins = [ + 'transform-vue-jsx', + '@babel/plugin-transform-runtime', + '@babel/plugin-proposal-optional-chaining' + ]; const env = { 'test': { 'presets': [['@babel/preset-env', { 'targets': { 'node': 'current' }}]] diff --git a/examples/router/babel.config.js b/examples/router/babel.config.js index ed3c0c49..d116750b 100644 --- a/examples/router/babel.config.js +++ b/examples/router/babel.config.js @@ -1,5 +1,4 @@ module.exports = { - presets: [ - '@vue/app' - ] + presets: ['@vue/app'], + plugins: ['@babel/plugin-proposal-optional-chaining'] }; diff --git a/examples/router/package.json b/examples/router/package.json index e24f7e77..a2ae7406 100644 --- a/examples/router/package.json +++ b/examples/router/package.json @@ -21,18 +21,19 @@ "vue-router": "^3.0.2" }, "devDependencies": { + "@babel/plugin-proposal-optional-chaining": "^7.14.5", "@vue/cli-plugin-babel": "^3.10.0", "@vue/cli-plugin-eslint": "^3.10.0", "@vue/cli-service": "^3.10.0", "autoprefixer": "^9.6.1", "babel-eslint": "^10.0.1", "eslint": "^5.16.0", - "sass": "^1.30.0", - "eslint-plugin-vue": "^5.0.0", - "vue-template-compiler": "^2.6.10", "eslint-config-alloy": "^2.0.5", + "eslint-plugin-vue": "^5.0.0", + "sass": "^1.30.0", + "sass-loader": "^7.2.0", "vue-eslint-parser": "^6.0.4", - "sass-loader": "^7.2.0" + "vue-template-compiler": "^2.6.10" }, "eslintConfig": { "root": true, diff --git a/package.json b/package.json index bc6e31b7..a81a9e2b 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "devDependencies": { "@babel/core": "^7.4.4", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", "@babel/plugin-syntax-jsx": "^7.2.0", "@babel/plugin-transform-runtime": "^7.4.4", "@babel/preset-env": "^7.4.4", diff --git a/src/ams/mixins/field-edit-options-mixin.js b/src/ams/mixins/field-edit-options-mixin.js index 300ff365..d21ef616 100644 --- a/src/ams/mixins/field-edit-options-mixin.js +++ b/src/ams/mixins/field-edit-options-mixin.js @@ -1,3 +1,5 @@ +import { getType } from '../../utils'; + export default { data() { return { @@ -9,18 +11,30 @@ export default { isSelectAll: { set(val) { if (val) { - this.localValue = this.options.filter(item => !item.disabled).map(item => item.value); + this.localValue = this.options + .filter(item => !item.disabled) + .map(item => item.value); } else { this.localValue = []; } this.$nextTick(() => { - this.on && typeof this.on.change === 'function' && this.on.change(this.localValue); + // https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining + typeof this.on?.change === 'function' && + this.on.change(this.localValue); }); }, get() { - if (!this.localValue || this.localValue.length === 0 || !this.isShowSelectAllCheck) return false; - const allValues = this.options.filter(item => !item.disabled).map(item => item.value); - return allValues.every(item => this.localValue.indexOf(item) >= 0); + if ( + !this.localValue || + this.localValue.length === 0 || + !this.isShowSelectAllCheck + ) { return false } + const allValues = this.options + .filter(item => !item.disabled) + .map(item => item.value); + return allValues.every( + item => this.localValue.indexOf(item) >= 0 + ); } }, isShowSelectAllCheck() { @@ -31,49 +45,67 @@ export default { return field.props.multiple && field.props['select-all']; }, indeterminate() { - return Boolean(this.localValue.length && this.localValue.length < this.options.filter(item => !item.disabled).length); + return Boolean( + this.localValue.length && + this.localValue.length < + this.options.filter(item => !item.disabled).length + ); }, options() { - let options = []; - if (Array.isArray(this.field.props.options)) { - if ( - !( - this.field.useStringValue === false || - this.isSingleOptions(this.field) - ) - ) { - this.field.props.options.forEach(item => { - item.value = String(item.value); - }); - } - options = this.field.props.options; - } else if (typeof this.field.props.options === 'object') { - Object.keys(this.field.props.options).forEach(key => { - options.push({ - value: key, - label: this.field.props.options[key] - }); - }); + let options = this.field.props.options; + const type = getType(options); + switch (type) { + case 'array': + this.mayStringifyOptionValue(options); + break; + case 'object': + options = this.object2Array(options); + break; + default: + break; } - return options; } }, methods: { + /** + * 按需将option.value 转为字符串类型 + * @param {*} options + */ + mayStringifyOptionValue(options) { + // 注意这里 !== false,和默认为true是两种含义,因为有可能不配置 useStringValue,即: field = {} + // [设计原则]这里感觉设计上不合理,后期设计API需要考虑:如果用户需要,可以通过开关打开,而不是默认打开,通过开关进行关闭 + if ( + !( + this.field.useStringValue === false || + this.isSingleOptions(this.field) + ) + ) { + options.forEach(item => { + item.value = String(item.value); + }); + } + }, + /** + * 对象转数组 {value: label} => [{ label, value }] + * @param {*} optionsObj {value1: label1, value2: label2} + * @returns [{ label, value }] + */ + object2Array(optionsObj) { + return Object.entries(optionsObj).map(([key, value]) => ({ label: value, value: key })); + }, isSingleOptions(field) { - return ( - field.type === 'radio' || - (field.type === 'select' && field.props.multiple === false) - ); + const singleSelect = + field.type === 'select' && field.props.multiple === false; // 单选 + return field.type === 'radio' || singleSelect; }, initRemoteOptions(value) { - const remoteConfig = this.field.remoteConfig; - // 值为空时如果isInitEmpty为false则不请求 - if (!value && !remoteConfig.isInitEmpty || !remoteConfig.isInitRemoteOptions) { - return; + const { isInitEmpty, isInitRemoteOptions, remoteMethod } = this.field.remoteConfig; + const isInitWhenEmptyValue = !value && isInitEmpty; // // 值为空 && 允许空值检索 + if (isInitWhenEmptyValue || isInitRemoteOptions) { + this.isInitRemoteOptions = true; + remoteMethod.call(this.$block, this, value, true); } - this.isInitRemoteOptions = true; - remoteConfig.remoteMethod.call(this.$block, this, value, true); }, queryRemoteOptions(value) { const remoteConfig = this.field.remoteConfig; @@ -82,9 +114,9 @@ export default { } }, initStyle() { - if (this.$refs.select && this.$refs.select.$el) { - this.$refs.select.$el.style.width = `${this.$refs.select.$el.offsetWidth - 55}px`; - } + if (!this.$refs.select?.$el) return; + this.$refs.select.$el.style.width = `${this.$refs.select.$el + .offsetWidth - 55}px`; } },