Sharing changes to data between Polymer elements

情到浓时终转凉″ 提交于 2019-12-13 23:25:03

问题


I have a page where I want to include three separate views (one showing all the data and ones with different summaries) on the same set of data.

I'm looking for a way to represent each view as a Polymer element and have each one update whenever the data changes. These changes will be to the values of properties of objects which are stored in an array. It is the array that is shared between the components.

I've found an approach that works by firing an event when there is a change to the data, listening for it outside the components, and then calling notifyPath — but it is somewhat unwieldy and likely to be more so as I grow my code its current state (a simple demo with two Polymer elements, one of which is readonly) to the end goal (three elements, all of which can read and write to the data).

Is there a simpler way to share changes between components than this?


index.html

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="utf-8">
        <title>polymer-test</title>
        <script>
            (function() {
                var data = [{
                    name: "Alice",
                    amount: 100
                }, {
                    name: "Bob",
                    amount: 200
                }];
                document.addEventListener('WebComponentsReady', function() {
                    document.querySelector('example-one').data = data;
                    document.querySelector('example-two').data = data;

                    document.querySelector('example-two').addEventListener('there-is-a-change', function(e) {
                        document.querySelector('example-one').notifyPath(e.detail.path);
                    })

                });
            })();
        </script>

        <script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
        <link rel="import" href="/src/polymer-test-app/example-one.html">
        <link rel="import" href="/src/polymer-test-app/example-two.html">
    </head>

    <body>
        <h1>One</h1>
        <example-one></example-one>
        <h1>Two</h1>
        <example-two></example-two>
    </body>

</html>

example-one.html

<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">

<dom-module id="example-one">
    <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <table>
    <tbody>
        <template is="dom-repeat" items="{{data}}">
            <tr>
                <td>{{item.name}}</td>
                <td>{{item.amount}}</td>
            </tr>
        </template>
    </tbody>
    </table>
    </template>

    <script>
        class ExampleOne extends Polymer.Element {
            static get is() {
                return 'example-one';
            }
            static get properties() {
                return {
                    data: {
                        type: Array,
                        notify: true,
                        value() {
                            return [];
                        }
                    }
                };
            }
        }

        window.customElements.define(ExampleOne.is, ExampleOne);
    </script>
</dom-module>

example-two.html

<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">

<dom-module id="example-two">
    <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <table>
    <tbody>
        <template is="dom-repeat" items="{{data}}">
            <tr>
                <td>{{item.name}}</td>
                <td><input value="{{item.amount::input}}"></td>
            </tr>
        </template>
    </tbody>
    </table>
    </template>

    <script>
        class ExampleTwo extends Polymer.Element {
            static get is() {
                return 'example-two';
            }
            static get properties() {
                return {
                    data: {
                        type: Array,
                        notify: true,
                        value() {
                            return [];
                        }
                    }
                };
            }
            static get observers() {
                return [
                    'arrayChanged(data.*)'
                ]
            }
            arrayChanged(data) {
                console.log("Changed!");
                this.dispatchEvent(new CustomEvent("there-is-a-change", {
                    detail: {
                        path: data.path
                    }
                }));
            }

        }

        window.customElements.define(ExampleTwo.is, ExampleTwo);
    </script>
</dom-module>

回答1:


Above codes may like this with Polymer way. without notifyPath.

DEMO

index html:

<html>

 <body> 

<dom-module id="my-test">
<template>
<style>
    :host {
      display: block;
      text-align: center;
    }
</style>
  <body>
    <h1>One</h1>
    <example-one data={{data}}></example-one>
    <h1>Two</h1>
    <example-two data={{data}}></example-two>
  </body>


</template> 
</dom-module>



<my-test></my-test>

</body>
</html>

example-one.html:

<dom-module id="example-one">
    <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <table>
    <tbody>
        <template is="dom-repeat" items="{{data}}">
            <tr>
                <td>{{item.name}}</td>
                <td>{{item.amount}}</td>
            </tr>
        </template>
    </tbody>
    </table>
    </template>
    <script>
 class ExampleOne extends Polymer.Element {
            static get is() { return 'example-one'; }
            static get properties() {
                return {
                    data: {
                        type: Array,
                        notify: true,
                        value() {
                            return [{ name: "Alice",
                                      amount: 100
                                      }, {
                                      name: "Bob",
                                      amount: 200          }];
                        }
                    }
                };
            }
        }

        window.customElements.define(ExampleOne.is, ExampleOne);
   </script>
</dom-module>

And example-two.html is:

<dom-module id="example-two">
    <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <table>
    <tbody>
        <template is="dom-repeat" items="{{data}}">
            <tr>
                <td>{{item.name}}</td>
                <td><input value="{{item.amount::input}}"></td>
            </tr>
        </template>
    </tbody>
    </table>
    </template>
<script>
class ExampleTwo extends Polymer.Element {
            static get is() {
                return 'example-two';
            }
            static get properties() {
                return {
                    data: {
                        type: Array,
                        notify: true,
                        value() {
                            return [];
                        }
                    }
                };
            }
        }
        window.customElements.define(ExampleTwo.is, ExampleTwo);
</script>
</dom-module>


来源:https://stackoverflow.com/questions/49689969/sharing-changes-to-data-between-polymer-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!