如何在聚合物中使用私有非静态变量?
在:
<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在外部是隐藏的,但它是静态的,并在组件的所有实例中共享。
有没有办法在聚合物对象中有一个私有的非静态变量?
答案 0 :(得分:4)
这是一个纯粹的JavaScript问题,而不是Polymer问题。从ES5开始,JavaScript中没有“私有实例成员”,尽管ES6带来了一些新工具。
我的建议是使用旧的约定来预先设置下划线(_internalState
)的私有实例变量。
否则,你必须对地图和闭包感到棘手。
答案 1 :(得分:1)
您必须为元素的每个实例维护一个私有静态上下文。文档中有some hints关于如何做到这一点。首先,我开始跟踪实时实例:
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;
}
没有测试过,但它应该有用。
答案 2 :(得分:0)
在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
答案 3 :(得分:-1)
以下是我采取的方法:
<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
方式在阴影根中按ID访问元素。
除此之外:我觉得这种编程风格让你可以将你的组件与Polymer分开一点,如果你进入那种事情的话。如果您选择,您实际上可以使用component.shadowRoot.getElementById('someElementId')
和component.shadowRoot.querySelector('#someElementId')
以及其他策略,除了Chrome之外,它们还可以在其他浏览器中使用(包括IE9及更高版本。)
答案 4 :(得分:-1)
只需在其中一个原型函数中移动值赋值,例如:
<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>