创建与框架无关的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使用手册之 事件处理
Mar 24 Javascript
JavaScript中定义类的方式详解
Jan 07 Javascript
JS Attribute属性操作详解
May 19 Javascript
Javascript必知必会(四)js类型转换
Jun 08 Javascript
JS使用cookie设置样式的方法
Jun 30 Javascript
Angular.Js中过滤器filter与自定义过滤器filter实例详解
May 08 Javascript
JS实现点击链接切换显示隐藏内容的方法
Oct 19 Javascript
解决LayUI表单获取不到data的问题
Aug 20 Javascript
Vue项目pdf(base64)转图片遇到的问题及解决方法
Oct 19 Javascript
Three.JS实现三维场景
Dec 30 Javascript
jQuery选择器之基本过滤选择器用法实例分析
Feb 19 jQuery
基于 jQuery 实现键盘事件监听控件
Apr 04 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 $_SERVER相关参数判断是否支持Rewrite模块
2013/09/26 PHP
PHP定时任务延缓执行的实现
2014/10/08 PHP
将PHP程序中返回的JSON格式数据用gzip压缩输出的方法
2016/03/03 PHP
删除重复数据的算法
2006/11/23 Javascript
pjblog修改技巧汇总
2007/03/12 Javascript
js用图作提交按钮或超连接
2008/03/26 Javascript
js中cookie的使用详细分析
2008/05/28 Javascript
javascript数组的扩展实现代码集合
2008/06/01 Javascript
JQueryEasyUI datagrid框架的基本使用
2013/04/08 Javascript
ajax请求乱码的解决方法(中文乱码)
2014/04/10 Javascript
浅谈javascript回调函数
2014/12/07 Javascript
Vue.js开发环境搭建
2016/11/10 Javascript
简单实现nodejs上传功能
2017/01/14 NodeJs
详解webpack分包及异步加载套路
2017/06/29 Javascript
详解自定义ajax支持跨域组件封装
2018/02/08 Javascript
vue项目中使用百度地图的方法
2018/06/08 Javascript
实现一个 Vue 吸顶锚点组件方法
2019/07/10 Javascript
javascript 原型与原型链的理解及应用实例分析
2020/02/10 Javascript
[53:29]完美世界DOTA2联赛循环赛 DM vs Matador BO2第二场 11.04
2020/11/05 DOTA
Python脚本处理空格的方法
2016/08/08 Python
Python网络爬虫项目:内容提取器的定义
2016/10/25 Python
django.db.utils.ProgrammingError: (1146, u“Table‘’ doesn’t exist”)问题的解决
2018/07/13 Python
Django 静态文件配置过程详解
2019/07/23 Python
python3.6生成器yield用法实例分析
2019/08/23 Python
python、Matlab求定积分的实现
2019/11/20 Python
django前端页面下拉选择框默认值设置方式
2020/08/09 Python
Django中template for如何使用方法
2021/01/31 Python
Fanatics法国官网:美国体育电商
2019/08/27 全球购物
园林资料员岗位职责
2013/12/30 职场文书
网络营销策划方案
2014/06/04 职场文书
五一活动标语
2014/06/30 职场文书
超市周年庆活动方案
2014/08/16 职场文书
2016年幼儿园教师师德承诺书
2016/03/25 职场文书
python实现调用摄像头并拍照发邮箱
2021/04/27 Python
mysql insert 存在即不插入语法说明
2022/03/25 MySQL
GO中sync包自由控制并发示例详解
2022/08/05 Golang