为什么我感觉结构清晰了 但是逻辑变复杂了
来源:4-11 useClickOutside 第一个自定义函数
慕莱坞0998854
2020-10-09
老师,这节的逻辑比较简单,总结起来就是:
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回答
-
张轩
2020-10-09
同学你好 谢谢你这么长的文字 你思考的很认真 也带给我很多启示 我认为 代码抽象 很有可能代码复杂度的上升和更高的理解难度 其实 isClickOutside 这个抽象的函数,我们需要抛开 isOpen 来看,因为它完成的是一个单独的功能,有了这个值,我们可以满足更丰富的需求,带来更广阔的场景,比如说另外一个场景:点击某元素外面取消一个元素的选中(常见于图形编辑器中),点击Modal 的其他区域来关闭一个 Modal 等等。所以抽象是为了更好的服务更多的场景,复杂度上升有时候是没法避免的。
20
相似问题