问题
Plugin code:
( function() {
this.Modal = function modal( selector, options ) {
// If there's a passed element is already initialized return its instance
if ( !modal.instances ) {
modal.instances = {};
}
if ( modal.instances[ selector ] ) {
return modal.instances[ selector ];
}
modal.instances[ selector ] = this;
// Plugin options
var defaults = {
open: false
};
this.options = extendDefaults( defaults, options );
selector.style.setProperty( 'background-color', 'red' );
}
function extendDefaults( source, properties ) {
var property;
for ( property in properties ) {
if ( properties.hasOwnProperty( property ) ) {
source[ property ] = properties[ property ];
}
}
return source;
}
}() );
To run the plugin:
$( window ).on( 'load', function() {
$( '.button' ).each( function() {
var myPlugin = new Modal( this );
} );
} );
HTML Code:
<button class="button">First Button</button>
<button class="button">Second Button</button>
<button class="button">Third Button</button>
The wrong on the code that the first button only will read the plugin and gets the red background and the second and third buttons will return the instance of the first button, And I don't why this happens the buttons has the same class, yes but there are different elements.
I need every button called from the plugin gets the red background color and at the same time avoid initialized multiple times (If the passed element is already initialized return its instance).
回答1:
Ok. The problem is in objects approach here because the keys of the object can be only strings. And when we are trying to so smth like this modal.instances[ selector ] = this;
we actually will have this modal.instances['[object HTMLButtonElement]'] = this;
for any of the html button element. So the solution is to use Map approach, because the keys of the map can be an objects.
(function() {
const modalInstances = new Map();
this.Modal = function(element, options) {
if (modalInstances.has(element)) {
console.log('return instance for: ' + element.innerHTML);
return modalInstances.get(element);
}
modalInstances.set(element, this);
// Plugin options
var defaults = {
open: false
};
this.options = extendDefaults(defaults, options);
element.style.setProperty('background-color', 'red');
}
function extendDefaults(source, properties) {
var property;
for (property in properties) {
if (properties.hasOwnProperty(property)) {
source[property] = properties[property];
}
}
return source;
}
}());
$(window).on('load', function() {
$('.button').each(function() {
var myPlugin = new Modal(this);
});
// we will use already careated instances here, see the console.log
$('.button').each(function() {
var myPlugin = new Modal(this);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="button">First Button</button>
<button class="button">Second Button</button>
<button class="button">Third Button</button>
来源:https://stackoverflow.com/questions/62229248/check-if-passed-element-is-already-initialized-return-its-instance-javascript-pl