创建与框架无关的JavaScript插件


Posted in Javascript onDecember 01, 2020

JavaScript 中的插件使我们能够扩展语言,以实现所需的某些强大(或不够强大)的功能。插件/库本质上是打包的代码,可以使我们免于一遍又一遍地编写相同的东西(功能)。

在 JavaScript 生态系统中,有数百个框架,这些框架中的每一个都为我们提供了一个创建插件的系统,以便为框架添加新的东西。

如果你看一下 NPM 注册表,几乎所有的 JavaScript 插件都是在那里发布的,你会看到有超过一百万个插件以简单库和框架的形式发布。

为每个框架创建插件的方式可能会有很大不同。例如,Vue.js 有自己的插件系统,这与你为 React.js 创建插件的方式不同。然而,这一切都归结为相同的 JavaScript 代码。

因此,使用普通 JavaScript 创建插件,让你有能力创建一个无论在哪个框架下都能使用。

“与框架无关的 JavaScript 插件是无需框架上下文即可工作的插件,您可以在任何框架(甚至没有框架)中使用插件”

构建库时要记住的事项

  • 您应该对插件有一个目标——这是插件要实现的关键
  • 您的插件应易于使用以达到预期用途
  • 您的插件应在很大程度上可定制
  • 您的插件应该有一个文档,指导将要使用该插件的开发人员

现在,让我们着眼于上述几点。

我们将创造什么

在本文中,我将向您展示如何创建与框架无关的插件。在本教程中,我们将创建一个旋转木马/幻灯片插件——该插件的目标。

这个插件会暴露一些方法,可以被插件的用户调用 .next() 和 .prev()

起步

让我们创建一个新的文件夹来存放我们的插件代码和任何其他必要的文件,我将把我的文件夹称为 TooSlidePlugin。

在这个文件夹中,在你喜欢的编辑器中创建一个新的 JavaScript 文件。这个文件将包含插件的代码,我把我的文件叫做 tooSlide.js。

有时,我什至想像在开始创建插件之前(从最终开发人员的角度)如何使用插件。

var slider = new ToolSidePlugin({
 slideClass: ".singleSlide",
 container: ".slideContainer",
 nextButton: ".next",
 previousButton: ".prev",
});

上面的代码假定有一个名为 TooSlides 的构造函数,该构造函数接收具有某些属性的对象作为参数。对象的属性是 slidesClass、container、nextButton 和 previousButton,这些是我们希望用户能够自定义的属性。

我们将从将插件创建为单个构造函数开始,以便其本身具有名称空间。

function ToolSidePlugin() {}

Options

由于我们的插件,TooSlides 需要一个选项参数,所以我们会定义一些默认的属性,这样如果我们的用户没有指定自己的属性,就会使用默认的属性。

function ToolSidePlugin(options) {
 let defaultOptions = {
  slideClass: ".singleSlide",
  container: ".slideContainer",
  nextButton: ".nextSlide",
  previousButton: ".previousSlide",
 };

 options = { ...defaultOptions, ...options };

 let _this = this;
 let slides = [];
 let currentSlideIdex = 0;
}

我们创建了一个 defaultOptions 对象来保存一些属性,我们还使用 JavaScript 扩展操作符将传入的选项与默认选项合并。我们将 this 分配给另一个变量,因此我们仍然可以在内部函数中对其进行访问。

我们还创建了两个变量 slides,它将保存所有我们想要用作幻灯片的图片,以及 currentSlideIndex,它保存当前正在显示的幻灯片的索引。

接下来,由于我们的幻灯片需要有一些控制,可以用来向前和向后移动幻灯片,我们将在构造函数中添加下面的方法。

this.prepareControls = function() {
 const nextButton = document.createElement("button");
 const previousButton = document.createElement("button");

 nextButton.setAttribute("class", "next");
 nextButton.InnerHTML = "Next";

 previousButton.setAttribute("class", "prev");
 nextButton.InnerHTML = "Prev";

 let controleContainer = document.createElement("div");

 controleContainer.setAttribute(
  "class",
  "too-slide-control-container"
 );

 controleContainer.appendChild(previousButton);
 controleContainer.appendChild(nextButton);

 document
  .querySelector(options.container)
  .appendChild(controleContainer);

 nextButton.addEventListener("click", function() {
  _this.next();
 });
 previousButton.addEventListener("click", function() {
  _this.previous();
 });
};

在 .prepareControls() 方法中,我们创建了一个容器 DOM 元素来保存控件按钮,我们自己创建了下一个和上一个按钮,并将它们附加到 controlContainer。

然后我们给两个按钮附加事件监听器,分别调用 .next() 和 .previous() 方法。别担心,我们很快就会创建这些方法。

接下来,我们将添加两个方法:.goToSlide() 和 .hideOtherSlides()。

this.goToSlide = function(index) {
 this.hideOtherSlides();
 if (index > slides.length - 1) {
  index = 0;
 }
 if (index < 0) {
  index = slides.length - 1;
 }
 slides[index].style = "display:block";
 currentSlideIndex = index;
};

this.hideOtherSlides = function() {
 document
  .querySelectorAll(options.slidesClass)
  .forEach((slide, index) => {
   slides[index].style = "display: none";
  });
};

.goToSlide() 方法采用参数 index,这是我们要显示的幻灯片的索引,此方法首先隐藏当前正在显示的任何幻灯片,然后仅显示我们要显示的幻灯片。

接下来,我们将添加 .next() 和 .previous() 辅助方法,分别帮助我们向前一步,或者向后一步(还记得我们之前附加的事件监听器吗?

this.next = function() {
 this.goToSlide(currentSlideIndex + 1);
};
this.previous = function() {
 this.goToSlide(currentSlideIndex - 1);
};

这两个方法基本上调用 .goToSlide() 方法,并将 currentSlideIndex 移动 1。

现在,我们还将创建一个 .init() 方法,该方法将在实例化构造函数时帮助我们进行设置。

this.init = function() {
 document.querySelectorAll(options.container).className +=
  " too-slide-slider-container";
 document
  .querySelectorAll(options.slidesClass)
  .forEach((slide, index) => {
   slides[index] = index;
   slides[index].style = "display:none";
   slides[index].className =
    " too-slide-single-slide too-slide-fade";
  });

 this.goToSlide(0);
 this.prepareControls();
};

如您所见,.init() 方法获取所有幻灯片图像并将其存储在我们之前声明的 slides 数组中,并默认隐藏所有图像。

然后,它通过调用 .goToSlide(0) 方法显示幻灯片中的第一张图像,并且还通过调用 .prepareControls() 设置我们的控制按钮。

为了收尾我们的构造函数代码,我们将在构造函数中调用 .init() 方法,这样每当构造函数被初始化时,.init() 方法总是被调用。

最终代码如下所示:

function ToolSidePlugin(options) {
 let defaultOptions = {
  slidesClass: ".singleSlide",
  container: ".slideContainer",
  nextButton: ".nextSlide",
  previousButton: ".previousSlide",
 };

 options = { ...defaultOptions, ...options };

 let _this = this;
 let slides = [];
 let currentSlideIdex = 0;

 this.init = function() {
  document.querySelectorAll(
   options.container
  ).className += " too-slide-slider-container";
  document
   .querySelectorAll(options.slidesClass)
   .forEach((slide, index) => {
    slides[index] = index;
    slides[index].style = "display:none";
    slides[index].className =
     " too-slide-single-slide too-slide-fade";
   });

  this.goToSlide(0);
  this.prepareControls();
 };

 this.prepareControls = function() {
  const nextButton = document.createElement("button");
  const previousButton = document.createElement("button");

  nextButton.setAttribute("class", "next");
  nextButton.InnerHTML = "Next";

  previousButton.setAttribute("class", "prev");
  nextButton.InnerHTML = "Prev";

  let controleContainer = document.createElement("div");

  controleContainer.setAttribute(
   "class",
   "too-slide-control-container"
  );

  controleContainer.appendChild(previousButton);
  controleContainer.appendChild(nextButton);

  document
   .querySelector(options.container)
   .appendChild(controleContainer);

  nextButton.addEventListener("click", function() {
   _this.next();
  });
  previousButton.addEventListener("click", function() {
   _this.previous();
  });
 };

 this.goToSlide = function(index) {
  this.hideOtherSlides();
  if (index > slides.length - 1) {
   index = 0;
  }
  if (index < 0) {
   index = slides.length - 1;
  }
  slides[index].style = "display:block";
  currentSlideIndex = index;
 };

 this.hideOtherSlides = function() {
  document
   .querySelectorAll(options.slidesClass)
   .forEach((slide, index) => {
    slides[index].style = "display: none";
   });
 };

 this.next = function() {
  this.goToSlide(currentSlideIndex + 1);
 };
 this.previous = function() {
  this.goToSlide(currentSlideIndex - 1);
 };

 this.init();
}

添加 CSS

在存放我们的插件项目的文件夹中,我们将添加一个 CSS 文件,其中包含我们的滑块的基本样式。我将把这个文件称为 tooSlide.css。

* {
 box-sizing: border-box;
}

body {
 font-family: Verdana, sans-serif;
 margin: 0;
 padding: 30px;
}

.too-slide-single-slide {
 display: none;
 max-height: 100%;
 width: 100%;
}

.too-slide-single-slide img {
 height: 100%;
 width: 100%;
}
img {
 vertical-align: middle;
}

/* Slideshow container */
.too-slide-slider-container {
 width: 100%;
 max-width: 100%;
 position: relative;
 margin: auto;
 height: 400px;
}

.prev,
.next {
 cursor: pointer;
 position: absolute;
 top: 50%;
 width: auto;
 padding: 10px;
 margin-right: 15px;
 margin-left: 15px;
 margin-top: -22px;
 color: white;
 font-weight: bold;
 font-size: 18px;
 transition: 0.6s ease;
 border-radius: 0 3px 3px 0;
 user-select: none;
 border-style: unset;
 background-color: blue;
}

.next {
 right: 0;
 border-radius: 3px 0 0 3px;
}

.prev:hover,
.next:hover {
 background-color: rgba(0, 0, 0, 0.8);
}

.too-slide-fade {
 -webkit-animation-name: too-slide-fade;
 -webkit-animation-duration: 1.5s;
 animation-name: too-slide-fade;
 animation-duration: 1.5s;
}

@-webkit-keyframes too-slide-fade {
 from {
  opacity: 0.4;
 }
 to {
  opacity: 1;
 }
}

@keyframes too-slide-fade {
 from {
  opacity: 0.4;
 }
 to {
  opacity: 1;
 }
}

/* On smaller screens, decrease text size */
@media only screen and (max-width: 300px) {
 .prev,
 .next,
 .text {
  font-size: 11px;
 }
}

测试我们的插件

为了测试我们的插件,我们将创建一个 HTML 文件,我将其命名为 index.html。我们还将添加 4 张图片用作幻灯片,所有图片都与我们的插件 JavaScript 代码位于同一目录中。

我的 HTML 文件如下所示:

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="UTF-8" />
  <meta
   name="viewport"
   content="width=device-width, initial-scale=1.0"
  />
  <title>测试幻灯片</title>
  <link rel="stylesheet" href="tooSlide.css" rel="external nofollow" />
 </head>
 <body>
  <div class="contaoner">
   <div class="slideContainer">
    <div class="singleSlide">
     <img
      src="slide1.png"
      alt="slide1"
      class="slideImage"
     />
    </div>
    <div class="singleSlide">
     <img
      src="slide2.png"
      alt="slide2"
      class="slideImage"
     />
    </div>
    <div class="singleSlide">
     <img
      src="slide3.png"
      alt="slide3"
      class="slideImage"
     />
    </div>
    <div class="singleSlide">
     <img
      src="slide4.png"
      alt="slide4"
      class="slideImage"
     />
    </div>
   </div>
  </div>

  <script src="tooSlide.js"></script>
  <script>
   var slider = new ToolSidePlugin({
    slideClass: ".singleSlide",
    container: ".slideContainer",
    nextButton: ".next",
    previousButton: ".prev",
   });
  </script>
 </body>
</html>

在 HTML 文件的头部分,我调用了 tooSlide.css 文件,而在文件的末尾,我调用了 tooSlide.js 文件。

完成此操作后,我们将能够实例化我们的插件构造函数:

var slider = new ToolSidePlugin({
 slideClass: ".singleSlide",
 container: ".slideContainer",
 nextButton: ".next",
 previousButton: ".prev",
});

最后的效果:

创建与框架无关的JavaScript插件

为您的 JavaScript 项目编写文档

文档是你教人们如何使用你的插件。因此,它需要你花一些心思。

对于我们新创建的插件,我将从在项目目录中创建 README.md 文件开始。

创建与框架无关的JavaScript插件

发布你的插件

在编写了您的插件之后,您很可能希望其他开发人员从您的新创建中受益,因此我将向您展示如何做到这一点。

你可以通过两种方式让你的插件对其他人可用:

在 Github 上托管它,当您这样做时,任何人都可以下载仓库,包括文件(.js 和.css),并立即使用您的插件。
发布在 npm 上,请查看官方的 npm 文档来指导您。
就是这样。

结束

在本文中,我们构建了一个插件来完成一件事:幻灯片图像。

它也是零依赖的,现在我们可以开始用我们的代码来帮助别人,就像我们也得到了帮助一样。

该插件教程的代码可在我的 github 上找到:https://github.com/dunizb/CodeTest/tree/master/JavaScript/TooSlidePlugin

以上就是创建与框架无关的JavaScript插件的详细内容,更多关于创建 JavaScript插件的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
动态加载js的几种方法
Oct 23 Javascript
JS+CSS 制作的超级简单的下拉菜单附图
Nov 22 Javascript
JavaScript中获取高度和宽度函数总结
Oct 08 Javascript
用队列模拟jquery的动画算法实例
Jan 20 Javascript
JavaScript中的setMilliseconds()方法使用详解
Jun 11 Javascript
JavaScript让Textarea支持tab按键的方法
Jun 26 Javascript
AngularJS实现单独作用域内的数据操作
Sep 05 Javascript
AngularJS获取json数据的方法详解
May 27 Javascript
AngularJs导出数据到Excel的示例代码
Aug 11 Javascript
使用vue实现grid-layout功能实例代码
Jan 05 Javascript
微信小程序基于ColorUI构建皮皮虾短视频去水印组件
Nov 04 Javascript
vue实现拖拽进度条
Mar 01 Vue.js
jQuery实现可以扩展的日历
Dec 01 #jQuery
如何使用gpu.js改善JavaScript的性能
Dec 01 #Javascript
jQuery实现容器间的元素拖拽功能
Dec 01 #jQuery
jQuery实现查看图片功能
Dec 01 #jQuery
vue实现表格合并功能
Dec 01 #Vue.js
vue element实现表格合并行数据
Nov 30 #Vue.js
Vue Elenent实现表格相同数据列合并
Nov 30 #Vue.js
You might like
ThinkPHP整合百度Ueditor图文教程
2014/10/21 PHP
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
JS获得URL超链接的参数值实例代码
2013/06/21 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
Jquery遍历节点的方法小集
2014/01/22 Javascript
在JavaScript中使用timer示例
2014/05/08 Javascript
滚动条响应鼠标滑轮事件实现上下滚动的js代码
2014/06/30 Javascript
jQuery中ajax的load()方法用法实例
2014/12/26 Javascript
轻松实现js图片预览功能
2016/01/18 Javascript
Three.js学习之正交投影照相机
2016/08/01 Javascript
jQuery实现动态文字搜索功能
2017/01/05 Javascript
xmlplus组件设计系列之列表(4)
2017/04/26 Javascript
Jquery把获取到的input值转换成json
2017/05/15 jQuery
JS去掉字符串中所有的逗号
2017/10/18 Javascript
Vue 让元素抖动/摆动起来的实现代码
2018/05/31 Javascript
JavaScript基础教程之如何实现一个简单的promise
2018/09/11 Javascript
vue 解决异步数据更新问题
2019/10/29 Javascript
在Python编程过程中用单元测试法调试代码的介绍
2015/04/02 Python
Python命令行参数解析模块getopt使用实例
2015/04/13 Python
Python2中的raw_input() 与 input()
2015/06/12 Python
使用python爬取B站千万级数据
2018/06/08 Python
Python3实现的旋转矩阵图像算法示例
2019/04/03 Python
Python生成个性签名图片获取GUI过程解析
2019/12/16 Python
用什么库写 Python 命令行程序(示例代码详解)
2020/02/20 Python
如何理解python面向对象编程
2020/06/01 Python
RetroStage德国:复古服装
2019/02/03 全球购物
Smilodox官方运动服装店:从运动服到健身配件
2020/08/27 全球购物
文件中有一组整数,要求排序后输出到另一个文件中
2012/01/04 面试题
销售工作人员的自我评价分享
2013/11/10 职场文书
应届毕业生求职信范例分享
2013/12/17 职场文书
工作总结与自我评价
2014/09/18 职场文书
大学生上课迟到检讨书
2014/10/15 职场文书
公司劳动纪律管理制度
2015/08/04 职场文书
《七律·长征》教学反思
2016/02/16 职场文书
JS继承最简单的理解方式
2021/03/31 Javascript
Jsonp劫持学习
2021/04/01 PHP