从组件更新路由模型

Posted

技术标签:

【中文标题】从组件更新路由模型【英文标题】:Update Route Model from Component 【发布时间】:2017-05-24 20:54:55 【问题描述】:

我是 Ember.js 的新手,我正在尝试使用他们的 API 创建一个模仿 Youtube 的应用程序。目前我有一条路线负责从 Youtube Api 获取初始信息以填充加载页面。我有一个搜索栏组件,用于收集用户的输入并使用基于字符串的结果重新填充列表。问题是,当我从用户那里获取输入时,我的 Route 模型没有刷新以从 api 获取更新数据。下面是我的代码。

我的视频路由 video.hbs 的模板:

// app/templates/video.hbs
<div class="row">
  search-bar
<div class="row">
  <div class="col-md-12">
    <hr>
    <br>
  </div>
</div>
<div class="row">
  <div class="col-md-8">
    <div class="row">
      video-list model=model
        <div class="col-md-4 pull-right video-container">
          #if  videoId
            <iframe id="video-player" src="https://www.youtube.com/embed/videoId"></iframe>
          else
            <iframe id="video-player" src="https://www.youtube.com/embed/kEpOF7vUymc"></iframe>
          /if
        </div>
      </div>
    </div>
  </div>
</div>

我的搜索栏模板

// app/templates/components/search-bar.hbs
<div class="col-md-12 col-md-offset-4">
    <form class="form-inline">
      <div class="form-group" onsubmit="return false">
        input type="text" class="form-control" value=search id="search" placeholder="Search Videos..."
      </div>
      <button type="submit" action "updateSearch"class="btn btn-success">Search</button>
    </form>
</div>

我的搜索栏组件

// app/components/search-bar.js
import Ember from 'ember';

export default Ember.Component.extend(
  userSearch: "",
  actions: 
    updateSearch: function() 
      this.set("userSearch", this.get("search"));
      this.modelFor("videos").reload();
    
  
);

视频路线

// app/routes/video.js
import Ember from 'ember';

export default Ember.Route.extend(
  model: function() 
    var userSearch = this.get("search") === undefined ? "Code" : this.get("search");
    this.set("search", userSearch);
    var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&q="+ userSearch +"&maxResults=50&key="api key goes here";
    return Ember.$.getJSON(url).then(function(data) 
      return data.items.filter(function(vid) 
        if(vid.id.videoId) 
          return vid;
        
      );
    );
  
);

【问题讨论】:

【参考方案1】:

reload - 不会调用模型钩子方法,在这种情况下,您可以将动作发送到视频路由并从那里尝试refresh。

编辑:

根据您的用例调整您的代码,如果它不起作用或这种方法有什么问题,请告诉我。

app/routes/video.js 这里我们使用 RSVP.hash 函数返回multiple model。我也包括userSearch。对于这个用例最好实现query parameters,但我没有使用它就实现了。

import Ember from 'ember';

export default Ember.Route.extend(
    userSearch: '',
    model: function() 
        var userSearch = this.get("userSearch") === undefined ? "Code" : this.get("userSearch");
        var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + userSearch + "&maxResults=50&key=apikey";
        return Ember.RSVP.hash(
            videosList: Ember.$.getJSON(url).then(function(data) 
                return data.items.filter(function(vid) 
                    if (vid.id.videoId) 
                        return vid;
                    
                );
            ),
            userSearch: userSearch
        );
    ,
    actions: 
        refreshRoute(userSearch) 
            this.set('userSearch',userSearch);
            this.refresh();
        ,
    
);

app/controllers/viedo.js 它包含 refreshRoute 函数,这将调用视频路由文件中可用的 refreshRoute 函数。

import Ember from 'ember';
export default Ember.Controller.extend(
  actions:
      refreshRoute(userSearch)
          this.sendAction('refreshRoute',userSearch);
      
  
);

app/templates/video.hbs 1. 我将userSearch 属性和refreshRoute 动作名称传递给搜索栏组件 2. 使用model.videosList访问videosList

<div class="row">
  search-bar userSearch=model.userSearch refreshRoute="refreshRoute"
<div class="row">
  <div class="col-md-12">
    <hr>
    <br>
  </div>
</div>
<div class="row">
  <div class="col-md-8">
    <div class="row">
      video-list model=model.videosList
        <div class="col-md-4 pull-right video-container">
          #if  videoId
            <iframe id="video-player" src="https://www.youtube.com/embed/videoId"></iframe>
          else
            <iframe id="video-player" src="https://www.youtube.com/embed/kEpOF7vUymc"></iframe>
          /if
        </div>
      </div>
    </div>
  </div>
</div>

app/components/search-bar.js 在这里,您将获得 userSearch 属性作为外部属性,即。它将作为包含组件的参数传递。

import Ember from 'ember';
export default Ember.Component.extend(
    userSearch:'',//external attributes
    actions: 
        updateSearch() 
            var userSearch = this.get('userSearch');
            this.sendAction('refreshRoute',userSearch); //this will call corresponding controller refreshRoute method
        
    
);

app/templates/components/search-bar.hbs

<div class="col-md-12 col-md-offset-4">
    <form class="form-inline">
      <div class="form-group" onsubmit="return false">
        input type="text" class="form-control" value=userSearch id="search" placeholder="Search Videos..."
      </div>
      <button type="submit" action "updateSearch"class="btn btn-success">Search</button>
    </form>
</div>

【讨论】:

我之前尝试过。整个页面将重新加载,用户输入将丢失。 refresh 将触发 beforeModel、model 和 afterModel 钩子。然后数据将在模板中更新。看起来您的代码与 searchuserSearch 属性几乎没有混淆,这可能是用户输入丢失的原因。您可能需要引入 queryParam 进行搜索 我的理解是我从输入中获取值并将该值设置为 userSearch 属性。我的期望是正确的还是我在做不同的事情? 是的,你是对的。那么您是否期望userSearch 可以在routes/video.js 文件中使用?我无法理解模型挂钩中的代码this.set("search", userSearch) 我认为它可以在 routes/video.js 上使用。它会看到发生了变化,然后刷新模型以从 api 获取新结果。我认为“搜索”是全局的,因此可以在模型中设置。

以上是关于从组件更新路由模型的主要内容,如果未能解决你的问题,请参考以下文章

Angular:从卡片路由到新视图

vueJS 路由器:从组件数据更新页面标题

如何在 Angular 1.5 中注入组件路由器?

nuxt watchQuery 无法使用新查询处理更新路由

Vue路由Vue UI组件库

Vue路由Vue UI组件库