Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow overflow in horizontal mode #159

Merged
merged 3 commits into from Jul 14, 2018
Merged

feat: allow overflow in horizontal mode #159

merged 3 commits into from Jul 14, 2018

Conversation

picodoth
Copy link
Contributor

@picodoth picodoth commented Jun 19, 2018

addressing #148

screen shot 2018-06-19 at 10 34 57 pm

TODO:

  • Adding test

src/MenuItem.jsx Outdated
});
// scrollIntoView(ReactDOM.findDOMNode(this), ReactDOM.findDOMNode(this.props.parentMenu), {
// onlyScrollIfNeeded: true,
// });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yesmeck do we still need this with the new feature?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

当然

src/DOMWrap.jsx Outdated
if (selectedIndex !== -1 && selectedIndex > lastVisibleIndex) {
const selectedIndexInOverflow = this.overflowedItems.findIndex(ele => ele.props.eventKey === this.childrenCache[selectedIndex].props.eventKey)
const tmp = this.props.children[lastVisibleIndex - 1];
this.props.children[lastVisibleIndex] = this.overflowedItems[selectedIndexInOverflow];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might not be the best way since we're modifying this.props.children. Suggestions appreciated!

src/DOMWrap.jsx Outdated
debouncedHandleResize = debounce(this.handleResize, 500);

componentDidMount() {
window.addEventListener('resize', this.debouncedHandleResize);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

window.addEventListener('resize', this.resize, { passive: true });
加上这个稍微提升点性能

src/DOMWrap.jsx Outdated
return childNode;
} else if (index === this.state.overflowingIndex) {
// put all the overflowed item inside a submenu with a title of overflow indicator ('...')
const copy = this.props.children[this.state.overflowingIndex];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overflowingIndex 用了好多次
搞个临时变量比较好

@picodoth picodoth force-pushed the allow-overflow branch 3 times, most recently from 39e584f to 7672518 Compare June 25, 2018 11:34
@picodoth picodoth changed the title [WIP] feat: allow overflow in horizontal mode feat: allow overflow in horizontal mode Jun 25, 2018
@picodoth picodoth force-pushed the allow-overflow branch 2 times, most recently from 701f3ad to 64ce8ba Compare June 25, 2018 11:44
@picodoth
Copy link
Contributor Author

picodoth commented Jun 25, 2018

@chenshuai2144 @yesmeck 再看下,加了test, 可以checkout出来感受下,看 examples/antd

@coveralls
Copy link

coveralls commented Jun 25, 2018

Coverage Status

Coverage decreased (-0.2%) to 99.429% when pulling 9c20a5e on allow-overflow into 0efef0b on master.

@@ -76,6 +76,7 @@
"babel-runtime": "6.x",
"classnames": "2.x",
"dom-scroll-into-view": "1.x",
"lodash": "^4.17.10",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以直接引用 lodash/debounce 包

src/DOMWrap.jsx Outdated
renderChildren(children) {
// need to take care of overflowed items in horizontal mode
if (this.props.mode === 'horizontal') {
const lastVisibleIndex = this.state.lastVisibleIndex;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const { lastVisibleIndex} = this.state;

src/DOMWrap.jsx Outdated
delete rest.visible;
delete rest.prefixCls;
delete rest.overflowedIndicator;
delete rest.mode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么不直接在结构赋值就不要引入?

src/DOMWrap.jsx Outdated
delete rest.visible;
delete rest.prefixCls;
delete rest.overflowedIndicator;
delete rest.mode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么不直接在结构赋值就不要引入?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么不呢

src/DOMWrap.jsx Outdated
@@ -1,7 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import debounce from 'lodash/debounce';
import debounce from 'lodash.debounce';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该都可以?

@picodoth picodoth force-pushed the allow-overflow branch 2 times, most recently from e028ba3 to 5e1c8aa Compare June 26, 2018 01:54
@picodoth
Copy link
Contributor Author

@yesmeck @afc163

package.json Outdated
@@ -76,6 +76,7 @@
"babel-runtime": "6.x",
"classnames": "2.x",
"dom-scroll-into-view": "1.x",
"lodash.debounce": "^4.0.8",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

统一用 lodash/debounce,这样不会跟其他包重复装依赖。

src/DOMWrap.jsx Outdated
};

componentDidMount() {
this.setChildrenCache();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

children 变化了呢?

src/DOMWrap.jsx Outdated

componentDidMount() {
this.setChildrenCache();
this.setOverflowedIndicatorSize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indicator 变化了呢?

src/DOMWrap.jsx Outdated
}

componentWillUnmount() {
window.removeEventListener('resize', this.debouncedHandleResize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debounced 的方法最后一次调用要 cancel 掉。

this.debouncedHandleResize.cancel()

src/DOMWrap.jsx Outdated
newState = {
...newState,
children: nextProps.children,
childrenUpdated: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不应该用这个状态,应该在 children 发生变化的时候直接更新 childrenCache

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个状态是为了让组件有机会重新直接渲染 children, 见 https://github.com/react-component/menu/pull/159/files#diff-e2fa48f75c2dd2318295cde428556a76R239, 否则没有机会拿到正确的 childrenCahe

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

componentDidUpdate 里能直接比较 preProps.children === this.props.children

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@picodoth picodoth force-pushed the allow-overflow branch 2 times, most recently from 2b53cbf to c46b2d1 Compare July 2, 2018 06:13
src/DOMWrap.jsx Outdated
this.overflowedItems[selectedIndexInOverflow] = tmp;

this.overflowedItems.splice(selectedIndexInOverflow, 1);
this.overflowedItems.unshift(tmp);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/DOMWrap.jsx Outdated
@@ -185,18 +173,6 @@ class DOMWrap extends React.Component {

lastVisibleIndex = lastVisibleIndex - 1;
}

// try to hoist hidden selected item
if (selectedIndex !== -1 && selectedIndex > lastVisibleIndex) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先 revert 了,选中项被隐藏的场景比较多比较复杂,如果有 feature request 再考虑加进来吧 @yesmeck @chenshuai2144

src/DOMWrap.jsx Outdated
@@ -27,7 +28,7 @@ class DOMWrap extends React.Component {
}

componentDidUpdate(prevProps) {
if (prevProps.children !== this.props.children
if (menuChildrenChanged(prevProps.children, this.props.children)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yesmeck 发现原来的版本在 antd 里每次hover children 都不一样,就会一致刷。

Copy link
Member

@yesmeck yesmeck Jul 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

什么意思,组件从父组件 render 过来的话 children 就是每次都不一样的。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

孙子节点有变化呢?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我改成了比较 key,假定 key 变了才认为 menuItem 改变

奇怪的是只是 hover 在 menuItem 上,为什么会触发父组件的 render

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

孙子节点的变化不影响顶级的渲染啊

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没懂,所以你认为目前的方案有问题么

我是说孙子节点要是变化了,并不需要updateChildrenCache,因为不会影响第一层MenuItems。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class App extends React.Component {
  render() {
    return (
      <Menu>
        <Menu.Item key="1"><Foo /><Menu.Item>
      </Menu>
    );
  }
}

App 重新 render,Foo 发生变化,这种情况,需不需要 updateChildrenCache

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没意识到 MenuItem 的孩子才是真正的内容 Foo 发生变化咋比较好 不能直接比较 reference 否则每次都不一样,不比较 reference 比较啥啊?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

引用比较有什么问题?

Copy link
Contributor Author

@picodoth picodoth Jul 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

每次 componentDidUpdate 都会重新 setState,在 antd 里 hover �在一个 popup 上会闪

@picodoth
Copy link
Contributor Author

@chenshuai2144 @yesmeck ready to go!!!!

@picodoth
Copy link
Contributor Author

picodoth commented Jul 13, 2018

FYI @afc163

@yesmeck
Copy link
Member

yesmeck commented Jul 13, 2018

screen shot 2018-07-13 at 11 10 47

自定义的会被遮住

@picodoth
Copy link
Contributor Author

自定义的会被遮住

好的,edge case 有点多,这个我到时候再加进去也计算一下

你先整体再确认一下,看实现有啥问题

const container = document.body.appendChild(document.createElement('div'));
container.setAttribute('style', 'position: absolute; top: 0; visibility: hidden');
ReactDOM.render(this.props.overflowedIndicator, container, () => {
this.overflowedIndicatorWidth = getWidth(container) + 40;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReactDOM.unmountComponentAtNode(container)

src/DOMWrap.jsx Outdated
});

this.originalScrollWidth = scrollWidth;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReactDOM.unmountComponentAtNode(container)

@picodoth
Copy link
Contributor Author

@yesmeck 修复了 简化了代码

fix leftover corner cases

fixing selected keys issue

fix selected menuItem got hidden scenario

cleaning up

fix lint

fix scroll into view

fix more item eventkey issue and cleanup

addressing corner cases

extract getWidth and getScrollWidth for test

adding test

update tests

update readme

adding more docs

fix lint

address cr

handle children or overflowedIndicator changes

fix lint

use componentDidUpdate rather than getDerivedStateFromProps

update debounce time and example

fix uncontrolled mode

fixing lint and adding text

try to keep order while hoisting hidden selected items

revert hoisting selected keys
@picodoth
Copy link
Contributor Author

没啥问题,合了哈

@picodoth picodoth merged commit c66f7c1 into master Jul 14, 2018
@picodoth picodoth deleted the allow-overflow branch July 14, 2018 06:12
yesmeck added a commit that referenced this pull request Jul 17, 2018
picodoth added a commit that referenced this pull request Jul 18, 2018
This reverts commit c96400a.
picodoth added a commit that referenced this pull request Aug 19, 2018
This reverts commit c96400a.
picodoth added a commit that referenced this pull request Aug 27, 2018
This reverts commit c96400a.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants