Blaze 是 Meteor 預設的前端框架,整合了 Meteor 的 Tracker 和 Minimongo,能夠隨著資料變動而自動更新使用者畫面,因此開發者不需要決定什麼時候去更新網頁元素,也不需要做 data-binding。
在 terminal 使用 meteor 的指令來創建空白的專案 meteor create 專案名稱 --bare
,如下:
$ meteor create my-app --bare
我們也可以去掉 --bare
來使用預設的方式創建專案,或是改成 --full
來創建檔案結構更完整的專案。這邊為了之後讓各位更了解 Meteor 的專案結構,所以加上 --bare
的參數。
建立完專案之後,會在目前的位置產生和專案名稱同名的資料夾,我們將這個專案跑起來:
$ cd my-app
$ meteor
看到空白的頁面是正常的,因為我們還沒有加入任何的檔案。
在專案中同時開發前端和後端,Meteor 要怎麼知道哪些程式碼屬於前端?哪些又屬於後端呢?
Meteor 會透過資料夾名稱來區分程式碼。因此我們先在專案目錄底下建立 client
和 server
兩個資料夾,之後只要是前端—要載入到瀏覽器的程式碼就放在 client
資料夾底下,而後端—要在伺服器執行的程式碼則放在 server
資料夾底下。
接著我們在 client
資料夾底下新建一個 main.html
,並且在裡面加上 <head>
和 <body>
的內容:
<!-- my-app/client/main.html -->
<head>
<title>My App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
</body>
存檔完之後就可以看到畫面跟著更新囉!
在開發的過程中,我們不需要停止執行 Meteor,只要專案目錄底下的檔案有任何的變動,都會經過重新編譯然後重啟環境,就能立刻看到程式改動的結果,實在是太方便啦!
要安裝 Meteor 的相關套件非常簡單,只要在 terminal 輸入 meteor add 套件名稱
,移除的話則是輸入 meteor remove 套件名稱
。所有安裝好的套件會記錄在 .meteor
資料夾底下的 packages
檔案裡。
我們這邊要移除預設的編譯套件 static-html
,並且安裝 blaze-html-templates
,它會幫我們編譯模板檔案、產生模板物件並且在執行的時候管理這些模板物件。
$ meteor remove static-html
$ meteor add blaze-html-templates
模板寫在 HTML 檔案裡,用 <template>
包起來然後模板的名稱寫在 name 屬性。例如定義一個名稱叫 hello 的模板:
<!-- my-app/client/hello.html -->
<template name="hello">
<div id="myDiv"></div>
</template>
我們可以在模板物件被產生的時候做一些事情,例如設定初始的資料。
只要在 Template.模板名稱.onCreated()
的括號裡頭傳入在模板物件被產生時要執行的 function 即可。
而要在 JS 檔案裡頭使用 Template
關鍵字,記得要引入 templating 套件,只要是 Meteor 自帶的套件都會在 meteor/...
底下。
// my-app/client/hello.js
import { Template } from 'meteor/templating';
Template.hello.onCreated(function() {
console.log('產生模板..');
// 建立一些初始屬性給這個模板物件,this 指的是 hello 本身這個模板物件
// 這邊我們先準備一個空的 timer 和數字預設為 0
this.timer = null;
this.number = 0;
});
更精確地來說是模板物件被放入 DOM 時,這個時候我們就可以去操作 template 中的網頁元素。
在 Template.模板名稱.onRendered()
的括號裡頭傳入在模板物件被使用時要執行的 function。
// my-app/client/hello.js
Template.hello.onRendered(function() {
console.log('顯示模板..');
// 操作網頁元素,this 指的就是本身 hello 這個模板物件
this.find('#myDiv').innerHTML = this.number;
// 設定 timer,每經過一秒鐘就將 #myDiv 中的數字加 1
this.timer = setInterval(() => {
this.number += 1;
this.find('#myDiv').innerHTML = this.number;
}, 1000);
});
模板物件可以使用 .find()
來尋找網頁元素,括號裡放 css selector,也可以使用 .findAll()
來尋找所有符合 selector 的網頁元素,或是使用 .$()
jQuery 選擇器來取得符合 selector 的網頁元素,不過要注意用 .$()
返回的是 jQuery 物件。
在 Template.模板名稱.onDestroyed()
的括號裡頭傳入在模板物件被使用時要執行的 function。
// my-app/client/hello.js
Template.hello.onDestroyed(function() {
console.log('摧毀模板..');
// 清除 timer
clearInterval(this.timer);
});
我們在 main.html
裡頭建立一個 <div>
:
<!-- my-app/client/main.html -->
<head>
<title>My App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<div id="hello"></div> <!-- 新增這一行,設定 id 以方便被選取 -->
</body>
接著新增 main.js
檔案。由於 <body>
也會被建立成一個模板物件,所以我們可以在 Template.body
被顯示時來插入 Template.hello
到剛剛建立的 <div>
裡,然後在經過五秒鐘之後將它移除:
// my-app/client/main.js
import { Blaze } from 'meteor/blaze';
import { Template } from 'meteor/templating';
Template.body.onRendered(function() {
// 將 hello 模板插入到 id 為 hello 網頁元素中 並且返回一個 view 物件
const helloView = Blaze.render(Template.hello, this.find('#hello'));
// 5秒鐘之後將此 view 物件移除
setTimeout(() => {
Blaze.remove(helloView);
}, 5000);
});
Spacebar 是搭配 Blaze 的模板語言,用法和 Handlebars 類似,程式碼簡潔可讀性高,學習曲線低,具有 reactivity。
在 Spaceboar 中使用模版的方式很簡單,這邊我們先把剛剛使用 Blaze 來 render 模板的程式碼註解掉:
// my-app/client/main.js
import { Template } from 'meteor/templating';
Template.body.onRendered(function() {
// 將 hello 模板插入到 id 為 hello 網頁元素中 並且返回一個 view 物件
// const helloView = Blaze.render(Template.hello, this.find('#hello'));
// 5秒鐘之後將此 view 物件移除
// setTimeout(() => {
// Blaze.remove(helloView);
// }, 5000);
});
再來修改 main.html
:
<!-- my-app/client/main.html -->
<head>
<title>My App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<div id="hello">{{> hello}}</div> <!-- 修改這一行 -->
</body>
並且修改 hello.js
的 onRendered()
的區塊:
// my-app/client/hello.js
Template.foo.onRendered(function() {
console.log('顯示模板..');
// 操作網頁元素,this 指的就是本身 foo 這個模板物件
this.find('#myDiv').innerHTML = this.number;
// 設定 timer,每經過一秒鐘就將 #myDiv 中的數字加 1
this.timer = setInterval(() => {
this.number += 1;
this.find('#myDiv').innerHTML = this.number;
}, 1000);
// 5秒鐘之後將自身的 view 物件移除
setTimeout(() => {
Blaze.remove(this.view);
}, 5000);
});
這樣也可以達到和使用 Blaze 同樣的效果喔!
Spacebar 的語法都是用 {{ }}
刮起來,我們可以透過 {{> 模板名稱}}
直接在模板中 render 另一個模板。Spacebar 的其他語法會在後續的章節介紹到。