创建与框架无关的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 相关文章推荐
基于jquery的不规则矩形的排列实现代码
Apr 16 Javascript
Bootstrap框架安装使用详解
Jan 21 Javascript
利用JQuery操作iframe父页面、子页面的元素和方法汇总
Sep 10 jQuery
解决js ajax同步请求造成浏览器假死的问题
Jan 18 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
May 30 Javascript
JavaScript常见继承模式实例小结
Jan 11 Javascript
详解React项目如何修改打包地址(编译输出文件地址)
Mar 21 Javascript
Vue使用NProgress进度条的方法
Sep 21 Javascript
Vue 设置axios请求格式为form-data的操作步骤
Oct 29 Javascript
在vue中使用console.log无效的解决
Aug 09 Javascript
Openlayers实现测量功能
Sep 25 Javascript
jquery简易手风琴插件的封装
Oct 13 jQuery
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
十天学会php(3)
2006/10/09 PHP
php 远程关机操作的代码
2008/12/05 PHP
PHP中使用gettext来支持多语言的方法
2011/05/02 PHP
一个基于phpQuery的php通用采集类分享
2014/04/09 PHP
php+MySQL判断update语句是否执行成功的方法
2014/08/28 PHP
WordPress中邮件的一些修改和自定义技巧
2015/12/15 PHP
JavaScript学习笔记之JS函数
2015/01/22 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
2015/03/02 Javascript
Javascript中For In语句用法实例
2015/05/14 Javascript
完美的js图片轮换效果
2017/02/05 Javascript
浅谈vue,angular,react数据双向绑定原理分析
2017/11/28 Javascript
Vue Socket.io源码解读
2018/02/07 Javascript
使用ngrok+express解决本地环境中微信接口调试问题
2018/02/26 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
2018/11/05 Javascript
vue-for循环嵌套操作示例
2019/01/28 Javascript
微信小程序实现展示评分结果功能
2019/02/15 Javascript
如何使用CSS3+JQuery实现悬浮墙式菜单
2019/06/18 jQuery
[03:24]DOTA2超级联赛专访hao 大翻盘就是逆袭
2013/05/24 DOTA
[47:03]Ti4第二日主赛事败者组 LGD vs iG 2
2014/07/21 DOTA
Python的Flask框架与数据库连接的教程
2015/04/20 Python
python字典基本操作实例分析
2015/07/11 Python
Python中.py文件打包成exe可执行文件详解
2017/03/22 Python
Python数据拟合与广义线性回归算法学习
2017/12/22 Python
Python基于递归算法实现的汉诺塔与Fibonacci数列示例
2018/04/18 Python
在python 中split()使用多符号分割的例子
2019/07/15 Python
python实现车牌识别的示例代码
2019/08/05 Python
Python中注释(多行注释和单行注释)的用法实例
2019/08/28 Python
Python多线程threading创建及使用方法解析
2020/06/17 Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
2021/02/25 Python
全球销量第一生发产品:Viviscal
2017/12/21 全球购物
Bealls Florida百货商店:生活服饰、家居装饰和鞋子
2018/02/23 全球购物
Crocs波兰官方商店:女鞋、男鞋、童鞋、洞洞鞋
2019/10/08 全球购物
法学专业大学生实习自我鉴定
2014/10/05 职场文书
投标承诺函范文
2015/01/21 职场文书
员工年度工作总结2015
2015/05/18 职场文书
创业计划书介绍
2019/04/24 职场文书