feat: update vc-form

pull/165/head
tangjinzhou 2018-05-03 19:10:43 +08:00
parent 01980821f6
commit 81048b901c
9 changed files with 743 additions and 654 deletions

View File

@ -7,6 +7,7 @@ module.exports = function (modules) {
require.resolve('babel-plugin-transform-es3-property-literals'),
require.resolve('babel-plugin-transform-object-assign'),
require.resolve('babel-plugin-transform-object-rest-spread'),
require.resolve('babel-plugin-transform-class-properties'),
]
plugins.push([require.resolve('babel-plugin-transform-runtime'), {
polyfill: false,

View File

@ -0,0 +1,66 @@
/* eslint no-console:0 */
import { createForm } from '../index'
import { regionStyle } from './styles'
let uuid = 0
const Form = {
props: {
form: Object,
},
methods: {
remove (k) {
const { form } = this
// can use data-binding to get
let keys = form.getFieldValue('keys')
keys = keys.filter((key) => {
return key !== k
})
// can use data-binding to set
form.setFieldsValue({
keys,
})
},
add () {
uuid++
const { form } = this
// can use data-binding to get
let keys = form.getFieldValue('keys')
keys = keys.concat(uuid)
// can use data-binding to set
// important! notify form to detect changes
form.setFieldsValue({
keys,
})
},
submit (e) {
e.preventDefault()
console.log(this.form.getFieldsValue())
},
},
render () {
const { getFieldProps, getFieldValue } = this.form
getFieldProps('keys', {
initialValue: [],
})
const inputs = getFieldValue('keys').map((k) => {
return (<div key={k} style={ regionStyle }>
<input {...getFieldProps(`name${k}`)}/>
<a
onClick={this.remove.bind(this, k)}
>delete</a></div>)
})
return (<div>
{inputs}
<div style={ regionStyle }>
<button onClick={this.submit}>submit</button>
<button onClick={this.add}>add</button>
</div>
</div>)
},
}
export default createForm()(Form)

View File

@ -0,0 +1,11 @@
export const regionStyle = {
border: '1px solid red',
marginTop: '10px',
padding: '10px',
}
export const errorStyle = {
color: 'red',
marginTop: '10px',
padding: '10px',
}

View File

@ -1,10 +1,11 @@
import createReactClass from 'create-react-class'
import AsyncValidator from 'async-validator'
import warning from 'warning'
import get from 'lodash/get'
import set from 'lodash/set'
import createFieldsStore from './createFieldsStore'
import { cloneElement } from '../../_util/vnode'
import BaseMixin from '../../_util/BaseMixin'
import PropTypes from '../../_util/vue-types'
import {
argumentContainer,
identity,
@ -35,11 +36,14 @@ function createBaseForm (option = {}, mixins = []) {
} = option
return function decorate (WrappedComponent) {
const Form = createReactClass({
mixins,
getInitialState () {
const fields = mapPropsToFields && mapPropsToFields(this.props)
const Form = {
mixins: [BaseMixin, ...mixins],
props: {
hideRequiredMark: PropTypes.bool,
layout: PropTypes.string,
},
data () {
const fields = mapPropsToFields && mapPropsToFields(this.$props)
this.fieldsStore = createFieldsStore(fields || {})
this.instances = {}
@ -56,13 +60,6 @@ function createBaseForm (option = {}, mixins = []) {
'isFieldsTouched',
'isFieldTouched'].forEach(key => {
this[key] = (...args) => {
if (process.env.NODE_ENV !== 'production') {
warning(
false,
'you should not use `ref` on enhanced form, please use `wrappedComponentRef`. ' +
'See: https://github.com/react-component/form#note-use-wrappedcomponentref-instead-of-withref-after-rc-form140'
)
}
return this.fieldsStore[key](...args)
}
})
@ -71,13 +68,17 @@ function createBaseForm (option = {}, mixins = []) {
submitting: false,
}
},
componentWillReceiveProps (nextProps) {
watch: {
'$props': {
handler: function (nextProps) {
if (mapPropsToFields) {
this.fieldsStore.updateFields(mapPropsToFields(nextProps))
}
},
deep: true,
},
},
methods: {
onCollectCommon (name, action, args) {
const fieldMeta = this.fieldsStore.getFieldMeta(name)
if (fieldMeta[action]) {
@ -147,7 +148,7 @@ function createBaseForm (option = {}, mixins = []) {
},
getFieldDecorator (name, fieldOption) {
const props = this.getFieldProps(name, fieldOption)
const { ref, ...restProps } = this.getFieldProps(name, fieldOption)
return (fieldElem) => {
const fieldMeta = this.fieldsStore.getFieldMeta(name)
const originalProps = fieldElem.props
@ -171,8 +172,11 @@ function createBaseForm (option = {}, mixins = []) {
fieldMeta.originalProps = originalProps
fieldMeta.ref = fieldElem.ref
return cloneElement(fieldElem, {
...props,
props: {
...restProps,
...this.fieldsStore.getFieldValuePropValue(fieldMeta),
},
ref,
})
}
},
@ -216,8 +220,25 @@ function createBaseForm (option = {}, mixins = []) {
const inputProps = {
...this.fieldsStore.getFieldValuePropValue(fieldOption),
ref: this.getCacheBind(name, `${name}__ref`, this.saveRef),
ref: name,
}
const saveRef = this.getCacheBind(name, `${name}__ref`, this.saveRef)
this.$nextTick(() => {
if (this.instances[name] !== this.$refs[name]) {
this.$refs[name].destroyed = () => {
this.$refs[name].destroyed()
// after destroy, delete data
this.clearedFieldMetaCache[name] = {
field: this.fieldsStore.getField(name),
meta: this.fieldsStore.getFieldMeta(name),
}
this.fieldsStore.clearField(name)
delete this.instances[name]
delete this.cachedBind[name]
}
}
saveRef(name, `${name}__ref`, this.$refs[name])
})
if (fieldNameProp) {
inputProps[fieldNameProp] = name
}
@ -314,17 +335,6 @@ function createBaseForm (option = {}, mixins = []) {
},
saveRef (name, _, component) {
if (!component) {
// after destroy, delete data
this.clearedFieldMetaCache[name] = {
field: this.fieldsStore.getField(name),
meta: this.fieldsStore.getFieldMeta(name),
}
this.fieldsStore.clearField(name)
delete this.instances[name]
delete this.cachedBind[name]
return
}
this.recoverClearedField(name)
const fieldMeta = this.fieldsStore.getFieldMeta(name)
if (fieldMeta) {
@ -475,7 +485,7 @@ function createBaseForm (option = {}, mixins = []) {
'Actually, it\'s more convenient to handle submitting status by yourself.'
)
}
return this.state.submitting
return this.submitting
},
submit (callback) {
@ -496,31 +506,27 @@ function createBaseForm (option = {}, mixins = []) {
})
callback(fn)
},
},
render () {
const { wrappedComponentRef, ...restProps } = this.props
const { $props, $listeners } = this
const formProps = {
[formPropName]: this.getForm(),
}
if (withRef) {
if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
warning(
false,
'`withRef` is deprecated, please use `wrappedComponentRef` instead. ' +
'See: https://github.com/react-component/form#note-use-wrappedcomponentref-instead-of-withref-after-rc-form140'
)
}
formProps.ref = 'wrappedComponent'
} else if (wrappedComponentRef) {
formProps.ref = wrappedComponentRef
}
const props = mapProps.call(this, {
const wrappedComponentProps = {
props: mapProps.call(this, {
...formProps,
...restProps,
})
return <WrappedComponent {...props}/>
...$props,
}),
on: $listeners,
}
if (withRef) {
wrappedComponentProps.ref = 'wrappedComponent'
}
return <WrappedComponent {...wrappedComponentProps}/>
},
})
}
return argumentContainer(Form, WrappedComponent)
}

View File

@ -49,6 +49,7 @@ function getScrollableContainer (n) {
}
const mixin = {
methods: {
getForm () {
return {
...formMixin.getForm.call(this),
@ -93,6 +94,8 @@ const mixin = {
return this.validateFields(names, options, newCb)
},
},
}
function createDOMForm (option) {

View File

@ -1,6 +1,7 @@
import createBaseForm from './createBaseForm'
export const mixin = {
methods: {
getForm () {
return {
getFieldsValue: this.fieldsStore.getFieldsValue,
@ -23,6 +24,7 @@ export const mixin = {
resetFields: this.resetFields,
}
},
},
}
function createForm (options) {

View File

@ -1,14 +1,13 @@
import hoistStatics from 'hoist-non-react-statics'
function getDisplayName (WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'WrappedComponent'
return WrappedComponent.name || 'WrappedComponent'
}
export function argumentContainer (Container, WrappedComponent) {
/* eslint no-param-reassign:0 */
Container.displayName = `Form(${getDisplayName(WrappedComponent)})`
Container.name = `Form_${getDisplayName(WrappedComponent)}`
Container.WrappedComponent = WrappedComponent
return hoistStatics(Container, WrappedComponent)
Container.methods = { ...Container.methods, ...WrappedComponent.methods }
return Container
}
export function identity (obj) {

View File

@ -144,8 +144,9 @@
"dependencies": {
"add-dom-event-listener": "^1.0.2",
"array-tree-filter": "^2.1.0",
"babel-runtime": "6.x",
"async-validator": "^1.8.2",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-runtime": "6.x",
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
"css-animation": "^1.4.1",

View File

@ -4,7 +4,7 @@ import Iframe from './components/iframe.vue'
const AsyncTestComp = () => {
const d = window.location.hash.replace('#', '')
return {
component: import(`../components/menu/demo/${d}`),
component: import(`../components/vc-form/demo/${d}`),
}
}