【问题标题】:How to bind a Jquery scroll event to a dynamically added element?如何将 Jquery 滚动事件绑定到动态添加的元素?
【发布时间】:2014-09-17 16:40:26
【问题描述】:

我正在创建一个 Ember 组件,我需要将滚动事件绑定到一个动态创建的 div。

我的车把代码如下所示:

<div class="searchbarContainer" tabindex="0" bubbles=false>
    {{input type="search" name="searchFor" class="searchTextField" placeholder="Search..." value=searchKey}}

    {{#if searchKeyNotNull}}
    <div class="searchResultsContainer box-shadow" {{bind-attr id="searchBarID"}}>
        {{!-- BINDS ID TO searchBarID for searchResultsContainer--}}
            {{#if noResults}} {{!-- Then say : "No Results. " --}}
                      <div class="applicantsName noResults">
                        No Results found.
                      </div>      
            {{else}}
                {{!-- For each Row, include visual elements. --}} 
                {{#each toSearch }}
                    <div> ... </div>
                {{/each}}
            <div class='endOfResults'>
                End of Results
            </div> 
            {{/if}}
    </div>
    {{/if}}
</div>

设置逻辑,以便根据在此输入部分中输入的内容,将 searchKeyNotNull 更新为“true”或“false”,noResults 也是如此。

当它现在运行时,div searchResultsContainer 将填充包含结果的 div,并且有一个最大高度。我还启用了溢出,因此用户可以滚动查看结果。

我需要将一个滚动事件绑定到这个 div,这样当它到达末尾时,就会触发一个动作。

现在,这是我开始使用的事件代码:

        $('#searchBarID').bind('scroll',function(){
        if($(this).scrollTop() + $(this).innerHeight()>=$(this)[0].scrollHeight)
        {
          alert('end reached');
        }
      });

哪个有效。不幸的是,当这个 sn-p 运行时,div 还没有被创建,所以这个事件永远不会被绑定。我也尝试过使用jQuery.on函数,但是好像scroll没有冒泡,所以

        $('body').on('scroll','#searchBarID', function(){
        if($(this).scrollTop() + $(this).innerHeight()>=$(this)[0].scrollHeight)
        {
          alert('end reached');
        }
      });

不起作用。

我无计可施,试图找到解决方法;我需要: a)找到一种方法将滚动绑定到动态添加的元素,或者 b) 找出 Ember 何时创建元素,以便我可以立即插入此绑定代码。

解决这两个问题的解决方案对我有很大帮助!

【问题讨论】:

  • 查看 didInsertElement 钩子:stackoverflow.com/questions/8881040/…
  • 是什么导致id为searchBarID的元素被添加到DOM中?我不熟悉 Ember,但考虑到类似的问题,我会尝试将回调附加到创建 searchBarID 的任何内容,以便事件绑定确保跟随 DOM 节点的创建。
  • 我确实想过走这条路:不幸的是,我找不到关于何时以及如何创建 DOM 元素的好文档。谢谢!
  • 奥利弗,我确实检查了钩子,它肯定有助于清除我尚未提出的其他问题,但对于这种特殊情况,didInsertElement 只触发一次,并且重新创建了 DOM 元素之后多次。所以不幸的是,它不适用于这种情况。
  • @Darshan didInsertElement 钩子绝对是你要找的。你只需要稍微修改一下你的模板。

标签: javascript jquery ember.js scroll ember-data


【解决方案1】:

我多次反驳这个问题。我发现隐藏元素而不是将其放置在 if 块中最简单。

你可以通过扩展你的绑定属性来做到这一点

<div class="searchResultsContainer box-shadow" {{bind-attr id="searchBarID" class="searchKeyNotNull::hidden"}}>

hidden 在哪里是一个将display 设置为none 的类。 这将导致元素只渲染一次,允许您像这样使用didInsertElement 钩子:

onDidInsert: function () {
    var element = $('#searchBarID', this.$());
    element.on('scroll', function () {
        // your impl.
    })
}.on('didInsertElement')

在您的组件中。

我使用bind-attr 隐藏元素(而不是不渲染它!)的原因是每次searchKeyNotNull 更改时,ember 都会创建一个新元素。 didInsertElement 钩子只会触发一次。

【讨论】:

  • 嗯。绝对是一个可靠的建议:当我首先创建某些东西时,它似乎正在破坏,然后被篡改。我会在确认它正常工作后立即更新此评论。
【解决方案2】:

scrollloaderror 事件没有冒泡(参见:https://developer.mozilla.org/en-US/docs/Web/Events/scroll),因此您必须在添加可滚动元素时更新处理程序。

【讨论】:

  • 我知道它不会冒泡;这就是为什么我要问是否有可能在创建元素时绑定滚动,为此我需要知道 Ember 何时以及如何创建 DOM 元素。我想知道是否有人可以为我提供答案。
【解决方案3】:

大多数时候,有一种方法可以使用 Ember 视图挂钩、操作和事件来完成您通常在 jQuery 中执行的操作。

另一种方法是将该 DOM 节点包装在 {{#view}} 中,然后使用 didInsertElement 挂钩。比如我们把它包裹在{{#view App.SearchResultsView}}

<div class="searchbarContainer" tabindex="0" bubbles=false>
    {{input type="search" name="searchFor" class="searchTextField" placeholder="Search..." value=searchKey}}

    {{#if searchKeyNotNull}}
      {{#view App.SearchResultsView}}
        <div class="searchResultsContainer box-shadow">
          <!-- MORE HBS HERE -->
        </div>
      {{/view}}
    {{/if}}
</div>

现在,让我们定义App.SearchResultsView

App.SearchResultsView = Ember.View.extend({
  didInsertElement: function () {
    this.$('.searchResultsContainer').on('scroll', function (e) {
      // scrolling...
    });
  }
});

希望对您有所帮助!让我知道是否可以进一步解释。

【讨论】:

  • 哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇。我的意思是如果是这样 - 哇 - 每次 dom 元素更改时,都会重新创建视图,并且每次重新创建视图时,都会触发 didInsertElement,因此每次我需要滚动绑定时,它都会被绑定在那里。我必须尽快尝试这条路线。稍后会更新。
  • @Darshan 这正是我要告诉你的。 :D 很容易遵循的模式,对吧?每次呈现视图时,它都会收到一个唯一的 id。因此,无需担心绑定。
  • 啊,我遇到了一个问题。似乎一旦进入视图,视图就无法再访问 SearchBarComponent 中定义的方法。所以虽然滚动绑定有效,但由于我无法访问组件的逻辑部分,我无法调用我需要的函数。除非我在这里遗漏了什么......
  • 是的,你遗漏了一些东西。 :) 您可以从组件和视图访问当前控制器...this.get('controller') 并且您可以使用Ember.Evented 作为与该控制器的混合,以便根据需要进行通信。您可以让视图滚动事件调用在视图中触发某些内容的控制器方法。 emberjs.com/api/classes/Ember.Evented.html 让您的控制器进行“思考”,让您的视图向其发送消息。希望这是有道理的。
  • @Darshan 所以在你的组件中,你可以做类似this.get('controller').on('searchTriggerFired', this.doSomethingThatViewToldMeToDoThroughTheController);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 2015-09-07
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多