在尚未添加到 DOM 的视图上使用骨干事件 - 渲染问题

发布于 2024-12-02 07:49:56 字数 2001 浏览 0 评论 0原文

短篇故事...我有嵌套视图,但只有顶级视图可以处理事件,因为我只将“el”属性传递给顶级视图。

长话短说...

我正在创建一个时间线项目,使用主干作为 JS/GUI 客户端应用程序。我用于渲染水平时间线的模板如下:

<script type="text/template" id="yearGroups">
<![CDATA[
   <% _.each(columns, function(item,i) { %>
      <div class="yearGroup">
         <h2><%= item.yearLabel %></h2>
         <div class="years">
            <% _.each(item.years, function(year, b) { %>

               <div class="year">

                  <% _.each(year.searchGroups, function(sg, sg_index) { %>               
                     <%= jQuery(sg.viewEl).html() %>
                  <% }); %>

               </div>
            <% }); %>
         </div>
      </div>
   <% }); %>
]]>
</script>

每年可以有多个搜索,因此可以有多个 searchGroups。 每个 searchGroup 都包含 eventBlocks 作为每个搜索结果的包装器。

下面是创建 SearchGroupViews 的循环中的代码片段(它创建了此处未显示的 eventBlocks)。

var events = eventCollection.getEventsInYear(year);
if(events.length > 0) {
   var sgv = new SearchGroupView({results: events, searchID: 'search1'});
   this.searchGroups.push(sgv);
   renderedResults.push({viewEl:sgv.render().el});
}

然后,renderedResults 最终传递到模板,如下所示:

$(this.el).html(this.template({columns:col}));

... 并在每个 .year 下渲染,使用:

jQuery(sg.viewEl).html().

所有这些意味着我的嵌套视图不会收到任何事件,因为它们没有使用 'el' 属性传入的容器 div。它们没有容器,因为它是在构建所有视图之后渲染的(请参阅第一个代码块)。

我当前的解决方案是使用全局 eventManager,它可以用作事件处理程序,以便在顶级视图调用 eventManger.trigger(..) 时通知视图。这并不理想。

必须有一个解决方案允许我的嵌套视图在渲染事件后拾取事件?或者我是否需要预渲染顶级视图模板并指定 el 属性,例如 {el: '.year.yearID-1984'}{el: '.searchGroup.groupID- 6'}

理想情况下,我可以渲染 sg.viewEl 而不仅仅是该对象的 html 输出,然后视图会自我意识到它在哪里。 ...但我知道那是不可能:(

希望这是清楚的。

Short story... I have nested views but only the top level view can work with events because I am only passing in the 'el' property to the top level view.

Long story...

I am creating a timeline project using backbone as JS/GUI client side app. My template for rendering the horizontal timeline is like this:

<script type="text/template" id="yearGroups">
<![CDATA[
   <% _.each(columns, function(item,i) { %>
      <div class="yearGroup">
         <h2><%= item.yearLabel %></h2>
         <div class="years">
            <% _.each(item.years, function(year, b) { %>

               <div class="year">

                  <% _.each(year.searchGroups, function(sg, sg_index) { %>               
                     <%= jQuery(sg.viewEl).html() %>
                  <% }); %>

               </div>
            <% }); %>
         </div>
      </div>
   <% }); %>
]]>
</script>

There can be multiple searches and therefore multiple searchGroups per year.
Each searchGroup contains eventBlocks as a wrapper for each search result.

Below is a code snippet from the loop which creates the SearchGroupViews (which creates the eventBlocks not shown here).

var events = eventCollection.getEventsInYear(year);
if(events.length > 0) {
   var sgv = new SearchGroupView({results: events, searchID: 'search1'});
   this.searchGroups.push(sgv);
   renderedResults.push({viewEl:sgv.render().el});
}

renderedResults is then eventually passed through to the template like this:

$(this.el).html(this.template({columns:col}));

... and rendered under each .year using:

jQuery(sg.viewEl).html().

All of this means that my nested views don't receive any events because they don't have a container div passed in using the 'el' attribute. They don't have a container because that's rendered after all the views are built (see first code block).

My current solution is to use a global eventManager that can be used as an event handler to notify views when the top level view calls an eventManger.trigger(..). This is not ideal.

There must be a solution that allows my nested views to pick up on the events after they have been rendered? Or do I need to pre-render the top level view template and specify el attributes like {el: '.year.yearID-1984'} and {el: '.searchGroup.groupID-6'}?

Ideally I could render sg.viewEl and not simply the html output from that object and the view would then be self aware of where it is. ... but I know that's not possible :(

Hope this is clear.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

妄想挽回 2024-12-09 07:49:56

我实现了一个接近我的问题中描述的解决方案...

//global event notifier system
window.vent = _.extend({}, Backbone.Events);
window.app = new TimelineRouter();

渲染顶级视图后,然后调用:

window.vent.trigger('ev:redelegate', {});

然后在每个视图初始化函数中捕获此事件...

this.model.view = this;
var _this = this;

window.vent.bind('ev:redelegate', function(event) {
   var nid = _this.model.get('nid');
   _this.el = $('.nid-'+nid);

   _this.delegateEvents();
});

...以便视图可以更新埃尔财产。这一切都依赖于用于查找 el 的唯一类名(例如,class="nid-1234")。

我猜这与在 init 上设置 view el 属性相同,因为我知道它所基于的 id。这假设主干使用 .live(..) 来查找 el: ".nid-1234" DOM 对象。

I implemented an ok solution close to what was described in my question...

//global event notifier system
window.vent = _.extend({}, Backbone.Events);
window.app = new TimelineRouter();

After rendering the top level view, I then call:

window.vent.trigger('ev:redelegate', {});

This event is then captured in each view init function....

this.model.view = this;
var _this = this;

window.vent.bind('ev:redelegate', function(event) {
   var nid = _this.model.get('nid');
   _this.el = $('.nid-'+nid);

   _this.delegateEvents();
});

...so that the view can update the el property. This all relies on a unique class name being used to find the el (eg, class="nid-1234").

I'm guessing this would then be the same as setting the view el property on init given that I know the id it's based on. This assumes that backbone uses .live(..) for finding the el: ".nid-1234" DOM obj.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文