From 2462cfc00a3b0218b2461308d0c23af287947ad3 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Mon, 22 Apr 2019 18:01:12 +0800 Subject: [PATCH] feat(mp,h5): uni://form-field --- build/rollup.config.js | 1 + package.json | 3 +- packages/uni-app-plus/dist/index.js | 38 ++++++- packages/uni-app-plus/package.json | 2 +- packages/uni-mp-baidu/dist/index.js | 38 ++++++- packages/uni-mp-baidu/package.json | 2 +- packages/uni-mp-toutiao/dist/index.js | 38 ++++++- packages/uni-mp-toutiao/package.json | 2 +- packages/uni-mp-weixin/dist/index.js | 38 ++++++- packages/uni-mp-weixin/package.json | 2 +- src/core/runtime/wrapper/create-component.js | 4 +- src/core/runtime/wrapper/util.js | 34 +++++- src/core/view/plugins/behaviors/form-field.js | 103 ++++++++++++++++++ src/core/view/plugins/behaviors/index.js | 12 ++ src/core/view/plugins/index.js | 9 +- 15 files changed, 290 insertions(+), 36 deletions(-) create mode 100644 src/core/view/plugins/behaviors/form-field.js create mode 100644 src/core/view/plugins/behaviors/index.js diff --git a/build/rollup.config.js b/build/rollup.config.js index 94e782a9f..f261bbc7c 100644 --- a/build/rollup.config.js +++ b/build/rollup.config.js @@ -41,6 +41,7 @@ module.exports = { replace({ __GLOBAL__: platform.prefix, __PLATFORM_TITLE__: platform.title, + __PLATFORM_PREFIX__: JSON.stringify(platform.prefix), __PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM) }) ], diff --git a/package.json b/package.json index 0e017e0ff..9ab868b0b 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,8 @@ "__PLATFORM__": true, "__VERSION__": true, "__GLOBAL__": true, - "__PLATFORM_TITLE__": true + "__PLATFORM_TITLE__": true, + "__PLATFORM_PREFIX__":true }, "rules": { "no-tabs": 0, diff --git a/packages/uni-app-plus/dist/index.js b/packages/uni-app-plus/dist/index.js index b463c38d3..1fe07d7a8 100644 --- a/packages/uni-app-plus/dist/index.js +++ b/packages/uni-app-plus/dist/index.js @@ -402,8 +402,32 @@ function createObserver (name) { } } -function getBehaviors (vueExtends, vueMixins) { +function getBehaviors (vueOptions) { + const vueBehaviors = vueOptions['behaviors']; + const vueExtends = vueOptions['extends']; + const vueMixins = vueOptions['mixins']; + + let vueProps = vueOptions['props']; + + if (!vueProps) { + vueOptions['props'] = vueProps = []; + } + const behaviors = []; + if (Array.isArray(vueBehaviors)) { + vueBehaviors.forEach(behavior => { + behaviors.push(behavior.replace('uni://', `${"wx"}://`)); + if (behavior === 'uni://form-field') { + if (Array.isArray(vueProps)) { + vueProps.push('name'); + vueProps.push('value'); + } else { + vueProps['name'] = String; + vueProps['value'] = null; + } + } + }); + } if (isPlainObject(vueExtends) && vueExtends.props) { behaviors.push( Behavior({ @@ -486,6 +510,11 @@ function getProperties (props, isBehavior = false, file = '') { } function wrapper$1 (event) { + // TODO 又得兼容 mpvue 的 mp 对象 + try { + event.mp = JSON.parse(JSON.stringify(event)); + } catch (e) {} + event.stopPropagation = noop; event.preventDefault = noop; @@ -495,9 +524,6 @@ function wrapper$1 (event) { event.detail = {}; } - // TODO 又得兼容 mpvue 的 mp 对象 - event.mp = event; - if (isPlainObject(event.detail)) { event.target = Object.assign({}, event.target, event.detail); } @@ -887,9 +913,9 @@ function initVm$2 (VueComponent) { function createComponent (vueOptions) { vueOptions = vueOptions.default || vueOptions; - const properties = getProperties(vueOptions.props, false, vueOptions.__file); + const behaviors = getBehaviors(vueOptions); - const behaviors = getBehaviors(vueOptions['extends'], vueOptions['mixins']); + const properties = getProperties(vueOptions.props, false, vueOptions.__file); const VueComponent = Vue.extend(vueOptions); diff --git a/packages/uni-app-plus/package.json b/packages/uni-app-plus/package.json index d472d9106..50ba1b2b2 100644 --- a/packages/uni-app-plus/package.json +++ b/packages/uni-app-plus/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-app-plus", - "version": "0.0.227", + "version": "0.0.228", "description": "uni-app app-plus", "main": "dist/index.js", "scripts": { diff --git a/packages/uni-mp-baidu/dist/index.js b/packages/uni-mp-baidu/dist/index.js index b185b9411..a981de4e9 100644 --- a/packages/uni-mp-baidu/dist/index.js +++ b/packages/uni-mp-baidu/dist/index.js @@ -535,8 +535,32 @@ function createObserver (name) { } } -function getBehaviors (vueExtends, vueMixins) { +function getBehaviors (vueOptions) { + const vueBehaviors = vueOptions['behaviors']; + const vueExtends = vueOptions['extends']; + const vueMixins = vueOptions['mixins']; + + let vueProps = vueOptions['props']; + + if (!vueProps) { + vueOptions['props'] = vueProps = []; + } + const behaviors = []; + if (Array.isArray(vueBehaviors)) { + vueBehaviors.forEach(behavior => { + behaviors.push(behavior.replace('uni://', `${"swan"}://`)); + if (behavior === 'uni://form-field') { + if (Array.isArray(vueProps)) { + vueProps.push('name'); + vueProps.push('value'); + } else { + vueProps['name'] = String; + vueProps['value'] = null; + } + } + }); + } if (isPlainObject(vueExtends) && vueExtends.props) { behaviors.push( Behavior({ @@ -635,6 +659,11 @@ function getProperties (props, isBehavior = false, file = '') { } function wrapper$1 (event) { + // TODO 又得兼容 mpvue 的 mp 对象 + try { + event.mp = JSON.parse(JSON.stringify(event)); + } catch (e) {} + event.stopPropagation = noop; event.preventDefault = noop; @@ -654,9 +683,6 @@ function wrapper$1 (event) { } } - // TODO 又得兼容 mpvue 的 mp 对象 - event.mp = event; - if (isPlainObject(event.detail)) { event.target = Object.assign({}, event.target, event.detail); } @@ -1070,9 +1096,9 @@ function initVm$2 (VueComponent) { function createComponent (vueOptions) { vueOptions = vueOptions.default || vueOptions; - const properties = getProperties(vueOptions.props, false, vueOptions.__file); + const behaviors = getBehaviors(vueOptions); - const behaviors = getBehaviors(vueOptions['extends'], vueOptions['mixins']); + const properties = getProperties(vueOptions.props, false, vueOptions.__file); const VueComponent = Vue.extend(vueOptions); diff --git a/packages/uni-mp-baidu/package.json b/packages/uni-mp-baidu/package.json index 2f95943b3..fd9ce10f1 100644 --- a/packages/uni-mp-baidu/package.json +++ b/packages/uni-mp-baidu/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-mp-baidu", - "version": "0.0.824", + "version": "0.0.825", "description": "uni-app mp-baidu", "main": "dist/index.js", "scripts": { diff --git a/packages/uni-mp-toutiao/dist/index.js b/packages/uni-mp-toutiao/dist/index.js index 32ce4f375..7db66e24c 100644 --- a/packages/uni-mp-toutiao/dist/index.js +++ b/packages/uni-mp-toutiao/dist/index.js @@ -619,8 +619,32 @@ function createObserver (name) { } } -function getBehaviors (vueExtends, vueMixins) { +function getBehaviors (vueOptions) { + const vueBehaviors = vueOptions['behaviors']; + const vueExtends = vueOptions['extends']; + const vueMixins = vueOptions['mixins']; + + let vueProps = vueOptions['props']; + + if (!vueProps) { + vueOptions['props'] = vueProps = []; + } + const behaviors = []; + if (Array.isArray(vueBehaviors)) { + vueBehaviors.forEach(behavior => { + behaviors.push(behavior.replace('uni://', `${"tt"}://`)); + if (behavior === 'uni://form-field') { + if (Array.isArray(vueProps)) { + vueProps.push('name'); + vueProps.push('value'); + } else { + vueProps['name'] = String; + vueProps['value'] = null; + } + } + }); + } if (isPlainObject(vueExtends) && vueExtends.props) { behaviors.push( Behavior({ @@ -703,6 +727,11 @@ function getProperties (props, isBehavior = false, file = '') { } function wrapper$1 (event) { + // TODO 又得兼容 mpvue 的 mp 对象 + try { + event.mp = JSON.parse(JSON.stringify(event)); + } catch (e) {} + event.stopPropagation = noop; event.preventDefault = noop; @@ -712,9 +741,6 @@ function wrapper$1 (event) { event.detail = {}; } - // TODO 又得兼容 mpvue 的 mp 对象 - event.mp = event; - if (isPlainObject(event.detail)) { event.target = Object.assign({}, event.target, event.detail); } @@ -1078,9 +1104,9 @@ function initVm$2 (VueComponent) { function createComponent (vueOptions) { vueOptions = vueOptions.default || vueOptions; - const properties = getProperties(vueOptions.props, false, vueOptions.__file); + const behaviors = getBehaviors(vueOptions); - const behaviors = getBehaviors(vueOptions['extends'], vueOptions['mixins']); + const properties = getProperties(vueOptions.props, false, vueOptions.__file); const VueComponent = Vue.extend(vueOptions); diff --git a/packages/uni-mp-toutiao/package.json b/packages/uni-mp-toutiao/package.json index 47f0c2aa2..b9a406fff 100644 --- a/packages/uni-mp-toutiao/package.json +++ b/packages/uni-mp-toutiao/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-mp-toutiao", - "version": "0.0.322", + "version": "0.0.323", "description": "uni-app mp-toutiao", "main": "dist/index.js", "scripts": { diff --git a/packages/uni-mp-weixin/dist/index.js b/packages/uni-mp-weixin/dist/index.js index daf672760..cc49efb8b 100644 --- a/packages/uni-mp-weixin/dist/index.js +++ b/packages/uni-mp-weixin/dist/index.js @@ -419,8 +419,32 @@ function createObserver (name) { } } -function getBehaviors (vueExtends, vueMixins) { +function getBehaviors (vueOptions) { + const vueBehaviors = vueOptions['behaviors']; + const vueExtends = vueOptions['extends']; + const vueMixins = vueOptions['mixins']; + + let vueProps = vueOptions['props']; + + if (!vueProps) { + vueOptions['props'] = vueProps = []; + } + const behaviors = []; + if (Array.isArray(vueBehaviors)) { + vueBehaviors.forEach(behavior => { + behaviors.push(behavior.replace('uni://', `${"wx"}://`)); + if (behavior === 'uni://form-field') { + if (Array.isArray(vueProps)) { + vueProps.push('name'); + vueProps.push('value'); + } else { + vueProps['name'] = String; + vueProps['value'] = null; + } + } + }); + } if (isPlainObject(vueExtends) && vueExtends.props) { behaviors.push( Behavior({ @@ -503,6 +527,11 @@ function getProperties (props, isBehavior = false, file = '') { } function wrapper$1 (event) { + // TODO 又得兼容 mpvue 的 mp 对象 + try { + event.mp = JSON.parse(JSON.stringify(event)); + } catch (e) {} + event.stopPropagation = noop; event.preventDefault = noop; @@ -512,9 +541,6 @@ function wrapper$1 (event) { event.detail = {}; } - // TODO 又得兼容 mpvue 的 mp 对象 - event.mp = event; - if (isPlainObject(event.detail)) { event.target = Object.assign({}, event.target, event.detail); } @@ -907,9 +933,9 @@ function initVm$2 (VueComponent) { function createComponent (vueOptions) { vueOptions = vueOptions.default || vueOptions; - const properties = getProperties(vueOptions.props, false, vueOptions.__file); + const behaviors = getBehaviors(vueOptions); - const behaviors = getBehaviors(vueOptions['extends'], vueOptions['mixins']); + const properties = getProperties(vueOptions.props, false, vueOptions.__file); const VueComponent = Vue.extend(vueOptions); diff --git a/packages/uni-mp-weixin/package.json b/packages/uni-mp-weixin/package.json index a3a357055..4f2cdbc02 100644 --- a/packages/uni-mp-weixin/package.json +++ b/packages/uni-mp-weixin/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-mp-weixin", - "version": "0.0.946", + "version": "0.0.947", "description": "uni-app mp-weixin", "main": "dist/index.js", "scripts": { diff --git a/src/core/runtime/wrapper/create-component.js b/src/core/runtime/wrapper/create-component.js index d492e0169..f987c0177 100644 --- a/src/core/runtime/wrapper/create-component.js +++ b/src/core/runtime/wrapper/create-component.js @@ -43,9 +43,9 @@ function initVm (VueComponent) { export function createComponent (vueOptions) { vueOptions = vueOptions.default || vueOptions - const properties = getProperties(vueOptions.props, false, vueOptions.__file) + const behaviors = getBehaviors(vueOptions) - const behaviors = getBehaviors(vueOptions['extends'], vueOptions['mixins']) + const properties = getProperties(vueOptions.props, false, vueOptions.__file) const VueComponent = Vue.extend(vueOptions) diff --git a/src/core/runtime/wrapper/util.js b/src/core/runtime/wrapper/util.js index 3287d4e50..e08c4cf68 100644 --- a/src/core/runtime/wrapper/util.js +++ b/src/core/runtime/wrapper/util.js @@ -64,8 +64,32 @@ function createObserver (name) { } } -export function getBehaviors (vueExtends, vueMixins) { +export function getBehaviors (vueOptions) { + const vueBehaviors = vueOptions['behaviors'] + const vueExtends = vueOptions['extends'] + const vueMixins = vueOptions['mixins'] + + let vueProps = vueOptions['props'] + + if (!vueProps) { + vueOptions['props'] = vueProps = [] + } + const behaviors = [] + if (Array.isArray(vueBehaviors)) { + vueBehaviors.forEach(behavior => { + behaviors.push(behavior.replace('uni://', `${__PLATFORM_PREFIX__}://`)) + if (behavior === 'uni://form-field') { + if (Array.isArray(vueProps)) { + vueProps.push('name') + vueProps.push('value') + } else { + vueProps['name'] = String + vueProps['value'] = null + } + } + }) + } if (isPlainObject(vueExtends) && vueExtends.props) { behaviors.push( Behavior({ @@ -164,6 +188,11 @@ export function getProperties (props, isBehavior = false, file = '') { } function wrapper (event) { + // TODO 又得兼容 mpvue 的 mp 对象 + try { + event.mp = JSON.parse(JSON.stringify(event)) + } catch (e) {} + event.stopPropagation = noop event.preventDefault = noop @@ -183,9 +212,6 @@ function wrapper (event) { } } - // TODO 又得兼容 mpvue 的 mp 对象 - event.mp = event - if (isPlainObject(event.detail)) { event.target = Object.assign({}, event.target, event.detail) } diff --git a/src/core/view/plugins/behaviors/form-field.js b/src/core/view/plugins/behaviors/form-field.js new file mode 100644 index 000000000..56548ab86 --- /dev/null +++ b/src/core/view/plugins/behaviors/form-field.js @@ -0,0 +1,103 @@ +/** + * uni://form-field + */ +import { + hasOwn +} from 'uni-shared' + +import { + emitter +} from 'uni-mixins' + +function created () { + this.$dispatch('Form', 'uni-form-group-update', { + type: 'add', + vm: this + }) +} + +function beforeDestroy () { + this.$dispatch('Form', 'uni-form-group-update', { + type: 'remove', + vm: this + }) +} + +export default { + name: 'uni://form-field', + init (options, vm) { + if ( + !vm.constructor.options.props.name || + !vm.constructor.options.props.value + ) { // 未初始化 props + if (!vm.constructor.options.props.name) { + vm.constructor.options.props.name = options.props.name = { + type: String + } + } + if (!vm.constructor.options.props.value) { + vm.constructor.options.props.value = options.props.value = { + type: null + } + } + } + + if (!options.propsData) { + options.propsData = {} + } + + const $vnode = vm.$vnode + if ($vnode && $vnode.data && $vnode.data.attrs) { + if (hasOwn($vnode.data.attrs, 'name')) { + options.propsData.name = $vnode.data.attrs.name + } + if (hasOwn($vnode.data.attrs, 'value')) { + options.propsData.value = $vnode.data.attrs.value + } + } + + if ( + !vm.constructor.options.methods || + !vm.constructor.options.methods._getFormData + ) { // 未初始化 methods + if (!vm.constructor.options.methods) { + vm.constructor.options.methods = {} + } + + if (!options.methods) { + options.methods = {} + } + + const formMethods = { + _getFormData () { + return this.name ? { + key: this.name, + value: this.value + } : {} + }, + _resetFormData () { + this.value = '' + } + } + + Object.assign(vm.constructor.options.methods, formMethods) + Object.assign(options.methods, formMethods) + + // add $dispatch + Object.assign(vm.constructor.options.methods, emitter.methods) + Object.assign(options.methods, emitter.methods) + + const createdHooks = options['created'] + vm.constructor.options['created'] = options['created'] = + createdHooks ? [].concat(created, createdHooks) : [ + created + ] + + const beforeDestroyHooks = options['beforeDestroy'] + vm.constructor.options['beforeDestroy'] = options['beforeDestroy'] = + beforeDestroyHooks ? [].concat(beforeDestroy, beforeDestroyHooks) : [ + beforeDestroy + ] + } + } +} diff --git a/src/core/view/plugins/behaviors/index.js b/src/core/view/plugins/behaviors/index.js new file mode 100644 index 000000000..fa1a4265f --- /dev/null +++ b/src/core/view/plugins/behaviors/index.js @@ -0,0 +1,12 @@ +import formField from './form-field' + +const behaviors = { + [formField.name]: formField +} + +export default function initBehaviors (options, vm) { + options.behaviors.forEach(name => { + const behavior = behaviors[name] + behavior && behavior.init(options, vm) + }) +} diff --git a/src/core/view/plugins/index.js b/src/core/view/plugins/index.js index 643d1f08d..f0e0dccf0 100644 --- a/src/core/view/plugins/index.js +++ b/src/core/view/plugins/index.js @@ -7,6 +7,8 @@ import { processEvent } from './events' +import initBehaviors from './behaviors' + function pageMounted () { // 通知 Service,View 层已 ready UniViewJSBridge.publishHandler('onPageReady', {}, this.$page.id) @@ -34,13 +36,18 @@ export default { } } $event = processEvent.call(this, $event.type, $event, {}, target || $event.target, $event.currentTarget) - } + } return $event } Vue.mixin({ beforeCreate () { const options = this.$options + + if (options.behaviors && options.behaviors.length) { + initBehaviors(options, this) + } + if (isPage(this)) { options.mounted = options.mounted ? [].concat(pageMounted, options.mounted) : [pageMounted] } -- GitLab