聚合物中的私有非静态变量?

时间:2014-06-27 21:35:54

标签: javascript polymer web-component

如何在聚合物中使用私有非静态变量?

在:

<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在外部是隐藏的,但它是静态的,并在组件的所有实例中共享。

有没有办法在聚合物对象中有一个私有的非静态变量?

5 个答案:

答案 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>