學了一段時間Meteor以後,着手作一個APP,關於時間管理的,取名 Next。css
Get things done , and do Nexthtml
同時,把開發過程儘量詳細的記錄下來,分享給有須要的同窗。前提是你有一些Meteor基礎,至少要了解各類基礎概念:集合、發佈訂閱、method、package等。git
若是以前沒了解過Meteor,能夠快速過一遍meteor教程github
Next 0.0.1版的目標是任務列表,四象限展現,能夠新增、修改和刪除任務。最後的效果以下圖:(後面會慢慢提高她的顏值)shell
新建項目數據庫
meteor create next
進入項目目錄,並啓動api
cd next meteor
打開瀏覽器,訪問 http://localhost:3000,會看到自動生成的demo。瀏覽器
刪除自動生成的文件,並創建項目目錄結構app
rm next.css next.html next.js mkdir client public server lib
添加路由包iron:router
;因爲後面會用coffeescript寫,因此還要加上coffeescript
包框架
meteor add iron:router meteor add coffeescript
基本的骨架都有了,能夠開始敲代碼了。在client文件夾中新建router.coffee,內容以下:
Router.route('/', -> @render("Home") )
瀏覽器中顯示了一條錯誤信息:找不到home模板
Couldn't find a template named "Home" or "home". Are you sure you defined it?
接下來定義home模板,在client文件夾中新建templates文件夾,在裏面新建home.html,內容以下:
<template name="home"> welcome to home </template>
此時瀏覽器顯示:
welcome to home
在lib文件夾中新建collections文件夾,在裏邊新建task.coffee,內容以下:
@Task = new Mongo.Collection('task')
Task collection就對應數據庫裏的一張表,根據需求,初步設計了下面幾個字段:
name 任務名稱 important 是否重要 urgent 是否緊急 complete 是否完成 create_time 建立時間 complete_time 完成時間
爲了方便調試,要製造一些初始數據。在server文件夾下新建init_data.coffee
Meteor.startup(-> if Task.find().count() is 0 Task.insert name: "晚上和妹子去吃飯" important: true urgent: true Task.insert name: "翻譯Meteor文檔" important: true urgent: false Task.insert name: "看完《悲傷與理智》" important: false urgent: false Task.insert name: "給手機充話費" important: false urgent: true )
解釋下上面的代碼:每次啓動Meteor的時候,查詢任務條數,若是條數爲零,則插入四條初始數據。
以後打開數據庫看看是否插入成功,打開一個新的命令行窗口,切換到項目根目錄:啓動mongo shell
meteor mongo
查詢任務條數:
db.task.find().count() 1
明明插入了四條,爲何只查詢到一條呢?由於在編碼過程當中,Meteor會監測源碼的變化並自動從新運行,當剛寫完第一條插入語句,Meteor可能就從新運行了,此時任務條數爲1,後面的插入就不會再執行了。
接下來須要control+c
中止Meteor進程,重置並重啓
meteor reset meteor
再次到mongo shell中查詢任務條數:
db.task.find().count() 4
能夠經過Helper給模板增長動態數據,在templates文件夾中新建home.coffee,內容以下:
Template.home.helpers taskList: -> Task.find()
修改home.html
<template name="home"> {{#each taskList}} {{name}} {{/each}} </template>
瀏覽器顯示
晚上和妹子去吃飯 翻譯Meteor文檔 看完《悲傷與理智》 給手機充話費
這裏有一個問題須要思考:爲何客戶端沒有進行任何請求,數據就從服務端到了客戶端?
這是由於:爲了簡化開發,每一個新建的Meteor項目都會包含一個autopublish包,這個包會把全部集合裏的文檔自動發佈到每個鏈接上的客戶端。爲了可以精確地控制文檔的發佈,須要移除autopublish,而後手動進行發佈與訂閱
meteor remove autopublish
此時瀏覽器中顯示頁面爲空。接下來,在server目錄下新建publish.coffee
Meteor.publish('tasks', -> Task.find() )
在client目錄下新建subscribe.coffee
Meteor.subscribe('tasks')
這時候瀏覽器中的頁面數據就又都回來了。
項目用到了yahoo的pure css框架:點我下載
在client文件夾下新建style文件夾,將pure-min.css放進去,而後再新建一個todo.css
將home.html 的佈局修改成四象限
<template name="home"> <div class="pure-g main-container"> <div class="pure-u-1-2 task-list-wrapper task-list-wrapper-tl"> <div class="task-list-title"> 重要&緊急 </div> <ul class="task-list"></ul> </div> <div class="pure-u-1-2 task-list-wrapper task-list-wrapper-tr"> <div class="task-list-title"> 重要&不緊急 </div> <ul class="task-list"></ul> </div> <div class="pure-u-1-2 task-list-wrapper task-list-wrapper-bl"> <div class="task-list-title"> 不重要&緊急 </div> <ul class="task-list"></ul> </div> <div class="pure-u-1-2 task-list-wrapper task-list-wrapper-br"> <div class="task-list-title"> 不重要&不緊急 </div> <ul class="task-list"></ul> </div> </div> </template>
在todo.css 裏增長樣式
html, body { height: 100%; } .main-container { height: 100%; } .task-list-wrapper { height: 50%; } .task-list-wrapper-tl { background-color: #ffaeae; } .task-list-wrapper-tr { background-color: #56baec; } .task-list-wrapper-bl { background-color: #ffec94; } .task-list-wrapper-br { background-color: #b4d8e7; }
接下來修改home模板的Helper
Template.home.helpers taskListTL: -> Task.find({important: true, urgent: true}) taskListTR: -> Task.find({important: true, urgent: false}) taskListBL: -> Task.find({important: false, urgent: true}) taskListBR: -> Task.find({important: false, urgent: false})
修改home.html,將對應的Helper展現到對應的板塊,例如:
<div class="pure-u-1-2 task-list-wrapper task-list-wrapper-tl"> <div class="task-list-title"> 重要&緊急 </div> <ul class="task-list"> {{#each taskListTL}} <li>{{name}}</li> {{/each}} </ul> </div>
此時效果以下圖:
修改home.html,給每一個版塊增長一個form表單,用於新增任務
<div class="pure-u-1-2 task-list-wrapper task-list-wrapper-tl"> <div class="task-list-title"> 重要&緊急 </div> <form class="pure-form form-create-task"> <input class="hidden" type="text" name="type" value="tl"/> <input class="pure-input-1" name="name" type="text"/> <button class="hidden" type="submit"></button> </form> <ul class="task-list"> {{#each taskListTL}} <li>{{name}}</li> {{/each}} </ul> </div>
表單裏有一個隱藏的輸入框,用於標識任務的類別,分別是:tl
,tr
,bl
,br
。
接下來,須要讓模板監聽表單的提交事件,並作處理。
在home.coffee 中增長:
Template.home.events 'submit .form-create-task': (e)-> e.preventDefault() $form = $(e.currentTarget) task = name: $form.find('input[name=name]').val() create_time: new Date() important: false urgent: false type = $form.find('input[name=type]').val() switch type when 'tl' task.important = true task.urgent = true when 'tr' then task.important = true when 'bl' then task.urgent = true console.log task Task.insert(task) $form.find('input[name=name]').val('')
首先阻止表單的默認提交,而後從表單中提取所需值,構建一個task
對象,經過Task.insert()
插入到數據庫,而後清空表單。
在瀏覽器中測試沒有問題,新增任務的功能就完成了。
修改home.html,修改任務列表爲:
<ul class="task-list"> {{#each taskListTL}} <li class="task-item" data-task-id="{{_id}}"> <div class="task-name" contenteditable="true">{{name}}</div> </li> {{/each}} </ul>
修改home.coffee,監聽.task-name
上的回車事件:
'keypress .task-name': (e)-> $el = $(e.currentTarget) taskId = $el.parent().attr('data-task-id') if e.keyCode is 13 taskName = $el.text() Task.update({_id: taskId}, {$set: {name: taskName}}) $el.blur() e.preventDefault()
瀏覽器中測試經過。
修改home.html,修改任務列表爲:
<ul class="task-list"> {{#each taskListTL}} <li class="task-item" data-task-id="{{_id}}"> <div class="task-name" contenteditable="true">{{name}}</div> <span>×</span> </li> {{/each}} </ul>
修改todo.css,調整樣式:
.task-item { position: relative; line-height: 25px; } .delete-task { position: absolute; top: 0px; right: 10px; cursor: pointer; } .delete-task:hover { color: #dd3023; }
修改home.coffee,綁定刪除按鈕的點擊事件:
'click .delete-task': (e)-> $el = $(e.currentTarget) taskId = $el.parent().attr('data-task-id') Task.remove({_id: taskId})
至此,Next 0.0.1 版本的需求就基本完成了。就是樣式醜了些,先不要在乎這些細節啦。後面再優化嘍。
原文地址:http://zicai.github.io/lessons/2015/06/22/meteor-in-action-next-0.0.1/