react-component / tree

React Tree
https://tree.react-component.now.sh/
MIT License
1.21k stars 484 forks source link

关于 TreeNode Click 事件 e.preventDefault(); 疑惑 #331

Open hnsylitao opened 4 years ago

hnsylitao commented 4 years ago

代码 https://github.com/react-component/tree/blob/master/src/TreeNode.tsx#L97-L120

我现在需要在label 中放入 input checkbox 导致了 change 失效

imhxc commented 4 years ago

遇到一样的问题,根据目前的情况来看,应该不止 checkbox 的 change 事件被阻止了,其他的事件也会失效。

sora496 commented 4 years ago

在treeNode的title中自定义渲染的一些checkbox,初始onchange事件会生效,再次点击就会失效,似乎onSelect的事件不加preventDefault会导致触发到oncheck事件?

hnsylitao commented 4 years ago

给一个我目前做法的建议把。(纯属建议) 1.二次封装RcTree 2.给RcTree 加上disabled 属性。禁止checkable,和selected

if (this.isDisabled()) return;

3.给RcTree 一个Ref 属性

  1. 给二次封装的RcTree 处理一下 onClick 事件

    const treeRef = useRef<TreeRef>(null);
    
    function isSelectable(data: EventDataNode) {
    const { selectable } = data;
    const { selectable: treeSelectable = true } = this.props;
    if (typeof selectable === 'boolean') {
      return selectable;
    }
    return treeSelectable;
    }
    
    const handleClick = useCallback(
    (event, data: EventDataNode) => {
      onClick && onClick(event, data);
      if (treeRef.current) {
        if (isSelectable(data)) {
          treeRef.current.onNodeSelect(event, data);
        } else {
          treeRef.current.onNodeCheck(event, data, !data.checked);
        }
      }
    },
    [treeRef],
    );
hnsylitao commented 4 years ago

这里采用disabled 碰到了draggable 得问题。因为禁用得同时禁用了draggable 。 请问一下如果遇到这种问题。我因该如何解决处理? @zombieJ

zombieJ commented 4 years ago

Tree 本身做 preventDefault 是为了防止焦点丢失的情况,title 里可以包一层 stopPropagation 阻止外层处理。

hnsylitao commented 4 years ago

如果同时想保留select 这种事件呢,岂不是阻止了外层本身得事件。 如果去除preventDefault 会带来什么负面得影响嘛。

zombieJ commented 4 years ago

根据需求来,业务上一般遇到组合的情况如: [文字][输入框][文字]

这时候是输入框不想响应 Tree 事件,就对输入框包一下。看自己不想响应的层级来处理即可。

andrejpavlovic commented 3 years ago

It is very unusual for this library to always call preventDefault() and because of it, my links <a href="..."></a> don't work.

Can we add an option to the library to allow us to choose whether we want to always preventDefault() or not? I can submit a PR for this.

Something like this in Tree.tsx:

export interface TreeProps {
  // ...
  alwaysPreventDefault?: boolean; // default to true for backwards compatibility
}

and then in TreeNode.tsx

  onSelect = (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => {
    if (this.isDisabled()) return;

    const {
      alwaysPreventDefault = true,
      context: { onNodeSelect },
    } = this.props;
    if (alwaysPreventDefault) e.preventDefault();
    onNodeSelect(e, convertNodePropsToEventData(this.props));
  };

I think that will make the component a lot more versatile.