diff --git a/components/align/Align.vue b/components/align/Align.vue index cd07b52c2..79466e570 100644 --- a/components/align/Align.vue +++ b/components/align/Align.vue @@ -3,6 +3,7 @@ import PropTypes from 'vue-types' import align from 'dom-align' import addEventListener from '../_util/Dom/addEventListener' import cloneElement from '../_util/cloneElement' +import isWindow from './isWindow' function noop () { } @@ -35,7 +36,39 @@ export default { monitorWindowResize: PropTypes.bool.def(false), disabled: PropTypes.bool.def(false), }, + watch: { + '$props': { + handler: function (props, prevProps) { + this.$nextTick(() => { + let reAlign = false + if (!props.disabled) { + if (prevProps.disabled || prevProps.align !== props.align) { + reAlign = true + } else { + const lastTarget = prevProps.target() + const currentTarget = props.target() + if (isWindow(lastTarget) && isWindow(currentTarget)) { + reAlign = false + } else if (lastTarget !== currentTarget) { + reAlign = true + } + } + } + if (reAlign) { + this.forceAlign() + } + + if (props.monitorWindowResize && !props.disabled) { + this.startMonitorWindowResize() + } else { + this.stopMonitorWindowResize() + } + }) + }, + deep: true, + }, + }, mounted () { const props = this.$props // if parent ref not attached .... use document.getElementById @@ -44,20 +77,7 @@ export default { this.startMonitorWindowResize() } }, - - updated () { - const props = this.$props - - this.forceAlign() - - if (props.monitorWindowResize && !props.disabled) { - this.startMonitorWindowResize() - } else { - this.stopMonitorWindowResize() - } - }, - - beforeDestory () { + beforeDestroy () { this.stopMonitorWindowResize() }, methods: { @@ -86,6 +106,7 @@ export default { }, render () { + console.log(4) const { childrenProps } = this.$props const child = this.$slots.default[0] if (childrenProps) { diff --git a/components/animate/index.js b/components/animate/index.js deleted file mode 100644 index a99ccde37..000000000 --- a/components/animate/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// do not modify this file -import Animate from './src/Animate' -export default Animate diff --git a/components/animate/src/Animate.js b/components/animate/src/Animate.js deleted file mode 100644 index d58661603..000000000 --- a/components/animate/src/Animate.js +++ /dev/null @@ -1,333 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { - toArrayChildren, - mergeChildren, - findShownChildInChildrenByKey, - findChildInChildrenByKey, - isSameChildren, -} from './ChildrenUtils' -import AnimateChild from './AnimateChild' -const defaultKey = `rc_animate_${Date.now()}` -import animUtil from './util' - -function getChildrenFromProps (props) { - const children = props.children - if (React.isValidElement(children)) { - if (!children.key) { - return React.cloneElement(children, { - key: defaultKey, - }) - } - } - return children -} - -function noop () { -} - -export default class Animate extends React.Component { - static propTypes = { - component: PropTypes.any, - componentProps: PropTypes.object, - animation: PropTypes.object, - transitionName: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.object, - ]), - transitionEnter: PropTypes.bool, - transitionAppear: PropTypes.bool, - exclusive: PropTypes.bool, - transitionLeave: PropTypes.bool, - onEnd: PropTypes.func, - onEnter: PropTypes.func, - onLeave: PropTypes.func, - onAppear: PropTypes.func, - showProp: PropTypes.string, - } - - static defaultProps = { - animation: {}, - component: 'span', - componentProps: {}, - transitionEnter: true, - transitionLeave: true, - transitionAppear: false, - onEnd: noop, - onEnter: noop, - onLeave: noop, - onAppear: noop, - } - - constructor (props) { - super(props) - - this.currentlyAnimatingKeys = {} - this.keysToEnter = [] - this.keysToLeave = [] - - this.state = { - children: toArrayChildren(getChildrenFromProps(this.props)), - } - - this.childrenRefs = {} - } - - componentDidMount () { - const showProp = this.props.showProp - let children = this.state.children - if (showProp) { - children = children.filter((child) => { - return !!child.props[showProp] - }) - } - children.forEach((child) => { - if (child) { - this.performAppear(child.key) - } - }) - } - - componentWillReceiveProps (nextProps) { - this.nextProps = nextProps - const nextChildren = toArrayChildren(getChildrenFromProps(nextProps)) - const props = this.props - // exclusive needs immediate response - if (props.exclusive) { - Object.keys(this.currentlyAnimatingKeys).forEach((key) => { - this.stop(key) - }) - } - const showProp = props.showProp - const currentlyAnimatingKeys = this.currentlyAnimatingKeys - // last props children if exclusive - const currentChildren = props.exclusive - ? toArrayChildren(getChildrenFromProps(props)) - : this.state.children - // in case destroy in showProp mode - let newChildren = [] - if (showProp) { - currentChildren.forEach((currentChild) => { - const nextChild = currentChild && findChildInChildrenByKey(nextChildren, currentChild.key) - let newChild - if ((!nextChild || !nextChild.props[showProp]) && currentChild.props[showProp]) { - newChild = React.cloneElement(nextChild || currentChild, { - [showProp]: true, - }) - } else { - newChild = nextChild - } - if (newChild) { - newChildren.push(newChild) - } - }) - nextChildren.forEach((nextChild) => { - if (!nextChild || !findChildInChildrenByKey(currentChildren, nextChild.key)) { - newChildren.push(nextChild) - } - }) - } else { - newChildren = mergeChildren( - currentChildren, - nextChildren - ) - } - - // need render to avoid update - this.setState({ - children: newChildren, - }) - - nextChildren.forEach((child) => { - const key = child && child.key - if (child && currentlyAnimatingKeys[key]) { - return - } - const hasPrev = child && findChildInChildrenByKey(currentChildren, key) - if (showProp) { - const showInNext = child.props[showProp] - if (hasPrev) { - const showInNow = findShownChildInChildrenByKey(currentChildren, key, showProp) - if (!showInNow && showInNext) { - this.keysToEnter.push(key) - } - } else if (showInNext) { - this.keysToEnter.push(key) - } - } else if (!hasPrev) { - this.keysToEnter.push(key) - } - }) - - currentChildren.forEach((child) => { - const key = child && child.key - if (child && currentlyAnimatingKeys[key]) { - return - } - const hasNext = child && findChildInChildrenByKey(nextChildren, key) - if (showProp) { - const showInNow = child.props[showProp] - if (hasNext) { - const showInNext = findShownChildInChildrenByKey(nextChildren, key, showProp) - if (!showInNext && showInNow) { - this.keysToLeave.push(key) - } - } else if (showInNow) { - this.keysToLeave.push(key) - } - } else if (!hasNext) { - this.keysToLeave.push(key) - } - }) - } - - componentDidUpdate () { - const keysToEnter = this.keysToEnter - this.keysToEnter = [] - keysToEnter.forEach(this.performEnter) - const keysToLeave = this.keysToLeave - this.keysToLeave = [] - keysToLeave.forEach(this.performLeave) - } - - performEnter = (key) => { - // may already remove by exclusive - if (this.childrenRefs[key]) { - this.currentlyAnimatingKeys[key] = true - this.childrenRefs[key].componentWillEnter( - this.handleDoneAdding.bind(this, key, 'enter') - ) - } - } - - performAppear = (key) => { - if (this.childrenRefs[key]) { - this.currentlyAnimatingKeys[key] = true - this.childrenRefs[key].componentWillAppear( - this.handleDoneAdding.bind(this, key, 'appear') - ) - } - } - - handleDoneAdding = (key, type) => { - const props = this.props - delete this.currentlyAnimatingKeys[key] - // if update on exclusive mode, skip check - if (props.exclusive && props !== this.nextProps) { - return - } - const currentChildren = toArrayChildren(getChildrenFromProps(props)) - if (!this.isValidChildByKey(currentChildren, key)) { - // exclusive will not need this - this.performLeave(key) - } else { - if (type === 'appear') { - if (animUtil.allowAppearCallback(props)) { - props.onAppear(key) - props.onEnd(key, true) - } - } else { - if (animUtil.allowEnterCallback(props)) { - props.onEnter(key) - props.onEnd(key, true) - } - } - } - } - - performLeave = (key) => { - // may already remove by exclusive - if (this.childrenRefs[key]) { - this.currentlyAnimatingKeys[key] = true - this.childrenRefs[key].componentWillLeave(this.handleDoneLeaving.bind(this, key)) - } - } - - handleDoneLeaving = (key) => { - const props = this.props - delete this.currentlyAnimatingKeys[key] - // if update on exclusive mode, skip check - if (props.exclusive && props !== this.nextProps) { - return - } - const currentChildren = toArrayChildren(getChildrenFromProps(props)) - // in case state change is too fast - if (this.isValidChildByKey(currentChildren, key)) { - this.performEnter(key) - } else { - const end = () => { - if (animUtil.allowLeaveCallback(props)) { - props.onLeave(key) - props.onEnd(key, false) - } - } - if (!isSameChildren(this.state.children, - currentChildren, props.showProp)) { - this.setState({ - children: currentChildren, - }, end) - } else { - end() - } - } - } - - isValidChildByKey (currentChildren, key) { - const showProp = this.props.showProp - if (showProp) { - return findShownChildInChildrenByKey(currentChildren, key, showProp) - } - return findChildInChildrenByKey(currentChildren, key) - } - - stop (key) { - delete this.currentlyAnimatingKeys[key] - const component = this.childrenRefs[key] - if (component) { - component.stop() - } - } - - render () { - const props = this.props - this.nextProps = props - const stateChildren = this.state.children - let children = null - if (stateChildren) { - children = stateChildren.map((child) => { - if (child === null || child === undefined) { - return child - } - if (!child.key) { - throw new Error('must set key for children') - } - return ( - this.childrenRefs[child.key] = node} - animation={props.animation} - transitionName={props.transitionName} - transitionEnter={props.transitionEnter} - transitionAppear={props.transitionAppear} - transitionLeave={props.transitionLeave} - > - {child} - - ) - }) - } - const Component = props.component - if (Component) { - let passedProps = props - if (typeof Component === 'string') { - passedProps = { - className: props.className, - style: props.style, - ...props.componentProps, - } - } - return {children} - } - return children[0] || null - } -} diff --git a/components/animate/src/AnimateChild.js b/components/animate/src/AnimateChild.js deleted file mode 100644 index 3cbeacd5c..000000000 --- a/components/animate/src/AnimateChild.js +++ /dev/null @@ -1,86 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom' -import PropTypes from 'prop-types' -import cssAnimate, { isCssAnimationSupported } from 'css-animation' -import animUtil from './util' - -const transitionMap = { - enter: 'transitionEnter', - appear: 'transitionAppear', - leave: 'transitionLeave', -} - -export default class AnimateChild extends React.Component { - static propTypes = { - children: PropTypes.any, - } - - componentWillUnmount () { - this.stop() - } - - componentWillEnter (done) { - if (animUtil.isEnterSupported(this.props)) { - this.transition('enter', done) - } else { - done() - } - } - - componentWillAppear (done) { - if (animUtil.isAppearSupported(this.props)) { - this.transition('appear', done) - } else { - done() - } - } - - componentWillLeave (done) { - if (animUtil.isLeaveSupported(this.props)) { - this.transition('leave', done) - } else { - // always sync, do not interupt with react component life cycle - // update hidden -> animate hidden -> - // didUpdate -> animate leave -> unmount (if animate is none) - done() - } - } - - transition (animationType, finishCallback) { - const node = ReactDOM.findDOMNode(this) - const props = this.props - const transitionName = props.transitionName - const nameIsObj = typeof transitionName === 'object' - this.stop() - const end = () => { - this.stopper = null - finishCallback() - } - if ((isCssAnimationSupported || !props.animation[animationType]) && - transitionName && props[transitionMap[animationType]]) { - const name = nameIsObj ? transitionName[animationType] : `${transitionName}-${animationType}` - let activeName = `${name}-active` - if (nameIsObj && transitionName[`${animationType}Active`]) { - activeName = transitionName[`${animationType}Active`] - } - this.stopper = cssAnimate(node, { - name, - active: activeName, - }, end) - } else { - this.stopper = props.animation[animationType](node, end) - } - } - - stop () { - const stopper = this.stopper - if (stopper) { - this.stopper = null - stopper.stop() - } - } - - render () { - return this.props.children - } -} diff --git a/components/animate/src/ChildrenUtils.js b/components/animate/src/ChildrenUtils.js deleted file mode 100644 index b9cc639cd..000000000 --- a/components/animate/src/ChildrenUtils.js +++ /dev/null @@ -1,101 +0,0 @@ -import React from 'react' - -export function toArrayChildren (children) { - const ret = [] - React.Children.forEach(children, (child) => { - ret.push(child) - }) - return ret -} - -export function findChildInChildrenByKey (children, key) { - let ret = null - if (children) { - children.forEach((child) => { - if (ret) { - return - } - if (child && child.key === key) { - ret = child - } - }) - } - return ret -} - -export function findShownChildInChildrenByKey (children, key, showProp) { - let ret = null - if (children) { - children.forEach((child) => { - if (child && child.key === key && child.props[showProp]) { - if (ret) { - throw new Error('two child with same key for children') - } - ret = child - } - }) - } - return ret -} - -export function findHiddenChildInChildrenByKey (children, key, showProp) { - let found = 0 - if (children) { - children.forEach((child) => { - if (found) { - return - } - found = child && child.key === key && !child.props[showProp] - }) - } - return found -} - -export function isSameChildren (c1, c2, showProp) { - let same = c1.length === c2.length - if (same) { - c1.forEach((child, index) => { - const child2 = c2[index] - if (child && child2) { - if ((child && !child2) || (!child && child2)) { - same = false - } else if (child.key !== child2.key) { - same = false - } else if (showProp && child.props[showProp] !== child2.props[showProp]) { - same = false - } - } - }) - } - return same -} - -export function mergeChildren (prev, next) { - let ret = [] - - // For each key of `next`, the list of keys to insert before that key in - // the combined list - const nextChildrenPending = {} - let pendingChildren = [] - prev.forEach((child) => { - if (child && findChildInChildrenByKey(next, child.key)) { - if (pendingChildren.length) { - nextChildrenPending[child.key] = pendingChildren - pendingChildren = [] - } - } else { - pendingChildren.push(child) - } - }) - - next.forEach((child) => { - if (child && nextChildrenPending.hasOwnProperty(child.key)) { - ret = ret.concat(nextChildrenPending[child.key]) - } - ret.push(child) - }) - - ret = ret.concat(pendingChildren) - - return ret -} diff --git a/components/animate/src/util.js b/components/animate/src/util.js deleted file mode 100644 index d84f1e662..000000000 --- a/components/animate/src/util.js +++ /dev/null @@ -1,21 +0,0 @@ -const util = { - isAppearSupported(props) { - return props.transitionName && props.transitionAppear || props.animation.appear; - }, - isEnterSupported(props) { - return props.transitionName && props.transitionEnter || props.animation.enter; - }, - isLeaveSupported(props) { - return props.transitionName && props.transitionLeave || props.animation.leave; - }, - allowAppearCallback(props) { - return props.transitionAppear || props.animation.appear; - }, - allowEnterCallback(props) { - return props.transitionEnter || props.animation.enter; - }, - allowLeaveCallback(props) { - return props.transitionLeave || props.animation.leave; - }, -}; -export default util; diff --git a/components/menu/src/util.js b/components/menu/src/util.js index d9a56c94e..14b9eed87 100644 --- a/components/menu/src/util.js +++ b/components/menu/src/util.js @@ -1,5 +1,3 @@ -import React from 'react' - export function noop () { } @@ -9,18 +7,18 @@ export function getKeyFromChildrenIndex (child, menuEventKey, index) { } export function loopMenuItem (children, cb) { - let index = -1 - React.Children.forEach(children, (c) => { - index++ - if (c && c.type && c.type.isMenuItemGroup) { - React.Children.forEach(c.props.children, (c2) => { - index++ - cb(c2, index) - }) - } else { - cb(c, index) - } - }) + // let index = -1 + // React.Children.forEach(children, (c) => { + // index++ + // if (c && c.type && c.type.isMenuItemGroup) { + // React.Children.forEach(c.props.children, (c2) => { + // index++ + // cb(c2, index) + // }) + // } else { + // cb(c, index) + // } + // }) } export function loopMenuItemRecusively (children, keys, ret) { diff --git a/package.json b/package.json index e99c19ab8..5e86c8c54 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "add-dom-event-listener": "^1.0.2", "css-animation": "^1.4.1", "eslint-plugin-vue": "^3.13.0", + "lodash.clonedeep": "^4.5.0", "lodash.debounce": "^4.0.8", "omit.js": "^1.0.0", "vue-types": "^1.0.2",