1

需求背景

举个栗子:
如下日历,目前存在一个问题,当我删除掉input值的时候,日历里model的值并没有删除掉。只是input显示的值被删除了。

为了解决这个bug, 我需要给Input添加blur事件,清空日历model值。同时,如果我blur点击的区域如果在下方日历显示的地方,禁止blur里的方法执行。

image.png

重点问题

如何判断blur事件鼠标点击的位置在日历上呢?

根据 MDN中blur的定义以及实践,我是没有办法从blur(event) 里获取所点击的位置的信息的。

所以我只能另辟蹊径,监听当前dom元素的click事件获取点击的地方,不就可以获取了。

解决方案

全局监听click事件判断是否点击到了日历

window.document.addEventListener('click', this.handleDocClick, false)

解决问题的道路是充满曲折的。

此时又产生了一个新的问题,发现blur事件永远比click事件先执行,blur都执行完了,我获取了位置也用不到呀。

blur,click执行顺序解决

blur和focus事件不会冒泡,其他表单事件都可以

click事件;所有元素都有此事件,会产生冒泡

一个元素失去焦点,blur事件优先于click事件

执行顺序为mousedown > mouseup > click

我们只需要把 全局监听的click事件换成 mousedown就可以了

window.document.addEventListener('mousedown', this.handleDocClick, false)

handleDocClick (e) {
  const target = e.target
  if (!this.picker) {
    return
  }
  // 日历是否被点击过
  this.pickerClicked = contains(this.picker.$el, target) // contains 判断日历picker元素是否包含mousedown点击的元素
},

// 节点包含
export const contains = (root, target) => {
  // root 节点是否包含 target 节点
  const isElement =
    Object.prototype.toString.call(root).includes('Element') &&
    Object.prototype.toString.call(target).includes('Element')
  if (!isElement) {
    return false
  }
  let node = target
  while (node) {
    if (node === root) {
      return true
    }
    node = node.parentNode
  }
  return false
}

旅图灬
905 声望43 粉丝

任何事物都有它的正反面,研究技术要全面