封装banner插件(完整版)
左右运动版轮播图
-
自动切换并且实现无缝斜街
-
点击焦点切换
-
点击左右切换
-
封装轮播图插件
-
...
window.οnlοad=function(){}容易被覆盖掉的解决方案
什么时候执行延迟加载:当页面加载成功才执行延迟加载。
window.οnlοad=function(){};但是window.onload在当前页面只能执行一次,所以容易被覆盖掉,最好不用
所以可以用window.addEventListener('load');但是不兼容
所以这里用定时器setTimeout();当整个js同步都执行完后(页面都加载完后)才会执行这个异步
所以很多时候都用定时器setTimeout()来代替window.onload
目录
思路
banner.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--<link rel="stylesheet/less" href="css/banner.less">
<script src="js/less-2.5.3.min.js"></script>-->
<link rel="stylesheet" href="css/banner.min.css">
</head>
<body>
<!--BANNER-->
<div class="container" id="container">
<!--WRAPPER-->
<ul class="wrapper clearfix">
<!--<li class="slide">
<a href="#">
<img src="img/banner1.jpg" alt="">
</a>
</li>-->
</ul>
<!--FOCUS-BOX-->
<ul class="focusBox clearfix">
<!--<li class="select"></li>
<li></li>-->
</ul>
<!--ARROW-->
<a href="javascript:;" class="arrow arrowLeft"></a>
<a href="javascript:;" class="arrow arrowRight"></a>
</div>
<div class="container" id="container2">
<!--WRAPPER-->
<ul class="wrapper clearfix">
</ul>
<!--FOCUS-BOX-->
<ul class="focusBox clearfix">
<!--<li class="select"></li>
<li></li>-->
</ul>
</div>
<!--IMPORT JS-->
<script src="js/utils.min.js"></script>
<script src="js/animate.min.js"></script>
<script src="js/banner.js"></script>
</body>
</html>
复制代码
banner.less
@import "reset";
.container {
@W: 1000px;
@H: 300px;
position: relative;
margin: 20px auto;
width: @W;
height: @H;
text-align: center;
overflow: hidden;
background: url("../img/default.gif") no-repeat center center #EEE;
.wrapper {
position: absolute;
top: 0;
left: 0;
width: unit(unit(@W,px)*10, px); //=>需要在JS中根据获取的数据动态设定宽度
height: @H;
.slide {
float: left;
width: @W;
height: @H;
a {
display: block;
width: @W;
height: @H;
img {
display: none;
width: @W;
height: @H;
opacity: 0;
filter: alpha(opacity=0);
}
}
}
}
.focusBox {
display: inline-block;
position: relative;
top: unit(unit(@H,px)-30, px);
z-index: 999;
padding: 4px;
background: #999;
background: rgba(0, 0, 0, .5);
border-radius: 20px;
li {
float: left;
margin: 0 4px;
width: 12px;
height: 12px;
background: #FFF;
border-radius: 50%;
cursor: pointer;
&.select {
background: #E01D20;
}
}
}
.arrow {
display: none;
position: absolute;
top: 50%;
margin-top: -22.5px;
width: 28px;
height: 45px;
background: url("../img/pre.png") no-repeat;
opacity: 0.5;
filter: alpha(opacity=50);
&.arrowLeft {
left: 0;
}
&.arrowRight {
right: 0;
background-position: -50px 0;
}
&:hover {
opacity: 1;
filter: alpha(opacity=100);
}
}
}
复制代码
reset.less
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, button, input, textarea, th, td {
margin: 0;
padding: 0
}
body {
font-size: 12px;
font-style: normal;
font-family: "\5FAE\8F6F\96C5\9ED1", Helvetica, sans-serif
}
small {
font-size: 12px
}
h1 {
font-size: 18px
}
h2 {
font-size: 16px
}
h3 {
font-size: 14px
}
h4, h5, h6 {
font-size: 100%
}
ul, ol {
list-style: none
}
a {
text-decoration: none;
background-color: transparent
}
a:hover, a:active {
outline-width: 0;
text-decoration: none
}
table {
border-collapse: collapse;
border-spacing: 0
}
hr {
border: 0;
height: 1px
}
img {
border-style: none
}
img:not([src]) {
display: none
}
svg:not(:root) {
overflow: hidden
}
html {
-webkit-touch-callout: none;
-webkit-text-size-adjust: 100%
}
input, textarea, button, a {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0)
}
article, aside, details, figcaption, figure, footer, header, main, menu, nav, section, summary {
display: block
}
audio, canvas, progress, video {
display: inline-block
}
audio:not([controls]), video:not([controls]) {
display: none;
height: 0
}
progress {
vertical-align: baseline
}
mark {
background-color: #ff0;
color: #000
}
sub, sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline
}
sub {
bottom: -0.25em
}
sup {
top: -0.5em
}
button, input, select, textarea {
font-size: 100%;
outline: 0
}
button, input {
overflow: visible
}
button, select {
text-transform: none
}
textarea {
overflow: auto
}
button, html [type="button"], [type="reset"], [type="submit"] {
-webkit-appearance: button
}
button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0
}
button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText
}
[type="checkbox"], [type="radio"] {
box-sizing: border-box;
padding: 0
}
[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button {
height: auto
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px
}
[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration {
-webkit-appearance: none
}
::-webkit-input-placeholder {
color: inherit;
opacity: .54
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit
}
.clearfix:after {
display: block;
height: 0;
content: "";
clear: both
}
复制代码
banner.js
~function (options) {
var container = document.getElementById('container'),
containerChild = utils.children(container),
wrapper = containerChild[0],
focusBox = containerChild[1],
arrowLeft = containerChild[2],
arrowRight = containerChild[3];
var slideList = null,
imgList = null,
focusList = null,
bannerData = null,
containerWidth = container.clientWidth;
//=>INIT PARAMETERS 默认设置
var _default = {
initIndex: 0,
autoInterval: 2000
};
//遍历options替换默认设置
for (var key in options) {
if (options.hasOwnProperty(key)) {
_default[key] = options[key];
}
}
var initIndex = _default.initIndex,
autoInterval = _default.autoInterval;
//=>GET DATA & BIND DATA
~function () {
//->AJAX GET DATA 获取数据
var xhr = new XMLHttpRequest();
xhr.open('GET', 'json/banner.json', false);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
bannerData = utils.toJSON(xhr.responseText);
}
};
xhr.send(null);
//->BIND DATA 绑定数据
var str = ``,
strFocus = ``;
for (var i = 0; i < bannerData.length; i++) {
var item = bannerData[i];
str += `<li class="slide">
<a href="${item.link}">
<img src="" data-img="${item.img}" alt="${item.desc}">
</a>
</li>`;
strFocus += `<li></li>`;
}
wrapper.innerHTML = str;
focusBox.innerHTML = strFocus;
//->GET ELEMENT LIST
slideList = wrapper.getElementsByTagName('li');
imgList = wrapper.getElementsByTagName('img');
focusList = focusBox.getElementsByTagName('li');
//=>CLONE 克隆第一张到末尾 cloneNode(true)深度克隆
wrapper.appendChild(slideList[0].cloneNode(true));
//->COMPUTED WRAPPER WIDTH
utils.css(wrapper, 'width', (bannerData.length + 1) * containerWidth);
}();
//=>INIT SHOW & LAZY IMG
~function () {
//->FOCUS DEFAULT SHOW
for (var i = 0; i < focusList.length; i++) {
focusList[i].className = i === initIndex ? 'select' : null;
}
//->WRAPPER DEFAULT SHOW
utils.css(wrapper, 'left', -containerWidth * initIndex);
//->LAZY IMG 懒加载
// 什么时候执行延迟加载:当页面加载成功才执行延迟加载
// window.onload=function(){};但是window.onload在当前页面只能执行一次,所以容易被覆盖掉,最好不用。
// 所以可以用window.addEventListener('load');但是不兼容
// 所以这里用定时器setTimeout();当整个js同步都执行完后(页面都加载完后)才会执行这个异步,所以这里500ms可以写成0ms也行
// 所以很多时候都用定时器setTimeout()来代替window.onload
var timer = setTimeout(function () {
for (var k = 0; k < imgList.length; k++) {
lazyImg(imgList[k]);
}
clearTimeout(timer);
}, 500);
function lazyImg(curImg) {
var tempImg = new Image;
tempImg.onload = function () {
curImg.src = this.src;
curImg.style.display = 'block';
animate({
curEle: curImg,
target: {opacity: 1},
duration: 200
});
tempImg = null;
};
tempImg.src = curImg.getAttribute('data-img');
}
}();
//=>AUTO CHANGE 自动切换 当运动到最后一张,让wrapper瞬移到第一张,并且让initIndex = 1,再执行动画就从第二张开始
var autoTimer = null;
autoTimer = setInterval(autoMove, autoInterval);
function autoMove() {
initIndex++;
if (initIndex === bannerData.length + 1) {
utils.css(wrapper, 'left', 0);
initIndex = 1;
}
change();
}
//=>MOUSE EVENT
container.onmouseenter = function () {
clearInterval(autoTimer);
arrowLeft.style.display = arrowRight.style.display = 'block';
};
container.onmouseleave = function () {
autoTimer = setInterval(autoMove, autoInterval);
arrowLeft.style.display = arrowRight.style.display = 'none';
};
//=>BIND FOCUS EVENT
~function () {
for (var i = 0; i < focusList.length; i++) {
focusList[i].myIndex = i;
focusList[i].onclick = function () {
initIndex = this.myIndex;
change();
}
}
}();
//=>BIND ARROW EVENT
~function () {
arrowRight.onclick = autoMove;
arrowLeft.onclick = function () {
initIndex--;
if (initIndex === -1) {
//->RUN TO CLONE ELEMENT
utils.css(wrapper, 'left', -bannerData.length * containerWidth);
initIndex = bannerData.length - 1;
}
change();
}
}();
//=>CHANGE
function change() {
animate({
curEle: wrapper,
target: {left: -initIndex * containerWidth},
duration: 300
});
//->CHANGE FOCUS
var tempIndex = initIndex;
tempIndex === bannerData.length ? tempIndex = 0 : null;
for (var i = 0; i < focusList.length; i++) {
focusList[i].className = i === tempIndex ? 'select' : null;
}
}
}();
复制代码
banner.json
复制代码
[
{
"id": 1,
"img": "img/banner1.jpg",
"desc": "推荐机会",
"link": "http://www.baidu.com/"
},
{
"id": 2,
"img": "img/banner2.jpg",
"desc": "梦想起飞",
"link": "http://www.baidu.com/"
},
{
"id": 3,
"img": "img/banner3.jpg",
"desc": "把握未来",
"link": "http://www.baidu.com/"
},
{
"id": 4,
"img": "img/banner4.jpg",
"desc": "先学习",
"link": "http://www.baidu.com/"
}
]
复制代码
封装banner插件(封装插件的基本思路)
插件思想:功能越强大越好
首先理解jq中最难理解的部分:
如何让一个函数执行,创建一个属于自己函数和这个类的实例
~function () {
function BannerPlugin(options) {//构造函数创建一个类 options配置参数
return new BannerPlugin.fn.init(options);
}
BannerPlugin.fn = BannerPlugin.prototype = {};
var init = BannerPlugin.fn.init = function (options) {
};
init.prototype = BannerPlugin.prototype;
}();
//--------------------------以上可以简写成以下-----------------------------------------
// 封装插件直接用构造函数模式 先写一个自执行函数~function (){},
// 在里面创建一个类BannerPlugin(),
// 执行BannerPlugin()会配置很多参数,很多参数用options来配置
~function () {
function BannerPlugin(options) {
// 执行BannerPlugin这个方法创建的是init对应函数的实例,
// 但是会用到BannerPlugin.prototype原型上的方法,所以
// BannerPlugin.prototype.init.prototype = BannerPlugin.prototype;
return new BannerPlugin.prototype.init(options);
}
BannerPlugin.prototype = {
//为了保证完构造函数完整性,constructor:BannerPlugin
//见JS中的闭包及面向对象编程 — 2、面向对象编程详解 19-2重新构造原型(最常用))
constructor:BannerPlugin,
init:function (options) { // 创建的是init时有个形参options,这里需要通过options接收
// 这里的this也可以调用BannerPlugin原型上的方法 看到20:20
}
};
// 让INIT的原型指向BANNER-PLUGIN的原型,目的:当执行BANNER-PLUGIN方法的时候创建出来的依然是BANNER-PLUGIN类的实例
BannerPlugin.prototype.init.prototype = BannerPlugin.prototype;
console.dir(BannerPlugin({}));//直接执行BannerPlugin()先创建init实例,由init实例再变成BannerPlugin实例,不用再通过newBannerPlugin()去创建BannerPlugin实例
window.$banner = window.BannerPlugin = BannerPlugin;//暴露BannerPlugin
}();
BannerPlugin({});
$banner({});
复制代码
图解:
首先一个类BannerPlugin(),有属性prototype;
BannerPlugin.prototype开辟一个新堆内存;(自己开辟的新堆内存没有constructor, 为了保证完构造函数完整性,constructor:BannerPlugin 见JS中的闭包及面向对象编程 — 2、面向对象编程详解 19-2重新构造原型(最常用));
原型prototype的_proto_都指向Object的原型
BannerPlugin.prototype里面有个init方法,方法又是一个堆内存BannerPlugin.prototype.init (BannerPlugin.prototype.init又是一个函数数据类型,有属性prototype)
BannerPlugin.prototype.init.prototype = BannerPlugin.prototype:让init的原型指向BannerPlugin的原型, 目的:当执行BannerPlugin方法的时候会通过return new BannerPlugin.prototype.init(options)创建init这个方法 的实例(init的实例),init的实例有_proto_指向所属类的原型,最终还是指向了BannerPlugin的原型,所以创 建的init依然是BannerPlugin类的实例
为什么要这么做呢,为什么不直接创建BannerPlugin这个类的实例呢?
这么做有个好处=>直接执行BannerPlugin({})返回的实例就是BannerPlugin()这个类的实例,不再需要通过new BannerPlugin()去创建这个类的实例, 而是通过先创建init实例,由init实例再变成BannerPlugin实例(通过console.dir(BannerPlugin({}))打印出来看是个死循环嵌套, 在原型里面是没有这个概念的,因为constructor构造函数虽然指向BannerPlugin,但是和普通类还是有所区别,并不会形成死循环)如图:
这个怎么去找上级?
init实例里面没有通过_proto_找到BannerPlugin.prototype,BannerPlugin.prototype没有再通过BannerPlugin.prototype.proto 找到Object.prototype。(这里上级查找不会去找BannerPlugin.prototype里的constructor,这个不会形成死循环)
封装插件
看懂了jq最难理解的部分,接下来一步步写插件
plugin-banner.js参照banner.js封装成插件的,对应banner.js看(方法里面的代码都是复制粘贴,改变参数,涉及utils的用原生,this...),注意this,并且把很多属性方法写在私有属性上就可以了。
plugin-banner.js
/*
* 分析我们需要支持的部分:
* [基础]
* 数据动态绑定的地址是不同的 (url)
* 切换速度 (speed:300)
* 默认展示第几张 (initIndex:0)
* 延迟多久进行图片懒加载 (lazyImgTime:500)
*
* [自动切换]
* 是否支持自动切换 (needAutoChange:true)
* 自动切换的间隔时间 (autoInterval:2000)
*
* [焦点]
* 是否显示焦点 (isFocusShow:true)
* 是否需要通过焦点切换 (needFocusChange:true)
* 什么样的事件控制焦点切换 (focusEvent:click)
*
* [左右切换]
* 是否支持左右切换 (isArrowShow:true)
*/
~function () {
function BannerPlugin(options) {
return new BannerPlugin.prototype.init(options);
}
BannerPlugin.prototype = {
constructor: BannerPlugin,
//=>1、声明可扩充参数的默认值,并且让传递参数的值OPTIONS替换原有的默认值(把需要用的参数扩展到实例的私有属性上)
initDefault: function (options) {
var _default = {
container: null,
url: null,
initIndex: 0,
speed: 300,
lazyImgTime: 500,
needAutoChange: true,
autoInterval: 2000,
isFocusShow: true,
needFocusChange: true,
focusEvent: 'click',
isArrowShow: true
};
//=>循环options替换默认值
for (var key in options) {
if (options.hasOwnProperty(key)) {
_default[key] = options[key];
}
}
//=>把_DEFAULT中的每一项遍历到THIS实例上(写到私有属性上)后销毁_default
for (key in _default) {
if (_default.hasOwnProperty(key)) {
this[key] = _default[key];
}
}
_default = null;
},
//=>3、AJAX数据绑定(复制banner.js中的代码逻辑,修改url,把bannerData扩充到实例上,获取元素和克隆)
// 这里ajax用的同步编程,项目中用异步(需要用到promise),(所以这个封装是个入门的插件,不建议项目中使用,同步会有问题)
queryData: function () {
var xhr = new XMLHttpRequest(),
bannerData = null;
xhr.open('GET', this.url, false);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
bannerData = JSON.parse(xhr.responseText);
}
};
xhr.send(null);
//=>扩充到实例上,方便以后再其它方法中使用
this.bannerData = bannerData;
},
bindData: function () {
var str = ``,
strFocus = ``;
for (var i = 0; i < this.bannerData.length; i++) {
var item = this.bannerData[i];
str += `<li class="slide">
<a href="${item.link}">
<img src="" data-img="${item.img}" alt="${item.desc}">
</a>
</li>`;
strFocus += `<li data-index="${i}"></li>`;
}
this.wrapper.innerHTML = str;
this.isFocusShow ? this.focusBox.innerHTML = strFocus : null;
//=>其它事情
this.slideList = this.wrapper.getElementsByTagName('li');
this.imgList = this.wrapper.getElementsByTagName('img');
this.isFocusShow ? this.focusList = this.focusBox.getElementsByTagName('li') : null;
//=>克隆第一张到末尾
this.wrapper.appendChild(this.slideList[0].cloneNode(true));
this.wrapper.style.width = (this.bannerData.length + 1) * this.containerWidth;
},
//=>6、图片延迟加载
lazyImg: function () {
var _this = this;
var timer = setTimeout(function () {//setTimeout中的this是window
[].forEach.call(_this.imgList, function (curImg) {
var tempImg = new Image;
tempImg.onload = function () {
curImg.src = this.src;
curImg.style.display = 'block';
animate({
curEle: curImg,
target: {opacity: 1},
duration: 200
});
tempImg = null;
};
tempImg.src = curImg.getAttribute('data-img');
});
clearTimeout(timer);
}, this.lazyImgTime);
},
//=>8、默认展示
showInit: function () {
var _this = this;
if (_this.isFocusShow) {
[].forEach.call(_this.focusList, function (item, index) {
item.className = index === _this.initIndex ? 'select' : null;
});
}
_this.wrapper.style.left = -_this.containerWidth * _this.initIndex + 'px';
},
//=>10、自动切换
change: function () {
animate({
curEle: this.wrapper,
target: {left: -this.initIndex * this.containerWidth},
duration: this.speed
});
//->CHANGE FOCUS
if (this.isFocusShow) {
var tempIndex = this.initIndex;
tempIndex === this.bannerData.length ? tempIndex = 0 : null;
[].forEach.call(this.focusList, function (item, index) {
item.className = index === tempIndex ? 'select' : null;
});
}
},
autoMove: function () {
this.initIndex++;
if (this.initIndex === this.bannerData.length + 1) {
this.wrapper.style.left = 0;
this.initIndex = 1;
}
this.change();
},
//=>12、其它切换方式
mouseEvent: function () {
var _this = this;
_this.container.onmouseenter = function () {
_this.needAutoChange ? clearInterval(_this.autoTimer) : null;
_this.isArrowShow ? _this.arrowLeft.style.display = _this.arrowRight.style.display = 'block' : null;
};
_this.container.onmouseleave = function () {
_this.needAutoChange ? _this.autoTimer = setInterval(_this.autoMove.bind(_this), _this.autoInterval) : null;
_this.isArrowShow ? _this.arrowLeft.style.display = _this.arrowRight.style.display = 'none' : null;
};
},
arrowEvent: function () {
var _this = this;
if (!_this.isArrowShow) return;
_this.arrowRight.onclick = _this.autoMove.bind(_this);//保证_this.autoMove方法中的this是实例
_this.arrowLeft.onclick = function () {
_this.initIndex--;
if (_this.initIndex === -1) {
_this.wrapper.style.left = -_this.bannerData.length * _this.containerWidth + 'px';
_this.initIndex = _this.bannerData.length - 1;
}
_this.change();
}
},
eventFocus: function () {
var _this = this;
if (!_this.isFocusShow) return;
if (!_this.needFocusChange) return;
[].forEach.call(_this.focusList, function (item, index) {
item['on' + _this.focusEvent] = function () {
_this.initIndex = index;
_this.change();
}
});
},
delegateEvent: function () {
var _this = this;
_this.container.onclick = function (e) {
e = e || window.event;
var target = e.target || e.srcElement,
targetParent = target.parentNode;
//=>焦点事件源
if (/(^| +)focusBox( +|$)/i.test(targetParent.className)) {
_this.initIndex = parseFloat(target.getAttribute('data-index'));
_this.change();
return;
}
//=>左右切换事件源
if (/(^| +)arrow( +|$)/i.test(target.className)) {
if (target.className.indexOf('arrowRight') > -1) {
_this.autoMove();
return;
}
_this.initIndex--;
if (_this.initIndex === -1) {
_this.wrapper.style.left = -_this.bannerData.length * _this.containerWidth + 'px';
_this.initIndex = _this.bannerData.length - 1;
}
_this.change();
}
};
},
init: function (options) {
//=>2、参数初始化
this.initDefault(options);
//=>4、获取需要使用的到的元素
// var container = document.getElementById('container'),
// containerChild = utils.children(container),
// wrapper = containerChild[0],
// focusBox = containerChild[1],
// arrowLeft = containerChild[2],
// arrowRight = containerChild[3];
// var slideList = null,
// imgList = null,
// focusList = null,
// bannerData = null,
// containerWidth = container.clientWidth;
// 以上可以写成
// this.wrapper = this.container.querySelector('.wrapper');
// this.focusBox = this.container.querySelector('.focusBox');
// this.arrowLeft = this.container.querySelector('.arrowLeft');
// this.arrowRight = this.container.querySelector('.arrowRight');
// this.containerWidth = this.container.clientWidth;
// var slideList = null,
// imgList = null,
// focusList = null;
// 以上可以写成
var _this = this;
['wrapper', 'focusBox', 'arrowLeft', 'arrowRight'].forEach(function (item, index) {
_this[item] = _this.container.querySelector('.' + item);
});
this.containerWidth = this.container.clientWidth;
//=>5、数据绑定
this.queryData();
this.bindData();
//=>7、图片延迟加载
this.lazyImg();
//=>9、默认展示
this.showInit();
//=>11、自动切换
// this.autoTimer = setInterval(function(){
// _this.autoMove();
// },this.autoInterval);
// 或者这样写
// this.autoTimer = setInterval(this.autoMove.bind(this),this.autoInterval);
if (this.needAutoChange) {
this.autoTimer = setInterval(this.autoMove.bind(this), this.autoInterval);
}
//=>13、其它方式切换
this.mouseEvent();
// this.arrowEvent();
// this.eventFocus();
this.delegateEvent();
}
};
// 14、深度扩展(类似jq一样,支持extend自己扩展方法,别人可以自己扩展方法,)
BannerPlugin.extend = function (obj, deep) {
typeof deep === 'undefined' ? deep = false : null;
for (var key in obj) {
//循环obj,替换插件原有方法,如果传递的obj中的方法在原插件中有,就continue不执行BannerPlugin.prototype[key] = obj[key];
// 如果传递的obj中的方法在原插件中有,并且deep是true的时候,替换到原型上方法执行BannerPlugin.prototype[key] = obj[key];
if (obj.hasOwnProperty(key)) {
if (BannerPlugin.prototype.hasOwnProperty(key)) {
if (deep) {
BannerPlugin.prototype[key] = obj[key];
}
continue;
}
BannerPlugin.prototype[key] = obj[key];
}
}
};
//=>让INIT的原型指向BANNER-PLUGIN的原型,目的:当执行BANNER-PLUGIN方法的时候创建出来的依然是BANNER-PLUGIN类的实例
BannerPlugin.prototype.init.prototype = BannerPlugin.prototype;
window.$banner = window.BannerPlugin = BannerPlugin;
}();
$banner({
container: document.getElementById('container'),
url: 'json/banner.json',
autoInterval: 3000,
initIndex: 2
});
var bannerExample = $banner({
container: document.getElementById('container2'),
url: 'json/banner2.json',
needFocusChange: false,
isArrowShow: false,
speed: 100,
lazyImgTime: 2000
});
// true深度扩展,把插件原有方法替换掉
// $banner.extend({
// aa: function () {
// }
// }, true);
// bannerExample.aa();//别人可以通过自己扩展aa()这个方法做一些其他的功能
//替换原型上的change方法
$banner.extend({
change: function () {
animate({
curEle: this.wrapper,
target: {left: -this.initIndex * this.containerWidth},
duration: this.speed,
effect: animateEffect.Bounce.easeOut
});
//->CHANGE FOCUS
if (this.isFocusShow) {
var tempIndex = this.initIndex;
tempIndex === this.bannerData.length ? tempIndex = 0 : null;
[].forEach.call(this.focusList, function (item, index) {
item.className = index === tempIndex ? 'select' : null;
});
}
}
}, true);
bannerExample.speed = 500;
复制代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--<link rel="stylesheet/less" href="css/banner.less">
<script src="js/less-2.5.3.min.js"></script>-->
<link rel="stylesheet" href="css/banner.min.css">
</head>
<body>
<!--BANNER-->
<div class="container" id="container">
<!--WRAPPER-->
<ul class="wrapper clearfix">
<!--<li class="slide">
<a href="#">
<img src="img/banner1.jpg" alt="">
</a>
</li>-->
</ul>
<!--FOCUS-BOX-->
<ul class="focusBox clearfix">
<!--<li class="select"></li>
<li></li>-->
</ul>
<!--ARROW-->
<a href="javascript:;" class="arrow arrowLeft"></a>
<a href="javascript:;" class="arrow arrowRight"></a>
</div>
<div class="container" id="container2">
<!--WRAPPER-->
<ul class="wrapper clearfix">
</ul>
<!--FOCUS-BOX-->
<ul class="focusBox clearfix">
<!--<li class="select"></li>
<li></li>-->
</ul>
</div>
<!--IMPORT JS-->
<script src="js/utils.min.js"></script>
<script src="js/animate.min.js"></script>
<script src="js/plugin-banner.js"></script>
</body>
</html>
复制代码
banner2.json
[
{
"id": 1,
"img": "img/banner1.jpg",
"desc": "推荐机会",
"link": "http://www.baidu.com/"
},
{
"id": 2,
"img": "img/banner2.jpg",
"desc": "梦想起飞",
"link": "http://www.baidu.com/"
},
{
"id": 3,
"img": "img/banner3.jpg",
"desc": "把握未来",
"link": "http://www.baidu.com/"
}
]
复制代码