我正在将jQuery插件转换为Vanilla Javascript。在我的示例中,我采用了Bootstrap风格的插件结构。实例化Accordion对象后,将其保存到dom元素中,以便以后可以对该对象使用各种方法。这是反模式吗?如果不正确,我将非常感谢您提供有关如何处理此问题的建议。
const Accordion = function(element, options){
this.$element = element;
this.target = this.$element.getAttribute('href') || this.$element.dataset.target;
this.$target = document.getElementById(this.target);
this.$header = document.querySelector(`.accordion-header[data-target='${this.target}']`) || document.querySelector(`.accordion-header[href='${this.target}']`);
this.options = {...Accordion.defaults, ...options};
}
Accordion.defaults = {
closeOthers: false
}
Accordion.prototype.open = function(){
this.$header.classList.add('active');
this.$target.classList.add('active');
};
Accordion.prototype.close = function(){
this.$header.classList.remove('active');
this.$target.classList.remove('active');
};
Accordion.prototype.toggle = function(){
if(this.$target.classList.contains('active')){
this.close();
} else {
this.open();
}
};
function Plugin(options){
let accordion = this.Accordion;
if(!accordion){
accordion = new Accordion(this, options);
// Is it okay to store an object on the DOM element?
this.Accordion = accordion;
}
}
const $accordions = [...document.querySelectorAll('[data-toggle="accordion"]')];
const options = {
closeOthers: true
};
/* Call the plugin */
$accordions.forEach($acc => {
Plugin.call($acc, options);
});
$accordions.forEach($acc => {
$acc.addEventListener('click', e => {
e.target.Accordion.toggle();
e.preventDefault();
});
});
const $toggle1 = document.getElementById('toggle1');
const $toggle2 = document.getElementById('toggle2');
const $acc1 = document.getElementById('acc1');
const $acc2 = document.getElementById('acc2');
$toggle1.addEventListener('click', e =>{
$acc1.Accordion.toggle();
});
$toggle2.addEventListener('click', e =>{
$acc2.Accordion.toggle();
});
body {
max-width: 500px;
margin: 0 auto;
padding: 10px;
}
.accordion {
border: 1px solid #ccc;
border-bottom: 0;
margin-bottom: 10px;
}
.accordion-header {
display: block;
padding: 10px;
text-decoration: none;
color: #000;
border-bottom: 1px solid #ccc;
}
.accordion-header.active {
background: #eee;
}
.accordion-body {
padding: 10px;
display: none;
border-bottom: 1px solid #ccc;
}
.accordion-body.active {
display: block;
}
<div class="accordion">
<a id="acc1" href="#1" class="accordion-header" data-toggle="accordion">Header1</a>
<div id="#1" class="accordion-body">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Consequatur aliquid et ipsam cupiditate. Omnis iste quas nostrum aliquid facilis ut natus excepturi deleniti nobis in similique, ex, voluptatibus commodi dolores.
</div>
</div>
<div class="accordion">
<a id="acc2" href="#2" class="accordion-header" data-toggle="accordion">Header2</a>
<div id="#2" class="accordion-body">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Consequatur aliquid et ipsam cupiditate. Omnis iste quas nostrum aliquid facilis ut natus excepturi deleniti nobis in similique, ex, voluptatibus commodi dolores.
</div>
</div>
<button id="toggle1">
Toggle 1
</button>
<button id="toggle2">
Toggle 2
</button>
答案 0 :(得分:1)
我不会为此担心。唯一的潜在问题是名称冲突(某些其他代码也尝试分配给element.Accordion
并覆盖它)。您也可以使用Map
。
var accordions = new Map()
function Accordion ( element ) {
accordions.set( element, this )
}
Accordion.get = element => accordions.get( element )
...
var accordion = Accordion.get( element )