2014-06-27 14 views
11

Wie ist es möglich, private nicht statische Variablen in Polymer zu haben?Private nicht statische Variablen in Polymer?

In:

<polymer-element name="component-one"> 
    <script> 

     Polymer('component-one', { 
     internalState = 1,  
     ready() { 
       this.anotherInternalState = 1; 
      } 
      /* more variables and functions */ 
     }); 

    </script> 

</polymer-element> 

beide internalState und anotherInernalState sind nach außen (zB zugänglich durch so etwas wie ausgesetzt:

document.querySelector('component-one').internalState 

(was unerwünscht sein könnte, wenn instabil von außen macht die Komponente internalState ändern.)

wo, wie in:

<polymer-element name="component-two"> 
    <script> 

    (function() { 

     var internalState = 1; 


     Polymer('component-two', { 
      /* some variables and functions */ 
     }); 
    })(); 

    </script> 

</polymer-element> 

internalState ist von außen verborgen, aber es ist statisch und wird für alle Instanzen der Komponente freigegeben.

Gibt es eine Möglichkeit, eine private nicht statische Variable in einem Polymerobjekt zu haben?

Antwort

4

Dies ist eher eine reine JavaScript-Frage als eine Polymer-Frage. Ab ES5 gibt es in JavaScript keine 'private instance members', obwohl ES6 einige neue Tools enthält.

Mein Vorschlag ist es, die alte Konvention von vorgehenden privaten Instanzvariablen mit Unterstrich (_internalState) zu verwenden.

Ansonsten müssen Sie mit Karten und Schließungen knifflig werden.

+0

Danke Scott, ich habe gerade FB React angeschaut und gesehen, dass React eine Zustandseigenschaft hat, die für die Komponente privat ist. Ist sowas nicht nützlich genug, um Polymer hinzugefügt zu werden? (zu meiner bescheidenen Meinung ist es :) – sepans

+1

Link: http://facebook.github.io/react/documents/tutorial.html#reactive-state – sepans

+0

Hoffe, dass diese Funktion in 0.8 und 1.0 API vorgeschlagen wird – andrsnn

-1

Hier ist der Ansatz, den ich gemacht habe:

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

ich es nicht zeigen, in dem Beispiel, aber man kann immer noch die component.$.someElementId Art und Weise den Zugriff auf Elemente von id im Schatten Wurzel verwenden.

Beiseite: Ich fühle mich wie diese Art der Programmierung ermöglicht es Ihnen, Ihre Komponenten ein wenig weiter von Polymer zu entkoppeln, wenn Sie in diese Art von Sache sind. Sie können tatsächlich component.shadowRoot.getElementById('someElementId') und component.shadowRoot.querySelector('#someElementId') sowie andere Taktiken verwenden, wenn Sie wählen, und sie werden in anderen Browsern neben Chrome arbeiten

-1

einfach die Wertzuweisung bewegen sich in einem der Prototyp-Funktionen, wie (einschließlich IE9 und höher.):

<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> 
+0

Vergiss das, warn ' t denken! – nikvm

+0

Aber wie wäre es mit der Deklaration eines privaten statischen Arrays? Dann, in einer der Prototyp-Funktionen, einen Wert auf dieses Array zu drücken und den Index wie 'this.index = internalState.push (someValue) - 1;' zu speichern und mit 'internalState [this.index]' darauf zuzugreifen. Dies würde nur den Index außerhalb von '' Elementen verfügbar machen. Auch ein '' - Element könnte immer noch auf den "internalState" einer anderen Instanz zugreifen. – nikvm

0

In ES6, wo man Symbole haben, können Sie

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

mit Symbolen tun. Dies sollte verhindern, dass Benutzer Ihres Elements auf bestimmte Daten Ihrer Wahl zugreifen. Da alle Instanzen den Schlüssel anzeigen können, sind die Daten für alle Instanzen Ihres Elements weiterhin sichtbar. Weitere Informationen: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

1

Sie müssten für jede Instanz Ihres Elements einen privaten statischen Kontext pflegen. Es gibt some hints im Dokument, wie man das macht.Zunächst einmal würde ich mit dem Überblick über Live-Instanzen starten:

var instances = []; 
Polymer('foo-bar', { 
    // ... 
    attached: function() { 
     instances.push(this); 
    }, 
    detached: function(){ 
     instances = instances.filter(function(instance){ 
      return instance !== this; 
     }.bind(this)); 
    }, 
    // ... 
}); 

Dann könnten Sie eine private Methode hinzufügen Zugriff auf Ihre Instanz privaten Kontext zu erhalten:

var instances = [], contexts = []; 
Polymer(/* ... */); 
function getPrivateContext(instance){ 
    return contexts[instances.indexOf(instance)]; 
} 

Und es verdrahten alle zusammen mehr elegant:

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; 
} 

Habe es nicht getestet aber es sollte funktionieren.