请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

为什么我感觉结构清晰了 但是逻辑变复杂了

回答1 浏览127 2020-10-09 18:08:18

老师,这节的逻辑比较简单,总结起来就是:
1> 用isOpen这个变量控制dropdown-item的显示与否
2> 当点击到页面中的其他部分,隐藏dropdown-item

前一节的代码时这样的:

	const dropdownRef = ref<null | HTMLElement>(null);

    const handler = (e: MouseEvent) => {
      if (dropdownRef.value) {
        if (
          !dropdownRef.value.contains(e.target as HTMLElement) &&
          isOpen.value
        ) {
          isOpen.value = false;
        }
      }
    };

    onMounted(() => {
      document.addEventListener("click", handler);
    });
    onUnmounted(() => {
      document.removeEventListener("click", handler);
    });

请注意,这里只有isOpen这一个变量。dropdown-item的显示与否只与isOpen相关,缺点也显而易见,setup这个函数容易变得很长很长。

老师把点击外面的区域这段代码抽象出来,这节的代码变成了:

// useClickOutside.ts
   const  useClickOutside = (
     elementRef: Ref<null | HTMLElement>
   ): Ref<boolean> => {
     const isClickOutside = ref(false);

     const handler = (e: MouseEvent) => {
      if (elementRef.value) {
        if (elementRef.value.contains(e.target as HTMLElement)) {
          isClickOutside.value = false;
          // 下面的else我在自己写的时候就没有注意要重置为true
        } else {
          isClickOutside.value = true;
        }
      }
   };

  onMounted(() => {
    document.body.addEventListener("click", handler);
  });

  onUnmounted(() => {
    document.body.removeEventListener("click", handler);
  });

  return isClickOutside;
};

//  Dropdown.vue

    const dropdownRef = ref<null | HTMLElement>(null);

    const isClickOutside = useClickOutside(dropdownRef);

    watch(isClickOutside, () => {
      if (isClickOutside.value && isOpen.value) {
        isOpen.value = false;
      }
    });

改写之后在Dropdown.vue中,代码少了一些。但是在这里我感到疑惑, 现在是两个变量了,其中isClickOutside可以通过改变isOpen的值的方式来间接影响dropdown-item的显示与否,就好像以前有只有一个变量A(true 或者 false),现在则是A(true 和 false)和B(同样也是true和false)两个变量,那么排列组合一下,就有四种情况了。

以第一次点击那个切换显示与否的button为例,我照着本节的代码捋捋流程就是这样的:
1 > 执行toggleOpen函数 isOpen由false变成true
2 > 点击的这个button是属于DropDown组件的,所以isClickOutside的值保持false不变
3 > 因为isClickOutside没有发生改变,所以watch里面的回调函数不会执行
4 > 由于isOpen值为true 故显示dropdown-item

但是如果按照上一节的代码来捋流程的话 似乎就简单了很多
1> 执行toggleOpen函数 isOpen由false变成true
2> 点击的这个button是属于DropDown组件的,不满足handler里面的if判断 什么也不做
3> 由于isOpen值为true 故显示dropdown-item

这只是一个例子 假如再想搞清楚"点击外部区域"这个情况 那么在脑中过一遍流程的话, 还是上一节的代码简单

按照本节的代码 我们需要关注isOpen和isClickOutside两个变量,我感觉多维护一个变量的话,总是容易想不清楚。

添加回答

1回答

  • 同学你好 谢谢你这么长的文字 你思考的很认真 也带给我很多启示 我认为 代码抽象 很有可能代码复杂度的上升和更高的理解难度 其实 isClickOutside 这个抽象的函数,我们需要抛开 is...
    2020-10-09 18:23:35

Vue3.0(正式版) + TS 仿知乎专栏企业级项目

难度中级
时长17小时
人数936
好评度98.5%

Vue3.0 全家桶+TS ,带你完成前后端分离复杂项目,率先掌握vue3.0造轮子技能

讲师

张轩 Web前端工程师

曾在Apple、百度担任高级前端开发工程师,是《React全栈:Redux Flux webpack Babel整合开发》该书作者,拥有丰富的Web开发经验,喜欢追寻新技术,同时致力于前端工程化,并且有大型SPA项目的架构及开发经验。

意见反馈 帮助中心 APP下载
官方微信