Tab组件
组件化的原则
一 、正交原则
正交原则类似数学中的直角坐标系
一个点只要在一条轴线上行走,他在其他两条轴上的坐标都不会改变。而在组件中,我们应该让html,css,js分离开来,尽量避免改动了其中一个,就造成了另外两个文件无法正常使用
举个例子
在tab组件中,点击哪一个标签,就要显示它下面的内容。一般人会使用$div.show()
与$.hide()
来控制内容的显示与隐藏。而这个jq的方法,其实是在html的行间样式上加上display:none/display:原来的状态
。用js去改变css,这样就违法了组件的正交原则,并且这个原来的状态,你很难判断它到底是什么,只要css一改变,这个状态就可能改变。
所以,比较正确的方法,应该是$div.addClass("active")
,这样就只是加了个class,js并没有干涉到css,符合正交原则
二 、面向接口原则
实现一个tab组件,如果一开始就想着内容应该怎么显示与隐藏,实现组件的细节,这是不对的。正确的方式应该是去想别人会怎么样去调用这个组件。如果使用者以new一个构造函数的方法去调用,那组件就要写成一个构造函数,再去考虑它要实现哪些功能,需要传进哪些参数
jq实现tab组件
效果展示
html
复制代码
- content-one
- content-two
- content-three
为了能加上样式,所以class必须是组件规定的,这是一个小小的缺点
css
.tabs{ border:1px solid #ff7800; width:94px;}.tabs > ol{//消除ol的默认样式 list-style:none; margin:0; padding:0; }.tabs > ol.tabs-bar{ display:flex;//flex默认让标签内的元素水平排列, border-bottom:px solid #ff7800;}.tabs > ol.tabs-bar >li{ padding:10px; border:1px solid #ff7800; border-bottom:0; color:#fff;}//鼠标移动到标签上时,出现hover的样式.tabs > ol.tabs-bar > li:hover{ background-color:#ff78aa;}//当标签被选中时的样式.tabs > ol.tabs-bar >li.active{ background-color:blue;}//内容默认是隐藏的.tabs >ol.tabs-content>li{ display:none; border:1px solid #ff7800;}//标签被选中时,内容显示.tabs >ol.tabs-content>li.active{ display:block; }复制代码
js
//考虑到别人会用new一个函数的方式来调用,所以写成构造函数的方法// new Tabs('.tabs');function Tabs(element){ //传进来到参数是类名,要用jq选中 this.elements = $(element); // 一个构造函数要有一个初始化的状态, // 在tabs中就是刚开始还没点击时,默认选中的第一个标签和显示第一内容 this.init();//由init来做初始化 //初始化后,就要给每个元素绑定上事件 this.bindEvent();}复制代码
Tabs函数初始化的实现
Tabs.prototype.init = function(){ // 实现默认状态,选中第一个标签和显示第一个内容 // 因为可能由很多个tabs组件,所以这里要给选中的标签遍历一下 this.elements.each(function(index,item){ //遍历过后的item是个原生的dom,所以这里要再一次选中 $(item).children(".tabs-bar").children('li').first().addClass('active'); $(item).children(".tabs-content").children('li').first().addClass('active'); })}复制代码
Tabs函数绑定事件功能的实现
Tabs.prototype.bindEvent = function(){ // 为了性能,我们不可能给每个li标签绑定上事件, // 我们可以利用事件捕获,给最外部的标签加上事件,来监听是不是li被点击了 this.elements.on("click",'.tabs-bar > li',function(e){ // 第二个参数是限定点击是li标签时才触发 $li = $(e.currentTarget);//这里currentTarget就是li标签,不过是原生的, // 再jq中,只要是以形参的方式出现在jq的回调函数中的dom,都是原生dom,所以要记得用$再次选中 $li.addClass('active').siblings().removeClass('active'); // 点击了li标签后要知道他的序号,这样才能知道要显示哪个内容 var index = $li.index(); //closest()可以匹配离他最近的父级的元素,包括他自己本身 $li.closest('.tabs').children('.tabs-content') .children("li").eq(index).addClass('active') .siblings().removeClass('active') // 在这里要注意,找 .tabs 标签不能 $('.tabs),因为你将匹配到多个dom,点击其中一个tab的标签,其他tab组件也会跟着变动 //所以,选中dom要从小到大去选,所以此处用$li.closest() })}复制代码
结语
本文作者胡志武,写于2019/5/7,转载请注明出处,另外走过路过不要忘记点个赞哦。