Частные нестатические переменные в полимере?
Как можно иметь частные нестатические переменные в полимере?
В:
<polymer-element name="component-one">
<script>
Polymer('component-one', {
internalState = 1,
ready() {
this.anotherInternalState = 1;
}
/* more variables and functions */
});
</script>
</polymer-element>
как internalState, так и anotherInernalState подвергаются внешней (например, доступной через что-то вроде:
document.querySelector('component-one').internalState
(что может быть нежелательным при изменении internalState извне, делает компонент неустойчивым.)
где как в:
<polymer-element name="component-two">
<script>
(function() {
var internalState = 1;
Polymer('component-two', {
/* some variables and functions */
});
})();
</script>
</polymer-element>
internalState скрыт снаружи, но он статичен и разделен во всех экземплярах компонента.
Есть ли способ иметь частную нестатическую переменную внутри полимерного объекта?
Ответы
Ответ 1
Это скорее вопрос с чисто JavaScript, чем вопрос Полимера. Начиная с ES5 в JavaScript нет "частных экземпляров", хотя ES6 предлагает несколько новых инструментов.
Мое предложение состоит в том, чтобы использовать старое соглашение о добавлении переменных частного экземпляра с подчеркиванием (_internalState
).
В противном случае вам нужно запутаться с картами и закрытием.
Ответ 2
Вам нужно будет поддерживать частный статический контекст для каждого экземпляра вашего элемента. несколько советов в документе о том, как это сделать. Прежде всего, я начну с отслеживания живых экземпляров:
var instances = [];
Polymer('foo-bar', {
// ...
attached: function() {
instances.push(this);
},
detached: function(){
instances = instances.filter(function(instance){
return instance !== this;
}.bind(this));
},
// ...
});
Затем вы можете добавить частный метод, чтобы получить доступ к частному контексту вашего экземпляра:
var instances = [], contexts = [];
Polymer(/* ... */);
function getPrivateContext(instance){
return contexts[instances.indexOf(instance)];
}
И соедините все это элегантно:
var instances = [];
Polymer('foo-bar', {
// ...
attached: function() {
instances.push({
element: this,
context: {}
);
},
detached: function(){
instances = instances.filter(function(instance){
return instance.element !== this;
}.bind(this));
},
// ...
whatever: function(){
var privateThis = private(this);
}
});
function private(element){
return instances.filter(function(instance){
return instance.element === element;
})[0].context;
}
Не тестировал, но он должен работать.
Ответ 3
В ES6, где у вас есть символы, вы можете сделать
<polymer-element name="my-element">
<script type="text/javascript">
(function () {
// visible to all my-element instances
var privateKey = Symbol('Symbol description');
Polymer({
ready: function () {
// initialize object containing private properties
this[privateKey] = {}; // only you can touch this
// only those with access to 'privateKey' can can access
// your new ContactCard
this[privateKey].contactCard = new ContactCard(this);
},
// public method
publicMethod: function() {
// accessing private data
doSomethingWith(this[privateKey].contactCard);
}
};);
})();
</script>
</polymer-element>
с использованием символов. Это должно препятствовать доступу пользователей вашего элемента к определенным данным по вашему выбору. Поскольку все экземпляры могут просматривать ключ, данные все еще видны для всех экземпляров вашего элемента. Дополнительная информация: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
Ответ 4
Здесь подход, который я сделал:
<script type="text/javascript">
(function () {
var privateStatic = Math.random();
function ContactCard(component) {
var mouseoverTimer;
var privateInstance = Math.random();
component.addEventListener('mouseenter', function () {
mouseoverTimer = setTimeout(function () {
alert(privateStatic);
alert(privateInstance);
}, 250);
});
component.addEventListener('mouseleave', function () {
clearTimeout(mouseoverTimer);
});
return {
};
};
Polymer({
ready: function () {
new ContactCard(this);
}
});
})();
</script>
Я не показываю его в примере, но вы все равно можете использовать способ component.$.someElementId
доступа к элементам по идентификатору в корне тени.
Кроме того: я чувствую, что этот стиль программирования позволяет вам разделить ваши компоненты немного дальше от Polymer, если вы в этом заняты. Фактически вы можете использовать component.shadowRoot.getElementById('someElementId')
и component.shadowRoot.querySelector('#someElementId')
, а также другие тактики, если вы выберете, и они будут работать в других браузерах, кроме Chrome (включая IE9 и выше).
Ответ 5
Просто переместите назначение значения в одну из функций прототипа, например:
<polymer-element name="component-two">
<script>
(function() {
var internalState;
Polymer('component-two', {
ready: function() {
internalState = 1; // Replace static value with something instance specific
}
});
})();
</script>
</polymer-element>