Polymer deactivating pages when their not in view

2019-04-06 13:26发布

问题:

I'm using the polymer application drawer template from the polymer cli.

I'm having some trouble with:

  1. When you load a new page, the html element is imported; then it's code executes
  2. When I move to another page the code for the previous page is still running.

Is there a way to destroy and create the page/element or suspend and enable?

Whats the best practice for dealing with this problem?

Have the pages implement a create and destroy method and invoke it when changing page?

Ie

oldPageElement.destroy();
newPageElement.create();



Polymer({
  is: 'my-random-page',
  behaviors: [MyBehaviors.CommonPageBehavior],


 /**
  * @override
  */
  create: function() {..}



 /**
  * @override
  */
  destroy: function() {..}

})

回答1:

You actually don't need to implement anything complicated, but just use a mere dom-if.

Working prototype: http://jsbin.com/gezihatera/edit?html,console,output

As you can see, the "View One" uses a custom page element, which is always restamped when re-selected. Other pages are ordinary div elements, since this is only a minimal prototype. But this also shows that you can selectively choose which pages get restamped and which do not (if you don't always need this).

The essence is the following: as per dom-if documentation, if you set the restamp attribute to true, then the dom-if will always create and destroy your pages upon selecting/deselecting them. You can see this in the console, where I print out sample-page ready on every ready element. I also create a helper function _equals to help with comparing whether the specified page is really selected.

To sum up, let me paste the code for the app:

<dom-module id="sample-app">
    <template>
        <style>
            :host {
                display: block;
            }
        </style>

        <iron-selector selected="{{page}}" attr-for-selected="name">
            <a name="view1" href="#">View One</a>
            <a name="view2" href="#">View Two</a>
            <a name="view3" href="#">View Three</a>
        </iron-selector>

        <iron-pages role="main" selected="[[page]]" attr-for-selected="name">
            <template is="dom-if" if="[[_equals(page, 'view1')]]" restamp="true">
                <sample-page name="view1">view1</sample-page>
            </template>
            <div name="view2">view2</div>
            <div name="view3">view3</div>
        </iron-pages>
    </template>
    <script>
        Polymer({
            is: 'sample-app',
            _equals: function(a, b) {
                return a == b;
            },
        });
    </script>
</dom-module>

And the code for the sample page:

<dom-module id="sample-page">
    <template>
        <style>
            :host {
                display: block;
            }
        </style>

        <content></content>
    </template>
    <script>
        Polymer({
            is: 'sample-page',
            ready: function() {
                console.log('sample-page ready');
            },
        });
    </script>
</dom-module>

Hope this satisfies your question.

Note: you should not put the name attribute on the dom-if itself, but rather onto its content (the same way I did).



回答2:

Thought I would post my solution after implementing @alesc's dom-if to get the element to be deactivated.

// after a successful importHref, _pageLoaded is called.
_pageLoaded: function(pageName) {
  var name = 'my-' + pageName;
  this.async(function() {
    // async to wait for element restamping, if done
    var pages = this.$.pages;
    var page = pages.querySelector(name);
    page.load()
    .then(page.isAuthorized.bind(this))
    .catch(this._catchPageIsAuthorizedError.bind(this))
    .then(this._shouldSetPage.bind(this, pageName));
  }.bind(this));
}