js 写插件入门(垂直循环播报)
阅读 (198) 2020-07-20 11:41:57
原生JS写插件,本例重点在于JS对DOM的操作,css过渡效果
之前用jQuery操作dom实现过循环播报的功能,先看一下jQuery实现:
HTML:用到jquery, 动画css引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>垂直循环播报demo | PHPer | Web前端 | 编程爱好者 | 郑凯文的个人网站</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.0/animate.min.css" rel="stylesheet">
</head>
<body style="padding: 20px;margin: 0;">
<ul id="list-box"></ul>
</body>
</html>
JS:
$(document).ready(function () {
var data = [
{
userNickName: '张三',
lastTime: '2020-07-20 10:00:00',
title: '瘦腿9分裤'
},
{
userNickName: '李四',
lastTime: '2020-07-20 10:00:00',
title: '收腰小西服'
},
{
userNickName: '王五',
lastTime: '2020-07-20 10:00:00',
title: '性感小内裤'
},
]
var html = ''
for (var key in data) {
if (data.hasOwnProperty(key)) {
var item = data[key];
html += '<li style="display:none;">' + item.userNickName + ' ' + item.lastTime + '成功购买了' + item.title + '</li>';
}
}
// DOM渲染
$('#list-box').html(html);
// 显示第一个li
$('#list-box li').first().show().addClass('animate__animated animate__fadeInUp');
// 最后一个加上特定样式
$('#list-box li').last().addClass('last');
// 定时器,3秒滚动循环播放
var timer = setInterval(function() {
// 找到.animate__animated的下一个同级元素
$next = $('#list-box li.animate__animated').next();
// 先把当前显示的元素样式移除并隐藏
$('#list-box li.animate__animated').removeClass('animate__animated animate__fadeInUp').hide();
// 接下来准备显示下一个元素,但需要判断一下是不是最后一个元素,如果是则把最后一个元素复制到第一个,方便下次循环时,直接用next()找到下一个同级元素
// 如果是最后一个元素
if ($next.hasClass('last')) {
// 把最后一个li复制一个到第一个
$('#list-box').prepend('<li style="display:none;">' + $next.html() + '</li>');
// 删除最后一个li
$('#list-box li.last').remove();
// 在现在最后一个li上加上last标记
$('#list-box li').last().addClass('last');
// 显示第一个li
$('#list-box li').first().show().addClass('animate__animated animate__fadeInUp');
} else {
// 不是最后一个li元素的话,正常显示
$next.show().addClass('animate__animated animate__fadeInUp');
}
}, 3000);
});
加载了完整的animate.css,实际就用到了几句,也可以自己单独引用我们这里需要的特效即可:
:root {
--animate-duration: 1s;
--animate-delay: 1s;
--animate-repeat: 1;
}
.animate__animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-duration: var(--animate-duration);
animation-duration: var(--animate-duration);
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
@keyframes fadeInUp {
from {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.animate__fadeInUp {
-webkit-animation-name: fadeInUp;
animation-name: fadeInUp;
}
-----------分割线-----------
然后再看一下原生js如何实现,实现上有什么区别,首先第一点,dom还是要在插件以外去自行渲染,然后再考虑js怎么让元素滚动循环播放起来,本例想到的是将列表元素内容都先记录到数组中,再设置定时器,记录当前显示元素的下标,下标累加,显示到最后一个元素后,再将下标设置为0从头开始,达到循环的滚动的效果,当然,上面用jquery实现的方式也可以改用这种方式,但上面jquery的样例主要对dom的操作,同样原生js也可以对dom操作加样式实现,但这里写另一种方法去实现
demo: https://returnc.com/demo/slider-1.html
;(function(undefined) {
"use strict"
var _global
// 插件函数
function Kmarquee(id, delay){
// 未使用new关键词时
if (!(this instanceof Kmarquee)){
// 等于再new一个
return new Kmarquee(id, delay)
}
this.play(id, delay)
}
Kmarquee.prototype = {
constructor: this,
// 核心代码
play: function (id, delay) {
var _this = this
var el = document.getElementById(id)
this.childrens = []
var tempChildren = el.children
// 拷贝,__proto__不再指向HTMLCollection
for (const key in tempChildren) {
if (tempChildren.hasOwnProperty(key)) {
const item = tempChildren[key];
this.childrens.push(item)
}
}
console.log(this.childrens)
// 默认显示的元素下标,从第一个开始
var pos = 0
// 这里直接定义了li元素,这点不太好,限定死了元素类型
el.innerHTML = '<li class="animate__animated animate__fadeInUp">'+this.childrens[0].innerHTML+'</li>'
// 子元素总数
var maxCount = this.childrens.length
// 定时执行,循环设置显示元素的内容
setInterval(function() {
pos++;
// 如果下标等于最大数,则又从0开始
if (pos == maxCount) {
pos = 0
}
el.innerHTML = '<li class="animate__animated animate__fadeInUp">'+_this.childrens[pos].innerHTML+'</li>'
}, delay);
},
}
// 插件引用时就向head中插入样式,只加载一次,这里的CSS不是重点,删掉自行加载写到自己的css中都行
var css = (function css() {
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.innerHTML = ':root { --animate-duration: 1s;--animate-delay: 1s;--animate-repeat: 1;}.animate__animated {-webkit-animation-duration: 1s;animation-duration: 1s;-webkit-animation-duration: var(--animate-duration);animation-duration: var( --animate-duration);-webkit-animation-fill-mode: both;animation-fill-mode: both;}@keyframes fadeInUp {from {opacity: 0;-webkit-transform: translate3d(0, 100%, 0);transform: ranslate3d(0, 100%, 0);} to { opacity: 1;-webkit-transform: translate3d(0, 0, 0);transform: translate3d(0, 0, 0);}}.animate__fadeInUp {-webkit-animation-name: fadeInUp;animation-name: fadeInUp;}';
head.appendChild(style);
})();
// 最后将插件对象暴露给全局对象
_global = (function(){ return this || (0, eval)('this'); }());
if (typeof module !== "undefined" && module.exports) {
module.exports = Kmarquee;
} else if (typeof define === "function" && define.amd) {
define(function(){return Kmarquee;});
} else {
!('Kmarquee' in _global) && (_global.Kmarquee = Kmarquee);
}
}());
$(document).ready(function () {
var data = [
{
userNickName: '张三',
lastTime: '2020-07-20 10:00:00',
title: '瘦腿9分裤'
},
{
userNickName: '李四',
lastTime: '2020-07-20 10:00:00',
title: '收腰小西服'
},
{
userNickName: '王五',
lastTime: '2020-07-20 10:00:00',
title: '性感小内裤'
},
]
var html = ''
for (var key in data) {
if (data.hasOwnProperty(key)) {
var item = data[key];
html += '<li>' + item.userNickName + ' ' + item.lastTime + '成功购买了' + item.title + '</li>';
}
}
// DOM渲染
$('#list-box').html(html);
// 插件调用
Kmarquee('list-box', 3000)
});
如果熟悉了这个套路,似乎自己动手写一个slider插件也不是很复杂了是不是?
更新于:2020-07-21 11:09:58