fix(select): select 面板大小变化时重新定位

feat/dropdown-mulit
sight 2025-09-04 21:36:02 +08:00
parent af6ba6c972
commit 99d5974092
3 changed files with 118 additions and 0 deletions

View File

@ -9,6 +9,7 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
var $ = layui.$; var $ = layui.$;
var laytpl = layui.laytpl; var laytpl = layui.laytpl;
var util = layui.util; var util = layui.util;
var lay = layui.lay;
var hint = layui.hint(); var hint = layui.hint();
var i18n = layui.i18n; var i18n = layui.i18n;
var device = layui.device(); var device = layui.device();
@ -20,6 +21,8 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
var MOD_INDEX_OPENED = MOD_INDEX + '_opened'; var MOD_INDEX_OPENED = MOD_INDEX + '_opened';
var MOD_ID = 'lay-' + MOD_NAME + '-id'; var MOD_ID = 'lay-' + MOD_NAME + '-id';
var resizeObserver = lay._createResizeObserver(MOD_NAME);
// 外部接口 // 外部接口
var dropdown = { var dropdown = {
config: { config: {
@ -361,6 +364,11 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
} }
}); });
if(resizeObserver){
resizeObserver.observe(options.elem[0], that.position.bind(that));
resizeObserver.observe(mainElem[0], that.position.bind(that));
}
// 组件打开完毕的事件 // 组件打开完毕的事件
typeof options.ready === 'function' && options.ready(mainElem, options.elem); typeof options.ready === 'function' && options.ready(mainElem, options.elem);
}; };
@ -392,6 +400,10 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
mainElem.prev('.' + STR_ELEM_SHADE).remove(); // 先移除遮罩 mainElem.prev('.' + STR_ELEM_SHADE).remove(); // 先移除遮罩
mainElem.remove(); mainElem.remove();
options.elem.removeData(MOD_INDEX_OPENED); options.elem.removeData(MOD_INDEX_OPENED);
if(resizeObserver){
resizeObserver.unobserve(options.elem[0]);
resizeObserver.unobserve(mainElem[0]);
}
delete dropdown.thisId; delete dropdown.thisId;
typeof options.close === 'function' && options.close(options.elem); typeof options.close === 'function' && options.close(options.elem);
} }

View File

@ -8,6 +8,7 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){
var $ = layui.$; var $ = layui.$;
var layer = layui.layer; var layer = layui.layer;
var util = layui.util; var util = layui.util;
var lay = layui.lay;
var hint = layui.hint(); var hint = layui.hint();
var device = layui.device(); var device = layui.device();
var i18n = layui.i18n; 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 OUT_OF_RANGE = 'layui-input-number-out-of-range';
var BAD_INPUT = 'layui-input-number-invalid'; var BAD_INPUT = 'layui-input-number-invalid';
var resizeObserver = lay._createResizeObserver(MOD_NAME);
// ie8 中可以获取到 input 元素的 'indeterminate' 属性描述符,但重新定义 getter/setter 无效,无报错 // ie8 中可以获取到 input 元素的 'indeterminate' 属性描述符,但重新定义 getter/setter 无效,无报错
// AppleWebKit/537.36 无法获取 input 元素任意属性的属性描述符(包括lookupGetter),但可以重新定义 getter/setter // AppleWebKit/537.36 无法获取 input 元素任意属性的属性描述符(包括lookupGetter),但可以重新定义 getter/setter
var needCheckboxFallback = (lay.ie && parseFloat(lay.ie) === 8) var needCheckboxFallback = (lay.ie && parseFloat(lay.ie) === 8)
@ -523,6 +526,9 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){
updatePosition(); updatePosition();
$(window).on('resize.lay_select_resize', 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 top = reElem.offset().top + reElem.outerHeight() + 5 - $win.scrollTop();
var dlHeight = dl.outerHeight(); var dlHeight = dl.outerHeight();
@ -575,6 +581,9 @@ layui.define(['lay', 'i18n', 'layer', 'util'], function(exports){
if(isAppendTo){ if(isAppendTo){
reElem.detach(); reElem.detach();
$(window).off('resize.lay_select_resize'); $(window).off('resize.lay_select_resize');
if(resizeObserver){
resizeObserver.unobserve(reElem[0]);
}
} }
if(choose) return; if(choose) return;

View File

@ -836,6 +836,103 @@
.replace(/\&/g, '&'); .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-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];
}
o.unobserve(element);
},
disconnect: function () {
o.disconnect();
handlerCache = {};
}
});
};
/* /*
* lay 元素操作 * lay 元素操作