如何使非子元素之间的数据绑定在 Polymer 中起作用

How to make data-binding between non-child elements work in Polymer

我正在用 Polymer 重制 my website。我目前正在尝试使双向数据绑定工作,以便能够在选择 iron-pages 时选择相应的菜单元素,反之亦然。我目前使用的代码是:

<body class="fullbleed roboto">
    <paper-drawer-panel force-narrow>
        <paper-header-panel mode="standard" main>
            <paper-toolbar class="amber">
                <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
                <div class="title">Charles Milette's Personnal Website</div>
            </paper-toolbar>
            <iron-pages selected="{{selected}}">
                <div id="content">Home Content</div>
                <div id="content">Page 1 Content</div>
            </iron-pages>
        </paper-header-panel>
        <div drawer>
            <img src="img/drawer.png" />
            <paper-menu selected="{{selected}}">
                <paper-item><iron-icon icon="home"></iron-icon>Home</paper-item>
                <paper-item>Page 1</paper-item>
            </paper-menu>
        </div>
    </paper-drawer-panel>
</body>

但是,显然,它不起作用,因为数据绑定仅在子元素和父元素之间起作用,如 here 所述。
我认为 attrForSelected 可以满足我的需要,但我不确定如何使用它。
使用一些事件侦听器来侦听属性更改 and/or 点击也可以做到这一点,但我正在寻找更好的方法来做到这一点(有点像数据绑定)。

还有比这更好的方法吗?这是什么?
如果我搜索的是 attrForSelected,我该如何使用它?

如果你也给我一个代码片段,我将不胜感激。

绑定需要在 <template> 上下文中。在您的情况下,将 html 放在 <template is="dom-bind"> 中将启用绑定。

请注意,绑定是在模板和元素之间进行的(元素不会直接相互绑定)。这意味着您没有违反关于 parents 和 children.

的任何规则

<base href="http://polygit.org/components/">

<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="paper-elements/paper-elements.html" rel="import">
<link href="iron-pages/iron-pages.html" rel="import">

<body class="fullbleed roboto">
  <template is="dom-bind" selected="0">
    <paper-drawer-panel force-narrow>
        <paper-header-panel mode="standard" main>
            <paper-toolbar class="amber">
                <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
                <div class="title">Charles Milette's Personnal Website</div>
            </paper-toolbar>
            <iron-pages selected="{{selected}}">
                <div id="content">Home Content</div>
                <div id="content">Page 1 Content</div>
            </iron-pages>
        </paper-header-panel>
        <div drawer>
            <paper-menu selected="{{selected}}">
                <paper-item><iron-icon icon="home"></iron-icon>Home</paper-item>
                <paper-item>Page 1</paper-item>
            </paper-menu>
        </div>
    </paper-drawer-panel>
  </template>
</body>

这个答案与 Scott 的答案基本相同,只是对 dom-bind 进行了更多解释,并举例说明了如何从主要内容中更改页面。

JS Bin

<body>
  <!-- dom-bind template is the key here. you can use it do declare properties
       at the scope of the template. any polymer elements that are children to
       to the template have access to the template's properties -->
  <template is="dom-bind" id="app">
    <paper-drawer-panel force-narrow>
      <paper-header-panel mode="standard" main>
        <paper-toolbar class="amber">
          <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
          <div class="title">Website</div>
        </paper-toolbar>
        <!-- attr-for-selected="page" means "when the value of 'selected'
             changes, select the <section> whose 'page' attribute equals
             the value of 'selected' 

             when attr-for-selected is omitted, then 'selected' just
             equals the index of the page

             the 'selected' property is scoped to the dom-bind, so you can think
             of it as document.querySelector('#app').selected 

             you only need one-way data-binding here ('[[selected]]') 
             because <iron-pages> doesn't modify the 'selected' property -->
        <iron-pages attr-for-selected="page" selected="[[selected]]">
          <section page="home">
            <p>value of selected: {{selected}}</p>
            <!-- check out how this ordinary button has access to polymer's 
                 on-* declarative events, thanks to dom-bind! -->
            <button on-tap="about">go to about page</button>
          </section>
          <section page="about">
            <p>value of selected: {{selected}}</p>
            <button on-tap="home">go to home page</button>
          </section>
        </iron-pages>
      </paper-header-panel>
      <div drawer>
        <!-- attr-for-selected works mostly the same here as it did above, 
             with one difference. when you select a <paper-item>, then the 
             'selected' property is set to the value of the 'page' attribute

             you need two-way data binding here ('{{selected}}') because we are
             modifying the value of 'selected'
        -->
        <paper-menu attr-for-selected="page" selected="{{selected}}">
          <paper-item page="home">home</paper-item>
          <paper-item page="about">about</paper-item>
        </paper-menu>
      </div>
    </paper-drawer-panel>
  </template>
  <script>

    // you can access dom-bind properties imperatively, too  
    (function(document) {
      var app = document.querySelector('#app');
      // the app shows the 'about' page first even though it's the second menu 
      // item because we are setting app.selected imperatively when DOM is ready
      app.selected = 'about';
      // changing the selected page is as simply as changing the 
      // value of app.selected
      app.about = function() {
        app.selected = 'about';
      };
      app.home = function() {
        app.selected = 'home';
      };
    }) (document);
  </script>
</body>