@whitesev/domutils 1.9.9 → 1.9.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "1.9.9";
1
+ const version = "1.9.11";
2
2
 
3
3
  class WindowApi {
4
4
  /** 默认的配置 */
@@ -1378,7 +1378,7 @@ class ElementEvent extends ElementAnimate {
1378
1378
  * @param startIndex
1379
1379
  * @param option
1380
1380
  */
1381
- function getOption(args, startIndex, option) {
1381
+ const getOption = function (args, startIndex, option) {
1382
1382
  const currentParam = args[startIndex];
1383
1383
  if (typeof currentParam === "boolean") {
1384
1384
  option.capture = currentParam;
@@ -1400,7 +1400,7 @@ class ElementEvent extends ElementAnimate {
1400
1400
  option.isComposedPath = currentParam.isComposedPath;
1401
1401
  }
1402
1402
  return option;
1403
- }
1403
+ };
1404
1404
  const that = this;
1405
1405
  // eslint-disable-next-line prefer-rest-params
1406
1406
  const args = arguments;
@@ -1455,74 +1455,96 @@ class ElementEvent extends ElementAnimate {
1455
1455
  // 这是存在selector的情况
1456
1456
  listenerOption = getOption(args, 4, listenerOption);
1457
1457
  }
1458
- /**
1459
- * 如果是once,那么删除该监听和元素上的事件和监听
1460
- */
1461
- const checkOptionOnceToRemoveEventListener = () => {
1462
- if (listenerOption.once) {
1463
- that.off(element, eventType, selector, callback, option);
1464
- }
1465
- };
1466
- $elList.forEach((elementItem) => {
1467
- /**
1468
- * 事件回调
1469
- * @param event
1470
- */
1471
- const handlerCallBack = function (event) {
1472
- if (selectorList.length) {
1473
- /* 存在子元素选择器 */
1474
- // 这时候的this和target都是子元素选择器的元素
1475
- let eventTarget = listenerOption.isComposedPath
1476
- ? event.composedPath()[0]
1477
- : event.target;
1478
- let totalParent = elementItem;
1479
- if (CommonUtils.isWin(totalParent)) {
1480
- if (totalParent === that.windowApi.document) {
1481
- totalParent = that.windowApi.document.documentElement;
1482
- }
1458
+ $elList.forEach(($elItem) => {
1459
+ // 遍历事件名设置元素事件
1460
+ eventTypeList.forEach((eventName) => {
1461
+ /**
1462
+ * 如果是option.once,那么删除该监听和元素上的事件和监听
1463
+ */
1464
+ const checkOptionOnceToRemoveEventListener = () => {
1465
+ if (listenerOption.once) {
1466
+ this.off($elItem, eventName, selector, callback, option);
1483
1467
  }
1484
- const findValue = selectorList.find((selectorItem) => {
1485
- // 判断目标元素是否匹配选择器
1486
- if (that.matches(eventTarget, selectorItem)) {
1487
- /* 当前目标可以被selector所匹配到 */
1488
- return true;
1468
+ };
1469
+ /**
1470
+ * 事件回调
1471
+ * @param event
1472
+ */
1473
+ const handlerCallBack = function (event) {
1474
+ let call_this = void 0;
1475
+ let call_event = void 0;
1476
+ let call_$selector = void 0;
1477
+ let execCallback = false;
1478
+ if (selectorList.length) {
1479
+ // 存在子元素选择器
1480
+ // 这时候的this和target都是子元素选择器的元素
1481
+ let $target;
1482
+ if (listenerOption.isComposedPath) {
1483
+ // 可能为空
1484
+ const composedPath = event.composedPath();
1485
+ if (!composedPath.length && event.target) {
1486
+ composedPath.push(event.target);
1487
+ }
1488
+ $target = composedPath[0];
1489
1489
  }
1490
- /* 在上层与主元素之间寻找可以被selector所匹配到的 */
1491
- const $closestMatches = that.closest(eventTarget, selectorItem);
1492
- if ($closestMatches && totalParent?.contains?.($closestMatches)) {
1493
- eventTarget = $closestMatches;
1494
- return true;
1490
+ else {
1491
+ $target = event.target;
1495
1492
  }
1496
- return false;
1497
- });
1498
- if (findValue) {
1499
- // 这里尝试使用defineProperty修改event的target值
1500
- try {
1501
- OriginPrototype.Object.defineProperty(event, "target", {
1502
- get() {
1503
- return eventTarget;
1504
- },
1505
- });
1493
+ let $parent = $elItem;
1494
+ if (CommonUtils.isWin($parent)) {
1495
+ // window和document共用一个对象
1496
+ // 这样就能处理子元素选择器无法匹配的问题
1497
+ $parent = that.windowApi.document.documentElement;
1506
1498
  }
1507
- catch {
1508
- // TODO
1499
+ const findValue = selectorList.find((selectors) => {
1500
+ // 判断目标元素是否匹配选择器
1501
+ if (that.matches($target, selectors)) {
1502
+ // 当前目标可以被selector所匹配到
1503
+ return true;
1504
+ }
1505
+ // 在上层与主元素之间寻找可以被selector所匹配到的
1506
+ const $closestMatches = that.closest($target, selectors);
1507
+ if ($closestMatches && $parent?.contains?.($closestMatches)) {
1508
+ $target = $closestMatches;
1509
+ return true;
1510
+ }
1511
+ return false;
1512
+ });
1513
+ if (findValue) {
1514
+ // 这里尝试使用defineProperty修改event的target值
1515
+ try {
1516
+ OriginPrototype.Object.defineProperty(event, "target", {
1517
+ get() {
1518
+ return $target;
1519
+ },
1520
+ });
1521
+ // oxlint-disable-next-line no-empty
1522
+ }
1523
+ catch { }
1524
+ execCallback = true;
1525
+ call_this = $target;
1526
+ call_event = event;
1527
+ call_$selector = $target;
1509
1528
  }
1510
- listenerCallBack.call(eventTarget, event, eventTarget);
1529
+ }
1530
+ else {
1531
+ execCallback = true;
1532
+ call_this = $elItem;
1533
+ call_event = event;
1534
+ }
1535
+ if (execCallback) {
1536
+ const result = listenerCallBack.call(call_this, call_event, call_$selector);
1511
1537
  checkOptionOnceToRemoveEventListener();
1538
+ if (typeof result === "boolean" && !result) {
1539
+ return false;
1540
+ }
1512
1541
  }
1513
- }
1514
- else {
1515
- // 这时候的this指向监听的元素
1516
- listenerCallBack.call(elementItem, event);
1517
- checkOptionOnceToRemoveEventListener();
1518
- }
1519
- };
1520
- /* 遍历事件名设置元素事件 */
1521
- eventTypeList.forEach((eventName) => {
1522
- elementItem.addEventListener(eventName, handlerCallBack, listenerOption);
1523
- /* 获取对象上的事件 */
1524
- const elementEvents = Reflect.get(elementItem, GlobalData.domEventSymbol) || {};
1525
- /* 初始化对象上的xx事件 */
1542
+ };
1543
+ // add listener
1544
+ $elItem.addEventListener(eventName, handlerCallBack, listenerOption);
1545
+ // 获取对象上的事件
1546
+ const elementEvents = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
1547
+ // 初始化对象上的xx事件
1526
1548
  elementEvents[eventName] = elementEvents[eventName] || [];
1527
1549
  elementEvents[eventName].push({
1528
1550
  selector: selectorList,
@@ -1530,8 +1552,8 @@ class ElementEvent extends ElementAnimate {
1530
1552
  handlerCallBack: handlerCallBack,
1531
1553
  callback: listenerCallBack,
1532
1554
  });
1533
- /* 覆盖事件 */
1534
- Reflect.set(elementItem, GlobalData.domEventSymbol, elementEvents);
1555
+ // 覆盖事件
1556
+ Reflect.set($elItem, GlobalData.domEventSymbol, elementEvents);
1535
1557
  });
1536
1558
  });
1537
1559
  return {
@@ -1545,7 +1567,7 @@ class ElementEvent extends ElementAnimate {
1545
1567
  /**
1546
1568
  * 主动触发事件
1547
1569
  * @param extraDetails 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
1548
- * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了$selector的没有值
1570
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了`$selector`的没有值
1549
1571
  */
1550
1572
  emit: (extraDetails, useDispatchToTriggerEvent) => {
1551
1573
  that.emit($elList, eventTypeList, extraDetails, useDispatchToTriggerEvent);
@@ -1559,7 +1581,7 @@ class ElementEvent extends ElementAnimate {
1559
1581
  * @param startIndex
1560
1582
  * @param option
1561
1583
  */
1562
- function getOption(args1, startIndex, option) {
1584
+ const getOption = function (args1, startIndex, option) {
1563
1585
  const currentParam = args1[startIndex];
1564
1586
  if (typeof currentParam === "boolean") {
1565
1587
  option.capture = currentParam;
@@ -1568,7 +1590,7 @@ class ElementEvent extends ElementAnimate {
1568
1590
  option.capture = currentParam.capture;
1569
1591
  }
1570
1592
  return option;
1571
- }
1593
+ };
1572
1594
  const that = this;
1573
1595
  // eslint-disable-next-line prefer-rest-params
1574
1596
  const args = arguments;
@@ -1626,40 +1648,43 @@ class ElementEvent extends ElementAnimate {
1626
1648
  filter = option;
1627
1649
  }
1628
1650
  $elList.forEach(($elItem) => {
1629
- /* 获取对象上的事件 */
1651
+ // 获取对象上的事件
1630
1652
  const elementEvents = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
1631
1653
  eventTypeList.forEach((eventName) => {
1632
1654
  const handlers = elementEvents[eventName] || [];
1633
- const filterHandler = typeof filter === "function" ? handlers.filter(filter) : handlers;
1634
- for (let index = 0; index < filterHandler.length; index++) {
1635
- const handler = filterHandler[index];
1655
+ // 过滤出需要删除的事件
1656
+ const handlersFiltered = typeof filter === "function" ? handlers.filter(filter) : handlers;
1657
+ for (let index = 0; index < handlersFiltered.length; index++) {
1658
+ const handler = handlersFiltered[index];
1659
+ // 过滤出的事件再根据下面的条件进行判断处理移除
1660
+ // 1. callback内存地址必须相同
1661
+ // 2. selector必须相同
1662
+ // 3. option.capture必须相同
1636
1663
  let flag = true;
1637
1664
  if (flag && listenerCallBack && handler.callback !== listenerCallBack) {
1638
- // callback不同
1639
1665
  flag = false;
1640
1666
  }
1641
1667
  if (flag && selectorList.length && Array.isArray(handler.selector)) {
1642
1668
  if (JSON.stringify(handler.selector) !== JSON.stringify(selectorList)) {
1643
- // 子元素选择器不同
1644
1669
  flag = false;
1645
1670
  }
1646
1671
  }
1647
1672
  if (flag &&
1648
1673
  typeof handler.option.capture === "boolean" &&
1649
1674
  listenerOption.capture !== handler.option.capture) {
1650
- // 事件的配置项不同
1651
1675
  flag = false;
1652
1676
  }
1653
1677
  if (flag) {
1654
1678
  $elItem.removeEventListener(eventName, handler.handlerCallBack, handler.option);
1655
- const findIndex = handlers.findIndex((item) => item === handler);
1656
- if (findIndex !== -1) {
1657
- handlers.splice(findIndex, 1);
1679
+ for (let i = handlers.length - 1; i >= 0; i--) {
1680
+ if (handlers[i] === handler) {
1681
+ handlers.splice(i, 1);
1682
+ }
1658
1683
  }
1659
1684
  }
1660
1685
  }
1661
1686
  if (handlers.length === 0) {
1662
- /* 如果没有任意的handler,那么删除该属性 */
1687
+ // 如果没有任意的handler,那么删除该属性
1663
1688
  CommonUtils.delete(elementEvents, eventType);
1664
1689
  }
1665
1690
  });
@@ -2420,11 +2445,11 @@ class ElementEvent extends ElementAnimate {
2420
2445
  * 阻止事件的默认行为发生,并阻止事件传播
2421
2446
  */
2422
2447
  const stopEvent = (event, onlyStopPropagation) => {
2448
+ // 停止事件的传播,阻止它继续向更上层的元素冒泡,事件将不会再传播给其他的元素
2449
+ event?.stopPropagation();
2450
+ // 阻止事件传播,并且还能阻止元素上的其他事件处理程序被触发
2451
+ event?.stopImmediatePropagation();
2423
2452
  if (typeof onlyStopPropagation === "boolean" && onlyStopPropagation) {
2424
- // 停止事件的传播,阻止它继续向更上层的元素冒泡,事件将不会再传播给其他的元素
2425
- event?.stopPropagation();
2426
- // 阻止事件传播,并且还能阻止元素上的其他事件处理程序被触发
2427
- event?.stopImmediatePropagation();
2428
2453
  return;
2429
2454
  }
2430
2455
  // 阻止事件的默认行为发生。例如,当点击一个链接时,浏览器会默认打开链接的URL,或者在输入框内输入文字