From 22d3b5ffad4d69acbe69cfee01011969e2d41024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B4=A4=E5=BF=83?= <3277200+sentsim@users.noreply.github.com> Date: Mon, 20 Oct 2025 11:48:59 +0800 Subject: [PATCH] =?UTF-8?q?refactor(carousel):=20=E4=BD=BF=E7=94=A8=20comp?= =?UTF-8?q?onent=20=E6=A8=A1=E5=9D=97=E9=87=8D=E6=9E=84=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=20(#2857)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/carousel/index.md | 3 +- examples/carousel.html | 2 +- src/modules/carousel.js | 258 ++++++++++++++++++---------------------- 3 files changed, 117 insertions(+), 146 deletions(-) diff --git a/docs/carousel/index.md b/docs/carousel/index.md index a0b8422e..8c0b1c26 100644 --- a/docs/carousel/index.md +++ b/docs/carousel/index.md @@ -2,7 +2,7 @@ title: 轮播组件 carousel toc: true --- - + # 轮播组件 > 轮播组件 `carousel` 主要适用于跑马灯/轮播等交互场景。它并非单纯地为焦点图而生,准确地说,它可以满足任何内容的轮播式切换操作,亦可胜任 `fullpage`(全屏上下轮播)的需求。 @@ -25,6 +25,7 @@ div[carousel-item]>*:nth-child(2n+1){background-color: #16baaa;} | API | 描述 | | --- | --- | | var carousel = layui.carousel | 获得 `carousel` 模块。 | +| [基础接口](../component/#export) 2.13+ | 该组件由 `component` 构建,因此继承其提供的基础接口。| | [var inst = carousel.render(options)](#render) | carousel 组件渲染,核心方法。 | | [inst.reload(options)](#reload) | 轮播实例重载 | | [inst.goto(index)](#goto) 2.8+ | 轮播切换到特定下标 | diff --git a/examples/carousel.html b/examples/carousel.html index b5b544a8..e1262b85 100644 --- a/examples/carousel.html +++ b/examples/carousel.html @@ -84,7 +84,7 @@ layui.use('carousel', function(){ // trigger: 'hover' }); - // carInst.goto(1); + // console.log(carInst); carInst.goto(1); // 事件 /* diff --git a/src/modules/carousel.js b/src/modules/carousel.js index 333eb508..8e2df9b7 100644 --- a/src/modules/carousel.js +++ b/src/modules/carousel.js @@ -1,135 +1,110 @@ /** - * carousel 轮播模块 - * MIT Licensed + * carousel + * 轮播 */ -layui.define(['jquery', 'lay'], function(exports) { +layui.define('component', function(exports) { "use strict"; var $ = layui.$; var lay = layui.lay; - var hint = layui.hint(); - var device = layui.device(); + // 创建组件 + var component = layui.component({ + name: 'carousel', - // 外部接口 - var carousel = { - config: {}, // 全局配置项 - - // 设置全局项 - set: function(options) { - var that = this; - that.config = $.extend({}, that.config, options); - return that; + // 默认配置 + config: { + width: '600px', + height: '280px', + full: false, // 是否全屏 + arrow: 'hover', // 切换箭头默认显示状态:hover/always/none + indicator: 'inside', // 指示器位置:inside/outside/none + autoplay: true, // 是否自动切换 + interval: 3000, // 自动切换的时间间隔,不能低于 800ms + anim: '', // 动画类型:default/updown/fade + trigger: 'click', // 指示器的触发方式:click/hover + index: 0 // 初始开始的索引 }, - // 事件 - on: function(events, callback) { - return layui.onevent.call(this, MOD_NAME, events, callback); + CONST: { + ELEM: 'layui-carousel', + ELEM_ITEM: '>*[carousel-item]>*', + ELEM_LEFT: 'layui-carousel-left', + ELEM_RIGHT: 'layui-carousel-right', + ELEM_PREV: 'layui-carousel-prev', + ELEM_NEXT: 'layui-carousel-next', + ELEM_ARROW: 'layui-carousel-arrow', + ELEM_IND: 'layui-carousel-ind' + }, + + // 渲染 + render: function() { + var that = this; + var options = that.config; + + that.elemItem = options.elem.find(CONST.ELEM_ITEM); + + if (options.index < 0) { + options.index = 0; + } + if (options.index >= that.elemItem.length) { + options.index = that.elemItem.length - 1; + } + if (options.interval < 800) { + options.interval = 800; + } + + // 是否全屏模式 + if (options.full) { + options.elem.css({ + position: 'fixed', + width: '100%', + height: '100%', + zIndex: 9999 + }); + } else { + options.elem.css({ + width: options.width, + height: options.height + }); + } + + options.elem.attr('lay-anim', options.anim); + + // 初始焦点状态 + that.elemItem.eq(options.index).addClass(CONST.CLASS_THIS); + + // 指示器、箭头等动作 + that.indicator(); + that.arrow(); + that.autoplay(); + }, + + // 扩展实例方法 + extendsInstance: function() { + var that = this; + var options = that.config; + + // 确保与文档描述一致 + return { + elemInd: that.elemInd, + elemItem: that.elemItem, + timer: that.timer, + goto: function (index) { + that.goto(index); + }, + }; } - }; + }); - // 字符常量 - var MOD_NAME = 'carousel'; - var ELEM = '.layui-carousel'; - var THIS = 'layui-this'; - var SHOW = 'layui-show'; - var HIDE = 'layui-hide'; - var DISABLED = 'layui-disabled' + var CONST = component.CONST; - var ELEM_ITEM = '>*[carousel-item]>*'; - var ELEM_LEFT = 'layui-carousel-left'; - var ELEM_RIGHT = 'layui-carousel-right'; - var ELEM_PREV = 'layui-carousel-prev'; - var ELEM_NEXT = 'layui-carousel-next'; - var ELEM_ARROW = 'layui-carousel-arrow'; - var ELEM_IND = 'layui-carousel-ind'; + /** + * 扩展组件原型方法 + */ - // 构造器 - var Class = function(options) { - var that = this; - that.config = $.extend({}, that.config, carousel.config, options); - that.render(); - }; - - // 默认配置 - Class.prototype.config = { - width: '600px', - height: '280px', - full: false, // 是否全屏 - arrow: 'hover', // 切换箭头默认显示状态:hover/always/none - indicator: 'inside', // 指示器位置:inside/outside/none - autoplay: true, // 是否自动切换 - interval: 3000, // 自动切换的时间间隔,不能低于800ms - anim: '', // 动画类型:default/updown/fade - trigger: 'click', // 指示器的触发方式:click/hover - index: 0 // 初始开始的索引 - }; - - // 轮播渲染 - Class.prototype.render = function(){ - var that = this; - var options = that.config; - - // 若 elem 非唯一,则拆分为多个实例 - var elem = $(options.elem); - if(elem.length > 1){ - layui.each(elem, function(){ - carousel.render($.extend({}, options, { - elem: this - })); - }); - return that; - } - - // 合并 lay-options 属性上的配置信息 - $.extend(options, lay.options(elem[0])); - - options.elem = $(options.elem); - if(!options.elem[0]) return; - that.elemItem = options.elem.find(ELEM_ITEM); - - if(options.index < 0) options.index = 0; - if(options.index >= that.elemItem.length) options.index = that.elemItem.length - 1; - if(options.interval < 800) options.interval = 800; - - // 是否全屏模式 - if(options.full){ - options.elem.css({ - position: 'fixed', - width: '100%', - height: '100%', - zIndex: 9999 - }); - } else { - options.elem.css({ - width: options.width, - height: options.height - }); - } - - options.elem.attr('lay-anim', options.anim); - - // 初始焦点状态 - that.elemItem.eq(options.index).addClass(THIS); - - // 指示器、箭头等动作 - that.indicator(); - that.arrow(); - that.autoplay(); - - if (that.elemItem.length > 1) { - that.events(); - } - }; - - // 重置轮播 - Class.prototype.reload = function(options){ - var that = this; - clearInterval(that.timer); - that.config = $.extend({}, that.config, options); - that.render(); - }; + var Class = component.Class; // 获取上一个等待条目的索引 Class.prototype.prevIndex = function(){ @@ -209,16 +184,16 @@ layui.define(['jquery', 'lay'], function(exports) { // 模板 var tplArrow = $([ - '', - '' + '', + '' ].join('')); // 预设基础属性 options.elem.attr('lay-arrow', options.arrow); // 避免重复插入 - if(options.elem.find('.'+ELEM_ARROW)[0]){ - options.elem.find('.'+ELEM_ARROW).remove(); + if(options.elem.find('.'+CONST.ELEM_ARROW)[0]){ + options.elem.find('.'+CONST.ELEM_ARROW).remove(); } itemsCount > 1 ? options.elem.append(tplArrow) : tplArrow.remove(); @@ -249,7 +224,7 @@ layui.define(['jquery', 'lay'], function(exports) { var itemsCount = that.elemItem.length; // 模板 - var tplInd = that.elemInd = $(['