2016-08-24 17 views
1

在一个关于分页的例子中,根据应该显示多少结果将不同的数字传递给路由。当订阅已经限制数据集时,是否需要通过数据限制?

// lib/router.js 
Router.route('/:postsLimit?', { 
    name: 'postsList', 
    waitOn: function() { 
    var limit = parseInt(this.params.postsLimit) || 5; 
    return Meteor.subscribe('posts', {sort: {submitted: -1}, limit: limit}); 
    }, 
    data: function() { 
    var limit = parseInt(this.params.postsLimit) || 5; 
    return { 
     posts: Posts.find({}, {sort: {submitted: -1}, limit: limit}) 
    }; 
    } 
}); 

我想知道是否仍然需要在数据属性中提供Posts.find()参数。这似乎有点多余,因为waitOn中的订阅已经限制了我从服务器获取的数据集。我知道数据用于为我的模板的不同部分提供数据上下文。然而,在这里提供相同的参数Posts.find()似乎是多余的。我试过只使用Posts.find()而没有参数,它工作。

此外,我想知道什么是访问路由器中的所有数据的方式?我正在访问单个路由之外的Posts集合,我认为我将能够访问Posts集合中的所有数据。但是,它与计数返回0

// lib/router.js 
var totalPostsCount = Posts.find().count() 
console.log('total count?') 
console.log(totalPostsCount)  // output 0 


PostsListController = RouteController.extend({ 
    template: 'postsList', 
    increment: 5, 
    postsLimit: function() { 
    return parseInt(this.params.postsLimit) || this.increment; 
    }, 
    findOptions: function() { 
    return {sort: {submitted: -1}, limit: this.postsLimit()}; 
    }, 
    subscriptions: function() { 
    this.postsSub = Meteor.subscribe('posts', this.findOptions()); 
    }, 
    posts: function() { 
    // console.log("is find limited to subscriptions too??"); 
    // console.log(Posts.find().count()) 
    return Posts.find({}, this.findOptions()); 
    }, 
    data: function() { 
    // console.log('is data limited to this?') 
    // console.log(Posts.find().count()) 

    var hasMore = this.posts().count() === this.postsLimit(); 
    var adjustOrNot = this.posts() 
    if (!hasMore){ 
     var nextPath = this.route.path({postsLimit: this.posts().count()});  
    }else{ 
     var nextPath = this.route.path({postsLimit: this.postsLimit() + this.increment});  
    } 
    return { 
     posts: this.posts(), 
     ready:this.postsSub.ready(), 
     nextPath: hasMore ? nextPath : null 
    }; 
    } 
}); 

//... 

Router.route('/:postsLimit?', { 
    name: 'postsList' 
}); 

编辑1:

// server 
Meteor.publish('allPosts',function(){ 

    return Posts.find({}); 
}) 


// lib/router.js 
if (Meteor.isClient){ 
    var handle = Meteor.subscribe('allPosts'); 
    if (handle.ready()) { 
     // This logs the actual count of posts 
     console.log(Posts.find().count()); 
    } else { 

     console.log('not ready yet'); 
    } 
} 

这仅输出“还没有准备好”在控制台,它甚至没有改变:为让所有职位代码当页面加载完成时。

非常感谢您的帮助。

编辑2:可能的解决方案

我试过包装计算里面的反应源就绪(),如Tracker.autorun(),现在它的工作。

if (Meteor.isClient){ 
    var handle = Meteor.subscribe('allPosts'); 

    Tracker.autorun(function(){ 
     var status = handle.ready(); 
     if (status){ 
      console.log(Posts.find().count()) 
     }else{ 
      console.log('not ready yet') 
     } 
    }) 

} 

回答

2

是的,您应该将限制和其他查询选项也传递给前端查询,无论您的订阅如何。这是因为如果您要同时激活同一个集合的多个订阅(通常是在较大的应用中完成的),订阅的记录最终会与前端的Minimongo集合中的所有记录完全相同。在这种情况下,如果您省略了查询参数,那么最终会产生不可预知的结果。详见this excellent explanation。另请注意,尽管iron:router支持在路由处理程序it's encouraged中执行订阅,以便在模板生命周期方法中处理它们。

对于第二个问题,Posts集合显示为空的原因是文件顶层的代码在文件加载时立即运行。此时,集合订阅尚未加载,所以前端集合为空。你需要在某些情况下反应,以检查订阅的准备,如模板助手或Tracker.autorun,以确保数据被加载:

var handle = Meteor.subscribe('posts'); 
if (handle.ready()) { 
    // This logs the actual count of posts 
    console.log(Posts.find().count()); 
} else { 
    // This logs 0 (unless there are other subscriptions to this collection) 
    console.log(Posts.find().count()); 
} 
+0

第一部分做了这么多的意义。但是对于第二部分,我尝试使用ready(),但没有任何显示。我在问题中添加了新代码。 – whales

+0

是否因为我没有在计算中包装反应性来源?我试图将其包装在Tracker.autorun中,它工作。 – whales

+0

@鲸鱼是的,这是令人兴奋的问题。当反应性函数(如'subscriptionHandle.ready()')在反应性上下文中调用时,Meteor反应性可以工作,比如'iron:router'路由定义的模板助手'Tracker.autorun'。除这些功能外,Meteor无法在其反应性数据源趋势下重新运行代码。 – Waiski