基本的ES6 Javascript插件 - 在函数

时间:2017-05-19 15:59:24

标签: javascript ecmascript-6

我尝试构建一个基本的JS插件,可以在单击事件后调用以禁用按钮(以防止用户触发多个API调用)并提供有关正在加载/发生的事情的反馈。以下是它的外观:

enter image description here

这在个人基础上很有效,但我想将其重新编写为插件,以便我可以在整个网站上重复使用它。

这是来自文件loader.plugin.js的JS的缩减版本。

let originalBtnText;


export function showBtnLoader(btn, loadingText) {
  const clickedBtn = btn;
  const spinner = document.createElement('div');

  spinner.classList.add('spin-loader');

  originalBtnText = clickedBtn.textContent;
  clickedBtn.textContent = loadingText;
  clickedBtn.appendChild(spinner);
  clickedBtn.setAttribute('disabled', true);
  clickedBtn.classList.add('loading');

  return this;
}


export function hideBtnLoader(btn) {
  const clickedBtn = btn.target;
  clickedBtn.textContent = originalBtnText;
  clickedBtn.removeAttribute('disabled');
  clickedBtn.classList.remove('loading');

  return this;
}


export function btnLoader() {
  showBtnLoader();
  hideBtnLoader();
}

以下是我想如何使用它的一个例子。

import btnLoader from 'loaderPlugin';

const signupBtn = document.getElementById('signup-btn');

signupBtn.addEventListener('click', function(e) {
  e.preventDefault();
  btnLoader.showBtnLoader(signupBtn, 'Validating');
  // Call API here
});

// Following API response
hideBtnLoader(signupBtn);

我遇到的问题是我想要存储originalBtnText函数中的showBtnLoader,然后在hideBtnLoader函数中使用该变量。我当然可以用不同的方式实现这一点(例如将值作为数据属性添加并稍后抓取它)但我想知道是否有一种简单的方法。

我遇到的另一个问题是,我不知道调用每个函数的正确方法以及我是否正确导入它。我尝试了以下内容。

btnLoader.showBtnLoader(signupBtn, 'Validating');
btnLoader(showBtnLoader(signupBtn, 'Validating'));
showBtnLoader(signupBtn, 'Validating');

但是我收到以下错误:

Uncaught ReferenceError: showBtnLoader is not defined
    at HTMLButtonElement.<anonymous>

我已经阅读了一些好的文章和SO答案,例如http://2ality.com/2014/09/es6-modules-final.htmlES6 export default with multiple functions referring to each other,但我对“正确的”问题感到有些困惑。这样做是为了让它可以重复使用。

任何指针都会非常感激。

2 个答案:

答案 0 :(得分:2)

我会导出一个创建一个具有show和hide功能的对象的函数,如下所示:

export default function(btn, loadingText) {

  function show() {
    const clickedBtn = btn;
    const spinner = document.createElement('div');

    spinner.classList.add('spin-loader');

    originalBtnText = clickedBtn.textContent;
    clickedBtn.textContent = loadingText;
    clickedBtn.appendChild(spinner);
    clickedBtn.setAttribute('disabled', true);
    clickedBtn.classList.add('loading');
  }

  function hide() {
    const clickedBtn = btn.target;
    clickedBtn.textContent = originalBtnText;
    clickedBtn.removeAttribute('disabled');
    clickedBtn.classList.remove('loading');
  }

  return {
    show,
    hide,
  };
}

然后,使用它:

import btnLoader from 'btnloader';

const signupBtn = document.getElementById('signup-btn');
const signupLoader = btnLoader( signupBtn, 'Validating' );

signupBtn.addEventListener('click', function(e) {
  e.preventDefault();
  signupLoader.show();
  // Call API here
});

// Following API response
signupLoader.hide();

如果您需要将其与显示的文件中的其他文件隐藏,则可以导出实例:

export const signupLoader = btnLoader( signupBtn, 'Validating' );

然后导入它。

import { signupLoader } from 'signupform';

function handleApi() {
    signupLoader.hide();
}

答案 1 :(得分:1)

你可能会覆盖Element.prototype,使其可以直接从该元素访问。但是,我不会在该元素上设置值,我宁愿返回一个包含所有必要内容的对象:

export function implementBtnLoader(){
 Element.prototype.showBtnLoader=function( loadingText) {
     const clickedBtn = this;
     const spinner = document.createElement('div');

     spinner.classList.add('spin-loader');

     var originalBtnText = clickedBtn.textContent;
     clickedBtn.textContent = loadingText;
     clickedBtn.appendChild(spinner);
     clickedBtn.setAttribute('disabled', true);
     clickedBtn.classList.add('loading');

    return {
        text:originalBtnText,
        el:this,
        hideBtnLoader: function() {
          const clickedBtn = this.target;
          clickedBtn.textContent = this.text;
          clickedBtn.removeAttribute('disabled');
          clickedBtn.classList.remove('loading');
          return this;
       }
    };
  };
}


export function btnLoader() {
   implementBtnLoader();
}

导入时,调用implementsBtnLoader,可以执行以下操作:

var loader=document.getElementById("test").showBtnLoader();
console.log(loader.text);
loader.hideBtnLoader();