METEOR

Made By Alex Wang

Meteor是什麼

  • 官網: https://www.meteor.com/
  • 即時更新
  • 適合拿來做留言板、待辦事項列表(todo list)

Install Meteor

  • Mac or Linux版
  • 打開terminal
  • 輸入:curl https://install.meteor.com/ | sh
  • Windows版(非官方)
  • http://win.meteor.com/

Create app

meteor create /資料夾名稱/

~ 然後進入資料夾 ~

cd /資料夾名稱/
meteor

在你的資料夾裡會有3個檔案

  • /資料夾名稱/.js
  • /資料夾名稱/.html
  • /資料夾名稱/.css

以及一個meteor的內部文件

  • .meteor

Run App

在meteor建立的資料夾裡,在terminal輸入

meteor

只要你的語法沒有錯誤,meteor檔案沒有受損,meteor就會在localhost:3000上run你的程式喔

javascript裡...

if (Meteor.isClient) {                //如果是使用者,指令如下
  // counter starts at 0
  Session.setDefault("counter", 0);

  Template.hello.helpers({
    counter: function () {
      return Session.get("counter");
    }
  });

  Template.hello.events({
    'click button': function () {
      // increment the counter when button is clicked
      Session.set("counter", Session.get("counter") + 1);
    }
  });
}

if (Meteor.isServer) {                //伺服器則是執行這裡的指令
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

Templates

meteor在解析html文件的時候,會辨識3個頂級標籤

  1. head
  2. body
  3. template

那麼,template是什麼呢?

簡單來說,就是模板。

什麼是Template?

首先,不能吃。

模板(Template)主要是代替你做"重複的工作"。

也就是當一件事(例如相同格式的留言)需要被顯示多次以上,甚至是依使用者而定(未知個數)的情況下,就可以使用模板。

怎麼使用?

首先,一個template標籤。

<template name="hello">
    <!--your code(template)-->
</template>

然後在body裡面引入

(語法為{{> template的名稱}})。

<body>
    <!--your code-->
    <!--引入template-->
    {{> hello}}
</body>

<template name="hello">
    <!--your code(template)-->
</template>

helpers

可以透過在javascript裡面定義helpers來傳遞資料到html文件裡

if (Meteor.isClient) {
    Template.body.helpers({
        x: "X",
        y: "Y",
    });
}

Template.templateName就是在js裡面指向html的template的方法喔!

而Template.body.helper就是指向<body>這個區塊。並透過其中的定義,傳遞資料到html。

Template.body.helpers

//javascript
if (Meteor.isClient) {
    Template.body.helpers({
        x: "X",
        y: "Y",
    });
}
<!--html-->
<body>
{{x}}  //會顯示字串X
{{y}}  //會顯示字串Y
</body>

在template.body.helpers裡面定義,需要一組key : value,而在html的body裡面輸入

{{key}}

會顯示

value的值

helpers裡面可以是一個字串,一個array,或是一個function

if (Meteor.isClient) {
  Template.body.helpers({
    tasks: [
      { text: "This is task 1" },
      { text: "This is task 2" },
      { text: "This is task 3" }
    ]
  });
}

如果是以上這種情形,則需在body裡面輸入

<body>
    {{#each tasks}}
        {{text}}
    {{/each}}
</body>

each就是"對於tasks裡的每個text",然後在each裡面一樣輸入{{text}},就會跑出每個text對應的value喔!最後記得要結束掉each

Template + helpers

<body>
    {{#each tasks}}
        {{> task}}
    {{/each}}
</body>
<template name="task">
    <p>{{text}}</p>
</template>

each裡面放引入template的指令,然後在template裡面放property就好囉~

Collections

  • 儲存永久性的data
  • 自動更新

new 一個Collection

MyCollection = new Mongo.Collection("my-collection");

透過helpers顯示Collection裡的data

Template.body.helpers({
    tasks : function() {
        return MyCollection.find({});
    }
});

forms and events 

新增一個form到html裡面讓使用者輸入,作為用戶端與Collection的溝通橋樑

<form class="new-task">
    <input type="text" name="text" />
</form>

而當提交(submit)表單時,需要一個事件處理,所以在javascript裡面輸入

Template.body.event

並在裡面輸入要觸發事件&函式執行

forms and events 

Template.body.events({
  "submit .new-task": function (event) {
    // 當class為new-task的form被submit時,此函數便執行

    var text = event.target.text.value; //input裡面的value

    MyCollection.insert({
      text: text,                                     //將text(input裡的值)作為value,對應到名為text的key
      createdAt: new Date()                // 現在時間
    });

    event.target.text.value = "";        //清空表格

    return false;                                 //防止函式重複執行
  }
});
  1. text為此事件的目標的text的值
  2. 把text和現在時間塞到Collection裡
  3. 清空form
  4. 預防此function重複執行

回到我們的helpers~~

既然Collection裡面有東西了,那要如何在前端顯示呢?

<body>
    {{#each MyCollection}}    <!--每個MyCollection裡的東西-->
        {{> text}}                        <!--引入template-->
    {{/each}}                            <!--結束each敘述-->
</body>
<template name="text">
    <p>{{text}}</p>                <!--輸出key為text的value-->
</template>

在MyCollection這個集合裡面,對於每對key: value

顯示key為text的value

update and remove

"更新"&"移除"Collection裡的data

update:

MyCollection.update(data._id, {$set: {property: value}});

remove

MyCollection.remove(data._id);

在Collection中,每組data都有一個屬於自己獨特的"._id", 將這個._id對應的value刪掉,該筆data也會消失。

先在html裡面增加幾個標籤吧

<body>
    <ul>
        {{#each MyCollection}}    
            {{> text}}                        
        {{/each}}                            
    </ul>
</body>
<template name="text">
    <li>
        <button class="btn">delete</button>    <!--按鈕-->

        <input type="checkbox"  checked="{{checked}}" class="ckd" />    <!--勾選框-->

        <p>{{text}}</p>
    </li> 
</template>

新增了勾選框(checkbox)和按鈕(button)

events !!!!

這次一樣要透過events來溝通Collection和客戶端的介面(checkbox&button),但是templateName變成了text喔!

Template.text.events({
    'click .btn' : function() {
        MyCollection.remove(this._id);    //移除遭點擊按鈕(delete)的text,this代表在Collection裡的data
    },

    'click .ckd' : function() {
        MyCollection.update(this._id, {$set: {checked: !this.checked}});    //更新狀態,將該text的checked屬性改變
    }
});
  1. 當click 按鈕button的時候,Collection會移除(remove)該data。
  2. 當click 勾選框checkbox的時候,Collection會更新(update)該data。

Deploy

差不多一個段落啦~~
要如何把你的心血deploy上去呢?

meteor有提供網路上的空間讓大家都能把自己的app deploy上去喔~~

在terminal輸入:

meteor deploy my_app_name.meteor.com

就可以在my_app_name.meteor.com上看到自己的meteor app喔!

Session

提供使用者暫時的介面(temporary UI state)

主要是透過

  • Session.set("SessionName", value)
  • Session.get("SessionName")

來存取和讀取

User accounts

在terminal輸入

  • meteor add accounts-ui
  • meteor add accounts-password

就可以得到登入系統

並在html的body裡面加上

{{> loginButtons}}

就有meteor內建的登錄介面囉

Security with methods

 因為我們現在對Collection的存取
(不論是直接輸入,或是選取checlbox、點擊button)

都是在isClient裡面運作,也就是在客戶端直接修改Collection的data,這樣會有安全上的疑慮,所以我們必須透過定義method來達到資訊安全的效果。

首先在terminal輸入

meteor remove insecure

這樣一來就無法在Client對Collection做修改。

method

接著把在Client裡的function全部丟到Meteor.methods裡面。

//在javascript code裡
Meteor.methods({
//新增文件
  addTask : function(text){
    Tasks.insert({
        text: text,
        createdAt: new Date(),
        owner: Meteor.userId(),
        username: Meteor.user().username,
      });
  },
//打勾
  setChecked : function(task) {
    Tasks.update(task._id, {$set: {checked: !task.checked}});
  },
//刪除
  delTask: function (task) {
    Tasks.remove(task._id);
  },
});

Meteor.call

除了宣告方法,也要在Client裡面呼叫

Meteor.call("method", arg)

使用Meteor.call,第一個參數為method的名稱,其後為method參數。

Template.body.events({
    'submit .new-task' : function (e) {    //新增一個text
      var text = e.target.text.value;
      Meteor.call("addTask", text);    
      e.target.text.value = "";
      return false;
    }
  });
Template.task.events({
    'click .delete' : function() {    //點擊按鈕時
      Meteor.call("delTask", this);
    }

    'click .toggle-checked' : function() {    //點擊checkedbox時
      Meteor.call("setChecked", this);
    }
});

Congratulations!

你學會了meteor!!

Thanks for your listening

Meteor Tutorial

By a136489

Meteor Tutorial

  • 963