From 182c0bceddb64e17ebb084fbd730f1e3d886694a Mon Sep 17 00:00:00 2001 From: morning-star <26325820+Sight-wcg@users.noreply.github.com> Date: Sun, 21 Sep 2025 23:36:33 +0800 Subject: [PATCH] =?UTF-8?q?fix(select):=20=E9=9D=A2=E6=9D=BF=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=A4=A7=E5=B0=8F=E5=8F=98=E5=8C=96=E6=97=B6=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E5=AE=9A=E4=BD=8D=20(#2824)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(select): select 面板大小变化时重新定位 * update * chore: 将 bind 改为 $.proxy * update --- src/modules/form.js | 9 ++++ src/modules/lay.js | 107 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/src/modules/form.js b/src/modules/form.js index 8b97692d..8ec8f02b 100644 --- a/src/modules/form.js +++ b/src/modules/form.js @@ -8,6 +8,7 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){ var $ = layui.$; var layer = layui.layer; var util = layui.util; + var lay = layui.lay; var hint = layui.hint(); var device = layui.device(); var i18n = layui.i18n; @@ -21,6 +22,8 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){ var OUT_OF_RANGE = 'layui-input-number-out-of-range'; var BAD_INPUT = 'layui-input-number-invalid'; + var resizeObserver = lay._createResizeObserver(MOD_NAME); + // ie8 中可以获取到 input 元素的 'indeterminate' 属性描述符,但重新定义 getter/setter 无效,无报错 // AppleWebKit/537.36 无法获取 input 元素任意属性的属性描述符(包括lookupGetter),但可以重新定义 getter/setter var needCheckboxFallback = (lay.ie && parseFloat(lay.ie) === 8) @@ -523,6 +526,9 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){ updatePosition(); $(window).on('resize.lay_select_resize', updatePosition); + if(resizeObserver){ + resizeObserver.observe(reElem[0], updatePosition); + } } var top = reElem.offset().top + reElem.outerHeight() + 5 - $win.scrollTop(); var dlHeight = dl.outerHeight(); @@ -575,6 +581,9 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){ if(isAppendTo){ reElem.detach(); $(window).off('resize.lay_select_resize'); + if(resizeObserver){ + resizeObserver.unobserve(reElem[0]); + } } if(choose) return; diff --git a/src/modules/lay.js b/src/modules/lay.js index 8a95f278..8a505a80 100644 --- a/src/modules/lay.js +++ b/src/modules/lay.js @@ -836,6 +836,113 @@ .replace(/\&/g, '&'); }; + /** + * 生成唯一的 ID 字符串 + * @param {string} prefix ID前缀,默认为'id' + * @returns {string} 唯一ID字符串 + */ + var generateUniqueId = (function () { + var counter = 0; + var lastTimestamp = null; + + return function (prefix) { + prefix = prefix || 'id'; + var timestamp = new Date().getTime(); + + // 如果时间戳与上一次相同,增加计数器 + // 否则重置计数器 + if (timestamp === lastTimestamp) { + counter++; + } else { + counter = 0; + lastTimestamp = timestamp; + } + + // 结合时间戳、随机数和计数器生成ID + var random = Math.floor(Math.random() * 10000); + + return prefix + '-' + timestamp + '-' + random + '-' + counter; + }; + })(); + + /** + * 创建全局 ResizeObserver 实例 + * @param {string} namespace 命名空间,用于区分不同的 ResizeObserver 实例 + * @returns {ResizeObserver | null} 全局 ResizeObserver 实例或 null(如果不支持) + */ + lay._createResizeObserver = function (namespace) { + if (typeof window.ResizeObserver === 'undefined') { + console.log && console.log('ResizeObserver is not supported in this browser'); + return null; + } + + var ATTR_NAME = 'lay-' + namespace + '-resizeobserver-key'; + var handlerCache = {}; + + var o = new ResizeObserver(function (entries) { + for (var i = 0; i < entries.length; i++) { + var attrValue = entries[i].target.getAttribute(ATTR_NAME); + + if (attrValue) { + var callback = handlerCache[attrValue]; + if (typeof callback === 'function') { + callback(entries[i]); + } + } + } + }); + + return Object.freeze({ + observe: function (element, callback) { + if (!element || !(element instanceof Element)) { + console.log && console.log('createResizeObserver: Cannot observe non-Element.'); + return; + } + + var attrValue = element.getAttribute(ATTR_NAME); + if (!attrValue) { + attrValue = generateUniqueId(namespace); + element.setAttribute(ATTR_NAME, attrValue); + } + + // 使用同一个观察者实例多次观察同一个元素,不会重复添加 + handlerCache[attrValue] = callback; + o.observe(element); + }, + unobserve: function (element) { + if (!element || !(element instanceof Element)) { + console.log && console.log('createResizeObserver: Cannot unobserve non-Element.'); + return; + } + + var attrValue = element.getAttribute(ATTR_NAME); + if (!attrValue) { + return; + } + + // 清除相关回调 + if (handlerCache[attrValue]) { + delete handlerCache[attrValue]; + } + + element.removeAttribute(ATTR_NAME); + o.unobserve(element); + }, + disconnect: function () { + for (var key in handlerCache) { + if (lay.hasOwn(handlerCache,key)) { + delete handlerCache[key]; + var elem = document.querySelector('[' + ATTR_NAME + '="' + key + '"]'); + if(elem){ + elem.removeAttribute(ATTR_NAME); + } + } + } + o.disconnect(); + } + }); + }; + /* * lay 元素操作