2014-09-28 55 views
9

我正在努力创建一个用户配置文件页面,使用铁路路由器,它位于localhost:3000/:username。在个人资料页应具有以下特点:流星:铁路用户配置文件页面

  • 公共视图 - 任何人都可以看到该用户
  • 个人观点基本信息 - 如果客户机访问自己的个人资料页,而登录的,他或她的显示敏感用户数据并且它们具有编辑功能
  • 加载视图 - 正在提取用户配置文件数据时,显示加载屏幕
  • 未找到视图 - 如果在URL中输入了无效用户名,则返回未找到页。

公共视图和私人视图应该存在于相同的 URL路径中。根据客户的凭据,他们看到一个或另一个没有重定向到不同的页面。未找到的页面也不应该重定向,这样,如果输入无效的用户名,用户仍然可以在浏览器URL栏中看到无效的URL。

我router.js文件:

this.route('profile', { 
    controller: 'ProfileController', 
    path: '/:username' 
    }); 

ProfileController,我想凑如下:

  • onBeforeAction - 显示加载屏幕;确定用户名是否存在(又名如果URL是有效的)
    • 要么显示没有找到视图,专用配置文件,或公开档案
  • waitOn - 等待删除加载屏幕
  • 之前被检索 username的数据
  • onAfterAction - 删除加载屏幕

谢谢!

回答

12

幸运的是,您所寻找的每一个特征都可以在插件中烘焙,因此您甚至不必在定义自己的钩子时进行深入研究。

请注意,我正在使用iron:[email protected],这对于跟上最新内容很重要,目前只有两个小问题,我希望能很快得到解决。

让我们从以用户名作为参数的用户配置文件发布开始。

server/collections/users.js

Meteor.publish("userProfile",function(username){ 
    // simulate network latency by sleeping 2s 
    Meteor._sleepForMs(2000); 
    // try to find the user by username 
    var user=Meteor.users.findOne({ 
     username:username 
    }); 
    // if we can't find it, mark the subscription as ready and quit 
    if(!user){ 
     this.ready(); 
     return; 
    } 
    // if the user we want to display the profile is the currently logged in user... 
    if(this.userId==user._id){ 
     // then we return the corresponding full document via a cursor 
     return Meteor.users.find(this.userId); 
    } 
    else{ 
     // if we are viewing only the public part, strip the "profile" 
     // property from the fetched document, you might want to 
     // set only a nested property of the profile as private 
     // instead of the whole property 
     return Meteor.users.find(user._id,{ 
      fields:{ 
       "profile":0 
      } 
     }); 
    } 
}); 

让我们继续配置文件模板,没有什么太花哨这里,我们会显示用户名作为公共数据,如果我们正在查看的专用配置文件,显示该用户的真实姓名,我们假设存储在profile.name

client/views/profile/profile.html

<template name="profile"> 
    Username: {{username}}<br> 
    {{! with acts as an if : the following part won't be displayed 
     if the user document has no profile property}} 
    {{#with profile}} 
     Profile name : {{name}} 
    {{/with}} 
</template> 

然后,我们需要定义在全球路由器配置纵断面图的路线:

lib/router.js

// define the (usually global) loading template 
Router.configure({ 
    loadingTemplate:"loading" 
}); 

// add the dataNotFound plugin, which is responsible for 
// rendering the dataNotFound template if your RouteController 
// data function returns a falsy value 
Router.plugin("dataNotFound",{ 
    notFoundTemplate: "dataNotFound" 
}); 

Router.route("/profile/:username",{ 
    name:"profile", 
    controller:"ProfileController" 
}); 

注意iron:router现在需要你定义路径和路由控制器在共享目录中(通常这是lib/ dir at t他是您的项目的根源)可用于客户端和服务器。

现在到了最棘手的部分,该ProfileController定义:

lib/controllers/profile.js

ProfileController=RouteController.extend({ 
    template:"profile", 
    waitOn:function(){ 
     return Meteor.subscribe("userProfile",this.params.username); 
    }, 
    data:function(){ 
     var username=Router.current().params.username; 
     return Meteor.users.findOne({ 
      username:username 
     }); 
    } 
}); 

iron:router检测到您在使用RouteControllerwaitOn现在会自动添加默认loading挂钩负责用于在订阅尚未准备好时呈现loadingTemplate

我现在要谈的是我在回答开始时提到的两个小错误。

首先,官方iron:router指南(你一定要读)http://eventedmind.github.io/iron-router/提到,你应该传递给dataNotFound插件选项的名称为dataNotFoundTemplate但截至28-09-2014这是不行的,你需要要使用传统名称notFoundTemplate,这可能会在几天内得到解决。

这同样适用于我的data功能的控制器代码:我已经使用了反直觉的语法Router.current().params访问路由参数时,通常this.params会一直恰当的规则语法。这是另一个尚未解决的问题。 https://github.com/EventedMind/iron-router/issues/857

+0

非常感谢您的帮助! Meteor.publish()函数仅用于发布有关用户的选择数据。 – 2014-09-29 03:56:09

+0

这是一篇很棒的文章,谢谢。值得注意的是,未来的读者将无法使用安装了[audit-argument-checks](https://atmospherejs.com/meteor/audit-argument-checks)软件包的代码。 – AlecRust 2015-10-27 20:24:48

+0

建议编辑来解决这个问题。 – AlecRust 2015-10-27 20:40:04