当Meteor更新集合时如何防止内容滚动

3

我的问题类似于这个那个,但不完全相同。

我在我的Meteor应用程序中有以下模板:

<template name="items">
    <div class="mainframe">
    <h3>Available items:</h3>
        <div class="items-table-container">
            <table class="table table-hover">
                <tbody>
                    {{#each all_items}}
                       {{> item}}
                    {{/each}}
                </tbody>
            </table>
        </div>
    </div>
    <div class="btn-group">
    <button id="create" class="btn">Create new item</button>
    </div>
</template>

模板函数是一种简单的功能:
Template.items.all_items = function () {
    return Items.find({}, {sort: {name: 1}}).fetch();
}

还有一个事件绑定在#create按钮上,它将一个新项目插入到Items集合中,这个功能很好用。

现在最重要的部分是CSS:

.items-table-container {
    height:340px;
    overflow-y: scroll;
}

所以基本上,我希望我的表格在固定大小的区域内拥有可滚动的内容。 问题开始于当我在一个浏览器中滚动项目表格的内容,然后在另一个浏览器中添加了一个新项目时。第一个浏览器会更新项目列表并将内容滚动回到顶部位置。
问题是如何防止单个模板的自动更新? 在这种特殊情况下,我认为我实际上需要类似传统网页更新的东西: 如果用户没有立即看到新添加的项目,而是在重新加载页面后才能看到,那也没关系。
另一个想法是进行某种分页,而不是滚动内容。我认为这将解决问题,但这将更加复杂,我希望避免这种情况。
我认为理想情况下,我希望能够告诉Meteor,我希望Meteor不是在模型更改时更新模板,而是通过请求来更新模板。
4个回答

4
将你的项目列表放在可滚动的div容器内的另一个模板中:
<template name="items">
    <div class="mainframe">
    <h3>Available items:</h3>
        <div class="items-table-container">
            <table class="table table-hover">
                <tbody>
                    {{> myitems}}
                </tbody>
            </table>
        </div>
    </div>
    <div class="btn-group">
        <button id="create" class="btn">Create new item</button>
    </div>
</template>

<template name="myitems">
    {{#each all_items}}
        {{> item}}
    {{/each}}
</template>

JavaScript:

Template.myitems.all_items = function () {
    return Items.find({}, {sort: {name: 1}}).fetch();
}

//Template.items.all_items = function () {
// remove this helper
//}

这样,您可以在不发送更新请求的情况下保持反应性。只有可滚动框中的部分会重新渲染,保持滚动容器的位置。
编辑:要保留/冻结您的内容,您可以使用preserve函数,它以css选择器作为输入。例如:
Template.items.preserve(['.items-table-container']);

解决了问题,谢谢!不过我认为应该有一种可能性来“冻结”渲染模板,因为有时候响应式行为是不必要的。 - conceptacid
我不知道"preserve",但是在重新渲染时保留滚动位置并不能保持。不过在其他场景下会有帮助。 - Tarang
#isolate、#constant和#preserve已经被移除:https://github.com/meteor/meteor/wiki/Using-Blaze#no-more-constant-isolate-or-preserve - Aaron

3

将数组迭代隔离。

{{#isolate}}
  {{#each all_items}}
    {{> item}}
  {{/each}}
{{/isolate}}

+1 这样做可以达到将内容放入另一个模板的效果,但是如果您的代码更适合保持在同一模板上下文中,则可以保持不变。 - Andrew Mao
#isolate, #constant, and preserve have all been removed: https://github.com/meteor/meteor/wiki/Using-Blaze#no-more-constant-isolate-or-preserve - Aaron

1
要使整个区域保持不变以避免重新渲染,您可以使用块助手{{#constant}}。
如果您有特定的DOM元素需要保留,可以使用Template.myTemplate.preserve(),它接受要保留的节点的选择器作为参数。

#isolate、#constant和#preserve已被移除:https://github.com/meteor/meteor/wiki/Using-Blaze#no-more-constant-isolate-or-preserve - Aaron

-1

你也可以使用jQuery来处理滚动位置的修复。我的用例是在主体文档中当前滚动点上方插入一些内容,然后将文本向下滚动。

还不确定如何让Meteor在每次更新发布集时运行回调函数,但你应该能理解这个想法:

before = document.body.scrollHeight
// insert your elements
after = document.body.scrollHeight

if $(document).scrollTop() != 0
  # scroll us equal to the amount of scroll height added
  window.scrollTo(0, $(document).scrollTop()+(after-before) )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接