MongoDB 為 Meteor 預設連接的資料庫,透過 Collection
來存取,但 Collection
不僅僅提供儲存與讀取資料等基本功能,還擁有 reactivity 的特性,進一步優化使用者體驗。為了實現 reactivity,資料庫可以同時存在於伺服器端與瀏覽器端。什麼?瀏覽器也有資料庫?沒錯!以下會進一步說明。
在 client
建立一個 Todos 的資料表,也就是 MongoDB 的 collection:
// my-app/client/todos.js
import { Mongo } from 'meteor/mongo';
const Todos = new Mongo.Collection();
export default Todos;
然後在 hello.js
中 import 這個 collection:
// my-app/client/hello.js
import Todos from './todos';
Meteor 的 Minimongo 套件實作了 MongoDB API,讓我們可以在 client 端建立一個 in-memory 的資料庫,並且對這個資料庫進行存取,還同時具有 reactivity 的效果。
MongoDB 的每一筆資料稱為 document,新增一筆 document 的方法很簡單:collection名稱.insert(document內容)
,而 document 內容其實就是一個 object。
我們試著建立一個輸入框,並且在按下 enter
時,將輸入框內的文字存成一筆資料,也就是 MongoDB 的 document,作法如下:
<!-- my-app/client/hello.html -->
<template name="hello">
<input type="text" id="myInput">
</template>
// my-app/client/hello.js
Template.hello.events({
'keyup #myInput'(event, templateInstance) {
if (event.keyCode === 13) {
Todos.insert({
text: event.currentTarget.value,
date: new Date(),
});
event.currentTarget.value = '';
}
},
});
不過我們現在還看不到存進資料庫的內容,接下來介紹如何讀取資料並且顯示。
讀取 document 的方法:collection名稱.find(selector)
,會回傳具有 reactivity 的 Collection.Cursor
,可以直接在模板中使用,其中 selector 是一個 object,用法請參考collections#selectors。
這邊我們試著將從輸入框存進去的資料全部顯示出來,只要資料庫的資料有任何變動,畫面都會呈現最新的資料。
<!-- my-app/client/hello.html -->
<template name="hello">
<input type="text" id="myInput">
<!-- 加入以下程式碼 -->
<ul>
{{#each todos}}
<li>
{{text}} - {{date}}
</li>
{{/each}}
</ul>
<!-- 以上 -->
</template>
// my-app/client/hello.js
Template.hello.events({
'keyup #myInput'(event, templateInstance) {
if (event.keyCode === 13) { // enter 的 keycode 是 13
Todos.insert({
text: event.currentTarget.value,
date: new Date(),
});
event.currentTarget.value = '';
}
},
});
// 加入以下程式碼
Template.hello.helpers({
todos() {
return Todos.find({});
},
});
// 以上
更新 document 的方法:collection名稱.update(selector, modifier)
,modifier 也是一個 object,用法請參考collections#modifiers。
我們新增一個可以更新時間的按鈕:
<!-- my-app/client/hello.html -->
<template name="hello">
<input type="text" id="myInput">
<ul>
{{#each todos}}
<li>
{{text}} - {{date}}
<!-- 加入以下程式碼 -->
<button class="updateButton">更新時間</button>
<!-- 以上 -->
</li>
{{/each}}
</ul>
</template>
// my-app/client/hello.js
Template.hello.events({
'keyup #myInput'(event, templateInstance) {
if (event.keyCode === 13) {
Todos.insert({
text: event.currentTarget.value,
date: new Date(),
});
event.currentTarget.value = '';
}
},
// 加入以下程式碼
'click .updateButton'(event, templateInstance) {
Todos.update({
_id: this._id, // this 參考到該筆 document
}, {
$set: { date: new Date() },
});
},
// 以上
});
Template.hello.helpers({
todos() {
return Todos.find({});
},
});
刪除 document 的方法很簡單:collection名稱.remove(selector)
。
我們新增一個可以刪除的按鈕:
<!-- my-app/client/hello.html -->
<template name="hello">
<input type="text" id="myInput">
<ul>
{{#each todos}}
<li>
{{text}} - {{date}}
<button class="updateButton">更新時間</button>
<!-- 加入以下程式碼 -->
<button class="deleteButton">刪除</button>
<!-- 以上 -->
</li>
{{/each}}
</ul>
</template>
// my-app/client/hello.js
Template.hello.events({
'keyup #myInput'(event, templateInstance) {
if (event.keyCode === 13) {
Todos.insert({
text: event.currentTarget.value,
date: new Date(),
});
event.currentTarget.value = '';
}
},
'click .updateButton'(event, templateInstance) {
Todos.update({
_id: this._id, // this 參考到該筆 document
}, {
$set: { date: new Date() },
});
},
// 加入以下程式碼
'click .deleteButton'(event, templateInstance) {
Todos.remove({ _id: this._id });
},
// 以上
});
Template.hello.helpers({
todos() {
return Todos.find({});
},
});
以上介紹了 Collection
在瀏覽器端的使用,基本上與在伺服器端的用法差不多,最大的差異在於瀏覽器端的 Collection
在網頁重新載入時就會被清除,而在伺服器端的 Collection
則會保存在本地端的 MongoDB,我們是否可以透過伺服器端將資料永久保存,又同時享有瀏覽器端 reactivity 的特性?答案是可以的!明天將會深入介紹 Collection
,敬請期待!