我是 Polymer 的新手,目前正在学习 Polymer 3.0 。我正在尝试制作一个工作如下的应用程序:

  • 从公共(public) url 获取播放列表数据(使用 Iron-ajax 元素)
  • 处理 handleResponse() 函数中的数据,并将值赋给 'playlistNames' 变量。
  • 使用路由显示播放列表和歌曲



  • 问题:(我被卡住的地方)

    在刷新页面 http://127.0.0.1:8081/playlist1 上,路由器正在加载 404 页面而不是播放列表页面,因为 playlistName 为空。但是,如果我单击任何播放列表(刷新页面后),则路由器正在工作。

    我无法在不同的函数“_routePageChanged”中访问更新的 playlistNames 数组。代码片段如下。

    handleResponse() func 中,我得到了正确的输出(带有播放列表列表的数组)。但是在 _routePageChanged() func' 中,输出是 [],一个空数组。

    routing - 无法在 Polymer JS 3.0 的路由函数中访问更改的数组  "value"? (使用 Iron-ajax 和 app-route 元素)-LMLPHP



    问题:

    我的理解:app-route 元素在 iron-ajax 元素之前处理。

    如何在 playlistNames 中访问 _routePageChanged 的新值?

    文件:my-element.js

    class MyApp extends PolymerElement {
        static get template() {
          return html `
            <!-- make api calls to fetch the playlists -->
            <iron-ajax
                    auto
                    url=""
                    handle-as = "json"
                    on-response="handleResponse"
                    last-response="{{ajaxResponse}}">
            </iron-ajax>
    
            <app-location route="{{route}}" url-space-regex="^[[rootPath]]">
            </app-location>
    
            <app-route route="{{route}}" pattern="[[rootPath]]:page" data="{{routeData}}" tail="{{subroute}}">
            </app-route>
    
            ...
                <iron-pages selected="[[page]]" attr-for-selected="name" role="main">
                  <my-view404 name="view404"></my-view404>
                  <data-send name="playlist" prop1="[[selectedPlaylist]]"></data-send>
                </iron-pages>
          `;
        }
    
        static get properties() {
          return {
            page: {
              type: String,
              reflectToAttribute: true,
              observer: '_pageChanged'
            },
            playlists: {
              type: Array,
              reflectToAttribute: true,
              value: 'waiting...',
              reflectToAttribute: true
            },
            playlistNames: {
              type: Array,
              value: function() {
                return [];
              }
            },
            selectedPlaylist: {
              type: String,
              value: 'selectedPlaylist is empty'
            },
            routeData: Object,
            subroute: Object
          };
        }
    
        static get observers() {
          return [
            '_routePageChanged(routeData.page, this.playlistNames.splices)'
          ];
        }
    
        // this function is called on api call
        handleResponse(event, request) {
          //  get all the playlists from the api call response
          this.playlists = request.response.playlists;
    
          // get all the playlist names
          for(let playlist of this.playlists) {
            if(this.playlistNames.length < this.playlists.length) {
              // this.playlistNames.push(playlist.name);
              this.push('playlistNames', playlist.name);
            }
          }
          console.log('handleResponse playlists', this.playlistNames); // ['playlist1', 'playlist2' ...]
    
          // on refreshing url, if any route is present, then find its id to fetch songs list from api
          if(this.routeData.page){
            for(let playlist of this.playlists){
              if(playlist.name === this.routeData.page){
                this.selectedPlaylist = playlist.id;
              }
            }
          }
        }
    
        // this func is called on route change or page refresh
        _routePageChanged(page, data) {
          console.log('routeData.page=', page);
          console.log('data=', data); // undefined
          console.log('_routePageChanged playlists.length=', this.playlistNames.length); // 0
          console.log('_routePageChanged playlists=', this.playlistNames); // empty
    
          if (!page) {
            this.page = 'view404';
          } else if (["playlist1", "playlist2"].indexOf(page)  !== -1) {
          //playlistNames is empty[],
          // } else if (this.playlistNames.indexOf(page) !== -1) {
            this.page = 'playlist';
          } else {
            this.page = 'view404';
          }
        }
    
        _pageChanged(page) {
          switch (page) {
            case 'view404':
              import('./my-view404.js');
              break;
            case 'playlist':
              import('./playlist-songs.js');
              break;
          }
        }
      }

    最佳答案

    编辑:改进的答案

    正如您在评论中所述,当路由更改为 View 时, _routePageChanged() 将始终在 handleResponse() 之前运行(因为 handleResponse() 是异步的),因此无论 handleResponse() 做什么,都只会在 _routePageChanged() 之后运行。

    如果您要遵循我的解决方案,则需要首先对数组属性 playlistNames observable 进行更改,因此:

    代替:
    this.playlistNames.push(playlist.name);
    用:
    this.push('playlistNames', playlist.name);
    As documented here

    解决方案 - 如果你真的需要检查 _routePageChanged() :

    您可以更改 _routePageChanged 以观察两个属性,而不仅仅是一个属性 page 。因此,您可以将观察者声明为 _routePageChanged(page) 并在其中包含逻辑,而不是 _routePagePlaylistNamesChanged(page, playlistNames) 。这样,观察者 will fire anytime any of the two properties change value 和你可以在其中包含逻辑,例如:

    _routePagePlaylistNamesChanged(page, playlistNames) {
      if(page == "myelement" && playlistNames.length > 0){
        //This is correct page and the playlistNames are defined
        console.log('_routePagePlaylistNamesChanged playlists', this.playlistNames);
      }
    }
    

    关于routing - 无法在 Polymer JS 3.0 的路由函数中访问更改的数组 "value"? (使用 Iron-ajax 和 app-route 元素),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51949759/

    10-12 01:06