看了一上午,感觉这确实比所谓传统的APP开发,有很多不一样的地方。

记录下来:

simple-todos.css

/* CSS declarations go here */
/* CSS declarations go here */
body {
  font-family: sans-serif;
  background-color: #315481;
  background-image: linear-gradient(to bottom, #315481, #918e82 100%);
  background-attachment: fixed;

  position: absolute;
  top:;
  bottom:;
  left:;
  right:;

  padding:;
  margin:;

  font-size: 14px;
}

.container {
  max-width: 600px;
  margin: 0 auto;
  min-height: 100%;
  background: white;
}

header {
  background: #d2edf4;
  background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%);
  padding: 20px 15px 15px 15px;
  position: relative;
}

#login-buttons {
  display: block;
}

h1 {
  font-size: 1.5em;
  margin:;
  margin-bottom: 10px;
  display: inline-block;
  margin-right: 1em;
}

form {
  margin-top: 10px;
  margin-bottom: -10px;
  position: relative;
}

.new-task input {
  box-sizing: border-box;
  padding: 10px 0;
  background: transparent;
  border: none;
  width: 100%;
  padding-right: 80px;
  font-size: 1em;
}

.new-task input:focus{
  outline:;
}

ul {
  margin:;
  padding:;
  background: white;
}

.delete {
  float: right;
  font-weight: bold;
  background: none;
  font-size: 1em;
  border: none;
  position: relative;
}

li {
  position: relative;
  list-style: none;
  padding: 15px;
  border-bottom: #eee solid 1px;
}

li .text {
  margin-left: 10px;
}

li.checked {
  color: #888;
}

li.checked .text {
  text-decoration: line-through;
}

li.private {
  background: #eee;
  border-color: #ddd;
}

header .hide-completed {
  float: right;
}

.toggle-private {
  margin-left: 5px;
}

@media (max-width: 600px) {
  li {
    padding: 12px 15px;
  }

  .search {
    width: 150px;
    clear: both;
  }

  .new-task input {
    padding-bottom: 5px;
  }
}

simple-todos.html

<head>
  <title>Todo List</title>
</head>

<body>
  <div class="container">
    <header>
      <h1>Todo List({{incompleteCount}})</h1>
      <lable class="hide-completed">
        <input type="checkbox" checked="{{hideCompleted}}" />
        Hide Completed Tasks
      </lable>
      {{> loginButtons}}
      {{#if currentUser}}
      <form class="new-task">
        <input type="text" name="text" placeholder="Type to add new tasks" />
      </form>
      {{/if}}
    </header>

    <ul>
      {{#each tasks}}
        {{> task}}
      {{/each}}
    </ul>
  </div>
</body>

<template name="task">
  <li class="{{#if checked}}checked{{/if}} {{#if private}}private{{/if}}">
    <button class="delete">&times;</button>
    <input type="checkbox" checked="{{checked}}" class="toggle-checked" />
    {{#if isOwner}}
      <button class="toggle-private">
        {{#if private}}
          Private
        {{else}}
          Public
        {{/if}}
      </button>
    {{/if}}
    <span class="text"><strong>{{username}}</strong> - {{text}}</span>
  </li>
</template>

simple-todos.js

Tasks = new Mongo.Collection("tasks");

if (Meteor.isServer) {
  Meteor.publish("tasks", function() {
    return Tasks.find( {
     $or: [
        { private: {$ne: true }},
        { owner: this.userId }
        ]
    });
  });
}

if (Meteor.isClient) {
  Meteor.subscribe("tasks");

  Template.body.helpers({
    tasks: function(){
      if (Session.get("hideCompleted")) {
        return Tasks.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
        }else{
          return Tasks.find({}, {sort: {createdAt: -1}});
        }
      },
      hideCompleted: function(){
        return Session.get("hideCompleted");
      },
      incompleteCount: function(){
        return Tasks.find({checked: {$ne: true}}).count();
      }
  });

  Template.body.events({
    "submit .new-task": function (event) {
    event.preventDefault();

    var text = event.target.text.value;

    Meteor.call("addTask", text);
    event.target.text.value = "";
    },
    "change .hide-completed input": function(event){
      Session.set("hideCompleted", event.target.checked);
    }
  });

  Template.task.helpers({
    isOwner: function() {
      return this.owner === Meteor.userId();
    }
  });

  Template.task.events({
    "click .toggle-checked": function(){
      Meteor.call("setChecked", this._id, ! this.checked);
    },
    "click .delete": function(){
      Meteor.call("deleteTask", this._id);
    },
    "click .toggle-private": function() {
      Meteor.call("setPrivate", this._id, ! this.private);
    }
  });
  Accounts.ui.config({
    passwordSignupFields: "USERNAME_ONLY"
  });
}

Meteor.methods({

  addTask: function(text) {
    if (! Meteor.userId()) {
      throw new Methor.Error("not-authorized");
    }

    Tasks.insert({
      text: text,
      createdAt: new Date(),
      owner: Meteor.userId(),
      username: Meteor.user().username
    });
  },

  deleteTask: function(taskId) {
    var task = Tasks.findOne(taskId);
    if (task.private && task.owner !== Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    Tasks.remove(taskId);
  },

  setChecked: function(taskId, setChecked) {
    var task = Tasks.findOne(taskId);
    if (task.private && task.owner !== Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    Tasks.update(taskId, {$set: { checked: setChecked} });
  },

  setPrivate: function(taskId, setToPrivate) {
    var task = Tasks.findOne(taskId);
    if (task.owner !== Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }
    Tasks.update(taskId, { $set: { private: setToPrivate } });
  }
});

截图:

来看看Meteor的功能的更多相关文章

  1. JavaScript 开发者的 10 款必备工具

    JavaScript,一种所有主流浏览器都支持的语言,是开发基于浏览器的 Web 应用程序的主力,几乎每年都会受到来自众多开发人员的关注.自然地,框架和库的生态系统自然而然地围绕着 JavaScrip ...

  2. Meteor+AngularJS:超快速Web开发

        为了更好地描述Meteor和AngularJS为什么值得一谈,我先从个人角度来回顾一下这三年来WEB开发的变化:     三年前,我已经开始尝试前后端分离,后端使用php的轻量业务逻辑框架.但 ...

  3. Meteor全栈开发平台 - 不仅仅是前端

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .网站上有对应每一 ...

  4. 怎么评价Facebook的Relay框架?Meteor.js 是什么?

    http://www.zhihu.com/question/34531232?rf=34500201 Meteor.js 是什么? 作者:陈天链接:http://www.zhihu.com/quest ...

  5. Meteor 之 数据的发布于订阅(Publish and subscribe )

    发布和订阅 发布(Publication)和订阅(Subscription)是 Meteor 的最基本最重要的概念之一,但是如果你是刚刚开始接触 Meteor 的话,也是有些难度的. 这已经导致不少误 ...

  6. Meteor 简介

    简介 先来活动一下大脑.假设你坐在电脑面前,在两个窗口中打开同一个文件夹. 在其中一个窗口中删除一个文件,另一个窗口中的这个文件会消失吗? 不用实际操作你也知道肯定会消失的.在本地文件系统中的操作,不 ...

  7. Meteor:用户账号管理添加密码和微博weibo账号系统支持

    Meteor账户系统构建与accounts-base包之上,并为publish和methods提供userId的顶层支持.核心包提供的功能有:数据库中的用户记录支持:额外的包提供密码安全验证:第三方登 ...

  8. Meteor全栈开发平台

    Meteor全栈开发平台 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonno ...

  9. javascript功能插件大集合,写前端的亲们记得收藏

    伯乐在线已在 GitHub 上发起「JavaScript 资源大全中文版」的整理.欢迎扩散.欢迎加入. https://github.com/jobbole/awesome-javascript-cn ...

随机推荐

  1. C#根据WSDL文件生成WebService服务端代码

    转自:http://www.cnblogs.com/liyi93/archive/2012/01/30/2332320.html 虽然现在已经进入了.NET FrameWork 4.0的时代,WebS ...

  2. ASP长文章分页的两个方法,函数

    '按标识手动分页 function manualPage(str) pages=request.QueryString("page") contentstr=split(str,& ...

  3. 我的MFC学习之路(一)

    因为项目需求,我开始应用MFC写程序.具体接触MFC的时间大概也有两个月了.现在的水平算是刚刚踏入了MFC大门的半只脚.目前能基本使用MFC Class Wizard,可以根据实例仿照完成需求,小范围 ...

  4. -exec和|xargs

    注意xargs会被空格割裂,所以遇到带有空格的文件名就不好办了,解决方法是使用-print0 例如:删除.目录下30天之前的.png文件 -type f -name rm 或者使用-exec:删除.目 ...

  5. c/c++中const使用总结(金典)

    原文地址:http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 个人总结:          (1)const只对它左 ...

  6. 【JAVA】抽象类

    一.什么是抽象类 用abstract修饰的类就是抽象类.抽象类中可以有用abstract修饰的抽象方法,也可以没有抽象方法. 二.为什么要设计抽象类 在某些情况下,某个父类只是知道其子类应该包含怎样的 ...

  7. 12天学好C语言——记录我的C语言学习之路(Day 8)

    12天学好C语言--记录我的C语言学习之路 Day 8: 从今天开始,我们获得了C语言中很有力的一个工具,那就是函数.函数的魅力不仅于此,一个程序到最后都是由众多函数组成的,我们一定要用好函数,用熟练 ...

  8. Windows下查询进程、端口

    PID --> 端口号netstat -ano | findstr 8244 端口号 --> PIDnetstat -aon|findstr "11211" PID - ...

  9. mysql学习笔记3

    要用php+mysql 首先要配置环境.现在要先下载wamp(Windows下的Apache+Mysql/MariaDB+Perl/PHP/Python).直接安装就行 可以点下一步的就点下一步,直至 ...

  10. 暑假集训(3)第三弹 -----Til the Cows Come Home(Poj2387)

    题意梗概:据说母牛在产奶的时候,因为奶量太充足,希望有人帮它挤奶,它回家就很快.我们便能喝到鲜美的 牛奶,不过,贫奶季节却大不相同,它会懒洋洋的在大草原上晃来晃去的晒太阳,而不会想到马上回家,这可不 ...