js 写插件入门(垂直循环播报)

阅读 (254)
原生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
返回顶部