当前位置:K88软件开发文章中心编程语言JavaScriptMeteor → 文章内容

Meteor 投票

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 15:29:04

由 北公爵无欢 创建,路飞 最后一次修改 2016-08-12 投票现在我们的系统更完善了,但是想要找到最受欢迎的帖子有点难。我们需要一个排名系统来给我们的帖子排个序。我们可以建立一个基于 karma 的复杂排名系统,权值随着时间衰减,和许多其他因素(很多功能都在 Telescope 中实现了,他是 Microscope 的大哥)。但是对于我们的例子 app, 我们尽量保持简单,我们只按照帖子收到的投票数为它们排序。让我们实现一个给用户为帖子投票的方法。数据模型我们将在帖子中保存投票者列表信息,这样我们能判断是否给用户显示投票按钮,并阻止用户给一个帖子投票两次。数据隐私与发布我们将向所有用户发布投票者名单,这样也自动使得通过浏览器控制台也可以访问这些数据。这是一类由于集合工作方式而引发的数据隐私问题。例如,我们是否希望用户能看到谁为他的帖子投了票。在我们的例子中,公开这些信息无关紧要,但重要的是至少知道这是个问题。我们也要非规范化帖子的投票者数量,以便更容易取得这个数值。所以我们给帖子增加两个属性,upvoters(投票者) 和 votes(票数)。让我们先在 fixtures 文件中添加它们:// Fixture dataif (Posts.find().count() === 0) { var now = new Date().getTime(); // create two users var tomId = Meteor.users.insert({ profile: { name: 'Tom Coleman' } }); var tom = Meteor.users.findOne(tomId); var sachaId = Meteor.users.insert({ profile: { name: 'Sacha Greif' } }); var sacha = Meteor.users.findOne(sachaId); var telescopeId = Posts.insert({ title: 'Introducing Telescope', userId: sacha._id, author: sacha.profile.name, url: 'http://sachagreif.com/introducing-telescope/', submitted: new Date(now - 7 * 3600 * 1000), commentsCount: 2, upvoters: [], votes: 0 }); Comments.insert({ postId: telescopeId, userId: tom._id, author: tom.profile.name, submitted: new Date(now - 5 * 3600 * 1000), body: 'Interesting project Sacha, can I get involved?' }); Comments.insert({ postId: telescopeId, userId: sacha._id, author: sacha.profile.name, submitted: new Date(now - 3 * 3600 * 1000), body: 'You sure can Tom!' }); Posts.insert({ title: 'Meteor', userId: tom._id, author: tom.profile.name, url: 'http://meteor.com', submitted: new Date(now - 10 * 3600 * 1000), commentsCount: 0, upvoters: [], votes: 0 }); Posts.insert({ title: 'The Meteor Book', userId: tom._id, author: tom.profile.name, url: 'http://themeteorbook.com', submitted: new Date(now - 12 * 3600 * 1000), commentsCount: 0, upvoters: [], votes: 0 }); for (var i = 0; i < 10; i++) { Posts.insert({ title: 'Test post #' + i, author: sacha.profile.name, userId: sacha._id, url: 'http://google.com/?q=test-' + i, submitted: new Date(now - i * 3600 * 1000 + 1), commentsCount: 0, upvoters: [], votes: 0 }); }}和之前一样,停止你的 app, 执行 meteor reset, 重启 app,创建一个新的用户。让我们确认一下用户创建帖子时,这两个新的属性也被初始化了://...var postWithSameLink = Posts.findOne({url: postAttributes.url});if (postWithSameLink) { return { postExists: true, _id: postWithSameLink._id }}var user = Meteor.user();var post = _.extend(postAttributes, { userId: user._id, author: user.username, submitted: new Date(), commentsCount: 0, upvoters: [], votes: 0});var postId = Posts.insert(post);return { _id: postId};//...投票模板开始时,我们在帖子部分添加一个点赞(upvote)按钮,并在帖子的 metadata 数据中显示被点赞次数:<template name="postItem"> <div class="post"> <a href="#" class="upvote btn btn-default">?</a> <div class="post-content"> <h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3> <p> {{votes}} Votes, submitted by {{author}}, <a href="{{pathFor 'postPage'}}">{{commentsCount}} comments</a> {{#if ownPost}}<a href="{{pathFor 'postEdit'}}">Edit</a>{{/if}} </p> </div> <a href="{{pathFor 'postPage'}}" class="discuss btn btn-default">Discuss</a> </div></template>接下来,当用户点击按钮时调用服务器端的 upvote 方法://...Template.postItem.events({ 'click .upvote': function(e) { e.preventDefault(); Meteor.call('upvote', this._id); }});最后,我们回到 lib/collections/posts.js 文件,在其中加入一个服务器端方法来 upvote 帖子://...Meteor.methods({ post: function(postAttributes) { //... }, upvote: function(postId) { check(this.userId, String); check(postId, String); var post = Posts.findOne(postId); if (!post) throw new Meteor.Error('invalid', 'Post not found'); if (_.include(post.upvoters, this.userId)) throw new Meteor.Error('invalid', 'Already upvoted this post'); Posts.update(post._id, { $addToSet: {upvoters: this.userId}, $inc: {votes: 1} }); }});//...这个方法很清楚。我们做了些检查确保当前用户已经登录和帖子存在。然后检查用户并没有给帖子投过票,检查如果用户没有增加过帖子的投票分数我们将用户添加到 upvoters 集合中。最后一步我们使用了一些 Mongo 操作符。有很多操作符需要学习,但是这两个尤其有用: $addToSet 将一个 item 加入集合如果它不存在的话,$inc 只是简单的增加一个整型属性。用户界面微调如果用户没有登录或者已经投过票了,他就不能再投票了。我们需要修改 UI, 我们将用一个帮助方法根据条件添加一个 disabled CSS class 到 upvote 按钮。<template name="postItem"> <div clas

[1] [2] [3]  下一页


Meteor 投票