【问题标题】:How to maintain scroll position when new posts are reactively rendered?当新帖子被反应性呈现时如何保持滚动位置?
【发布时间】:2015-03-10 08:59:22
【问题描述】:

假设我正在渲染一堆帖子。

{{#each posts}}
  {{>post}}
{{/each}}

我收到一堆按日期排序的帖子。

Posts.find({}, {sort:{name: 1, date:-1}, limit: Session.get('limit')}).fetch()

正如您对移动应用程序所期望的那样,我在这里进行了一些反应性滚动。但现在的问题是,当有人发布新内容时,一切都变了。我的滚动位置保持不变,但我不再看同一个帖子。

任何想法如何让它工作?

编辑:

在我看来,最优雅的解决方案就是颠倒我们对滚动的看法。如果我们以另一种方式对帖子进行排序 - 最旧的在顶部,那么新帖子将最终在底部并且不会弄乱 scrollTop 位置。

编辑 2:

我忘了提——我不知道我要插入的元素的高度。否则我可以接受ugly brute force method

【问题讨论】:

  • 这里只是集思广益,但如果您使用集合挂钩包,您可以在 Posts.find() 函数之后在 scrollTo 上触发它。可能是一种更简单的方法。
  • 我考虑过使用Cursor.observe,但那是一个巨大的痛苦,我相信它会有些卡顿。看看我的编辑——这里太长了
  • 一种方法是让帖子从顶部滑入(即从高度 0 到 500 像素),同时使页面以与帖子相同的速度滚动滑入(即使帖子滑入超过 650 毫秒,滚动也超过 650 毫秒)
  • 是的,但我还要提一个问题——我不知道我要插入的元素的高度...
  • 您可以使用 javascript 来获取元素高度,我知道您可以使用 jQuery 确定有一个原生 JS 等价物。实际上可能只是 .height

标签: javascript meteor meteor-blaze


【解决方案1】:

好的,我遇到了同样的问题,这是我想出的粗略解决方案。如果您发现其中有任何漏洞,请告诉我。

Template.postsList.rendered = function (){
this.find('.wrapper')._uihooks = {
    insertElement: function (node, next){

        //hide newly added element, add a class to identify it as a post inserted 
        //after initial load.
        $(node).hide().insertBefore(next).addClass('insertedAfterLoad');

        //if it's at the top of the page, fade it in, otherwise it will stay hidden
        if (getDistance() === 0){
            $(node).fadeIn();
        } 
    }
},

//Continually watch the page while scrolling
$(document).scroll(function(){
        var scrollDistance = getDistance();

        //if any posts have the  'insertedAfterLoad' class, fade them into view.
        //this will only load new posts if the user scrolls back to the top
        if( scrollDistance === 0 && $('.post').hasClass('insertedAfterLoad') ){
            $('.insertedAfterLoad').fadeIn();
        }
});

//This will get the distance to the top of the page of any elements 
//inserted after the initial page load
var getDistance = function(){
        if( $('.post').hasClass('insertedAfterLoad') ){
            return $('.insertedAfterLoad').offset().top;
        }
    }
}

【讨论】:

    【解决方案2】:

    我对你真正想要做什么有点困惑,但如果你想在底部有新帖子并滚动到它们,你可以做一些类似于我在这个 @987654321 中所做的事情@ 使用 scrollTo 作为 Meteor。

    首先,将scrollTo包添加到meteor app中

    $ meteor add natestrauser:jquery-scrollto
    

    在用于将表单中的帖子提交到集合中的模板事件中,使用scrollTo 添加 setTimeout 函数,该函数将在新帖子添加到集合后几毫秒触发,并滚动到新帖子:

    Template.posts.events({
        "submit .new-post": function (event) {
        var title = event.target.postTitle.value;
        var text  = event.target.postText.value;
    
        Posts.insert({
          title: title, 
          text: text, 
          date: new Date() // current time
        });
    
        setTimeout(function(){
            $(".posts-wrapper").scrollTo("max", 500); // change 500 miliseconds to whatever speed you want
        }, 100);
    
        // Clear form
        event.target.postTitle.value = "";
        event.target.postText.value = "";
    
        // Prevent default form submit
        return false;
      }
    });
    

    我们获取帖子、进行排序等的模板助手:

    Template.posts.helpers({
        posts: function() {
            return Posts.find({}).fetch;
        }
    }); 
    

    带有表单的模板以添加帖子以及在div 中呈现的帖子,类.posts-wrapper

    <template name="posts">
        <form class="new-post">
            <label>Post title: </label>
            <input type="text" name="postTitle">
            <label>Post text: </label>
            <input type="textarea" name="postText">
        </form>
        <div class="posts-wrapper">
            {{#each posts}}
                {{> post}}
            {{/each}}
        </div>
    </template>
    

    您可以在here 中看到这个并检查这个Meteorpad 中的代码。

    如果您需要滚动整个&lt;body&gt;,只需使用:

    setTimeout(function(){
        $("body").scrollTo("max", 500); // change 500 miliseconds to whatever speed you want
    }, 100);
    

    【讨论】:

      猜你喜欢
      • 2014-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-01
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多