昨天介紹了 .onCreated()
.onRendered()
.onDestroyed
的使用方式與呼叫時機,今天要介紹如何使用 .events()
和 .helpers()
並且搭配 ReactiveVar 實現 reactivity。
目前我們透過 hello.js
中的這一行 this.find('#myDiv').innerHTML = this.number;
用命令式(imperativate)的方式來主動更新 div
中的數字,現在試著來改用宣告式(declaritive)的方式來注入數字到到 div
中。
.helpers()
注入資料到模板中我們可以宣告 helpers object 來幫助我們在模板中注入資料。只要在 Template.模板名稱.helpers()
的括號裡頭傳入 helpers object 即可。
首先我們在 hello.js
移除掉 this.find('#myDiv').innerHTML = this.number;
這兩行:
然後在 hello.js
中新增:
// my-app/client/hello.js
Template.hello.helpers({
myNumber() {
return Template.instance().number;
},
});
便可以在 hello.html
透過 Spacebar 使用 helper:
<!-- my-app/client/hello.html -->
<template name="hello">
<div id="myDiv">{{myNumber}}</div> <!-- 加入 {{myNumber}} -->
</template>
我們來看看網頁顯示的結果,咦?數字怎麼停在0沒有增加呢?因為 helper 必須依賴於具有 reactivity 的資料才會自動更新,雖然 myNumber
返回了我們一開始預設給模板的數字,但是這個數字不具有 reactivity,即使有改動也不會觸發 myNumber
重新執行。
因此,我們必須使用 ReactiveVar。
ReactiveVar
建立 reactivity data在 hello.js
中引入 ReactiveVar
,並且將原先的 number
改使用 ReactiveVar
來建立:
// my-app/client/hello.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
Template.hello.onCreated(function() {
console.log('產生模板..');
this.timer = null;
this.number = new ReactiveVar(0); // 建立具 reactivity 的變數,預設值為 0
});
Template.hello.onRendered(function() {
console.log('顯示模板..');
this.timer = setInterval(() => {
const number = this.number.get(); // 透過 .get() 可以取得目前的值
this.number.set(number + 1); // 透過 .set() 可以指派新的值
}, 1000);
setTimeout(() => {
Blaze.remove(this.view);
}, 5000);
});
Template.hello.onDestroyed(function() {
console.log('摧毀模板..');
clearInterval(this.timer);
});
Template.hello.helpers({
myNumber() { // 依賴於具 reactivity 的變數,當 number 的值改變,這個 helper 會重新執行
return Template.instance().number.get();
},
});
經過這樣的修改,只要 number
有任何變動,網頁畫面上的數字就會同步更新!
helper
helper
可以接受參數,例如:
// my-app/client/hello.js
Template.hello.helpers({
myNumber(initialValue) {
return Template.instance().number.get() + initialValue;
},
});
而在 Spacebar 中傳入參數的方式很簡單:
<!-- my-app/client/hello.html -->
<template name="hello">
<div id="myDiv">{{myNumber 5}}</div> <!-- 以空格為間隔,傳入參數 -->
</template>
這樣數字就會從5開始往上增加囉!
.events()
處理網頁互動為了展示網頁互動的範例,我們先把 timer
的部分移除掉:
// my-app/client/hello.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
Template.hello.onCreated(function() {
console.log('產生模板..');
this.number = new ReactiveVar(0); // 建立具 reactivity 的變數,預設值為 0
});
Template.hello.onRendered(function() {
console.log('顯示模板..');
});
Template.hello.onDestroyed(function() {
console.log('摧毀模板..');
});
Template.hello.helpers({
myNumber(initialValue) {
return Template.instance().number.get() + initialValue;
},
});
接著,在 Template.模板名稱.events()
的括號裡頭傳入 event map。event map 透過 object 來定義,由屬性來指定要處理的事件,屬性的值則是處理該事件的 function,而這個 function 具有兩個參數,第一個是事件物件,第二個則是所屬的模板物件。
再來,在 hello.html
新增一個按鈕:
<!-- my-app/client/hello.html -->
<template name="hello">
<div id="myDiv">{{myNumber}}</div>
<bbutton id="myButton">加一</button>
</template>
然後在 hello.js
中新增:
// my-app/client/hello.js
Template.hello.events({
// 當 id 為 myButton 的元素被點擊時,將 number 加 1
'click #myButton'(event, templateInstance) {
const originalValue = templateInstance.number.get();
templateInstance.number.set(originalValue + 1);
},
});
現在只要點擊按鈕,網頁上的數字就會加1囉!
各位對於 .events()
和 .helpers()
以及 ReactiveVar
的用法有不清楚或是想更近一步了解的歡迎留言討論喔!明天將會介紹 Spacebar 與 .helpers()
進階搭配用法。