我尝试构建一个基本的JS插件,可以在单击事件后调用以禁用按钮(以防止用户触发多个API调用)并提供有关正在加载/发生的事情的反馈。以下是它的外观:
这在个人基础上很有效,但我想将其重新编写为插件,以便我可以在整个网站上重复使用它。
这是来自文件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.html和ES6 export default with multiple functions referring to each other,但我对“正确的”问题感到有些困惑。这样做是为了让它可以重复使用。
任何指针都会非常感激。
答案 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();