本文處于完善狀態,會持續更新。最近有點忙,各位看官可以養肥再看。多謝關注!
akryum:vue-component
使用 akryum:vue-component 包幫助 meteor 識別編譯 vue 文件。
meteor add akryum:vue-component
vue-meteor-tracker
使用 vue-meteor-tracker 包,在 Vue 組件中集合 Meteor 響應數據。
Installation
meteor npm install --save vue-meteor-tracker
Install the plugin into Vue
import VueMeteorTracker from 'vue-meteor-tracker';
Vue.use(VueMeteorTracker);
Use
在你的 vue 組件中添加 meteor 對象屬性 :
new Vue({
meteor: {
// Meteor specific options
}
});
Subscriptions
在 $subscribe object 定義訂閱者,key 為發布者名稱,value 為數組參數,在訂閱的時候傳遞給發布者。
當組件銷毀時訂閱將停止
meteor: {
//在 $subscribe object 定義訂閱者
$subscribe: {
// 不帶參數訂閱 'threads' 發布者
'threads': [],
// 帶參數訂閱 'threads' 發布者
'threads': ['new', 10], // The 10 newest threads
// 帶動態參數訂閱 'threads' 發布者
// 當 vue 響應屬性改變時,重新訂閱
'posts': function() {
// Here you can use Vue reactive properties
return [this.selectedThreadId] // Subscription params
}
}
}
你能夠 $subscribe(name, ...params) 方法在你的組件代碼中:
ready () {
// Subscribes to the 'threads' publication with two parameters
this.$subscribe('thread', 'new', 10);
}
在你的組件中,$subReady 對象屬性包含訂閱者訂閱狀態 ,為了獲知訂閱者是否已訂閱,你可以這樣做:
console.log(this.$subReady.thread);
或者在你的模板中:
<div v-if="!$subReady.thread">Loading...</div>
Reactive data
在 meteor 對象里的屬性(不在 $subscribe 中)會被轉化為 vue 的響應屬性(附加到 vue 的 data 屬性中) ,你可以在模板中像標準 vue data 屬性一樣使用,或者在計算屬性中。
...
data() {
return {
// 初始化 todos 也可以不用
todos: [],
newTodo: ''
}
},
meteor: {
$subscribe: {
['todos']: []
},
// todos 屬性會響應更新 meteor 的響應數據源(就像 collections 或者 session )
// 當 Todos 集合發生變化時,todos將發生改變
todos() {
return Todos.find({}, {sort: {date: -1}});
}
},
...
通過上面做法,僅僅讓 vue data 響應更新于 meteor 響應數據源,當 todos 集合發生改變,vue 的 todos 數據屬性才能獲取更新,如下圖所示
如上圖所示,vue 和 meteor 的數據是單向的:meteor => vue
通過把 meteor 對象屬性的值定義為一個對象,我們可以讓 meteor 響應 vue,該對象有以下來個參數:
- params() (可選), 返回對象的函數, 該對象屬性值可以為 vue data 的響應屬性
- update([params]), 但依賴參數發生改變回調的函數。
...
meteor: {
// 無參訂閱 todos
$subscribe: {
["todos"]: []
},
todos: {
// 聲明定義一個依賴 vue 響應屬性的參數
params() {
// Here you can use Vue reactive properties
// Don't use Meteor reactive sources!
return {
type: this.type
};
},
// 可選項,深度觀察嵌套對象屬性值,
// 此處 type 為普通類型,故 false
deep: false,
//// Meteor Reactivity
// param 參數響應 vue 更新時,將刷新 todos 屬性值
// Then it calls Tracker.autorun() to refresh the result
// each time a Meteor reactive source changes
update({ type }) {
// Here you can use Meteor reactive sources
// like cursors or reactive vars
// Don't use Vue reactive properties!
if (type) {
return Todos.find({checked: true},{sort: {date: -1}});
} else {
return Todos.find({checked: false},{sort: {date: -1}});
}
}
}
},
...
此刻,vue 和 meteor 數據流為雙向:vue <=> meteor
注意
在 meteor 屬性中我們有兩個地方使用到 vue 響應屬性。
meteor: {
1. 在 $subscribe 中帶參訂閱 publisher
$subscribe: {
['todos']: function() {
// 使用 vue 屬性
return [xxx]
}
},
2. 在對象屬性中 param 中
todos: {
params() {
// 使用 vue 屬性
return {
type: xxx
};
},
}
},
區別是 “1” 處 vue 屬性發生改變會重新訂閱,“2”處 vue屬性發生改變重新獲取 miniMongo 獲取數據。
開啟或禁用 meteor data
export default {
meteor: {
// ...
},
methods: {
activate () {
this.$startMeteor()
},
deactivate () {
this.$stopMeteor()
},
},
}
你能夠使用來防止 meteor data 自啟動
export default {
meteor: {
$lazy: true,
// ...
},
}
Freezing data
此選項將對 Meteor 數據使用 Object.freeze,以防止 Vue 響應。 這樣可以在渲染大型集合列表時提高 Vue 的性能。 默認情況下,此選項已關閉。
// Disable Vue reactivity on Meteor data
Vue.config.meteor.freeze = true;
vue-supply
Installation
npm install --save vue-supply
Use
import Vue from 'vue'
import VueSupply from 'vue-supply'
Vue.use(VueSupply)
當應用變得越來越龐大時,我們需要在每個組件重復定義 meteor 屬性,并且我們可能定義同樣的值,管理這些響應性數據源就會變得越來越困難。
使用 vue-supply,您可以輕松地使用數據并自動激活或停用訂閱。
vue-supply 為我們的應用添加了一層 supply,幫助我們管理訂閱 meteor 數據,避免在組件重復訂閱 meteor 數據。
使用 vue-supply,您可以創建擴展Supply定義的 Vue 實例。定義兩個方法: activate 和 deactivate。當在組件或 Vue store 首次消費該 supply 時,它會自動激活(使用 grasp 方法);當沒有組件使用它時,它會自動關閉(使用 release 方法)。當激活或關閉時,supply 會回調 activate 和 deactivate 方法。
// base.js
export default {
extends: Supply,
methods: {
activate () {
// 當激活時,開啟 meteor ,訂閱發布者
this.$startMeteor()
},
deactivate () {
// 關閉 meteor ,取消訂閱
this.$stopMeteor();
},
},
meteor: {
// 關閉 vue-meteor-tracker自啟動訂閱 meteor data
// 讓 supply 監聽組件,管理訂閱
$lazy: true,
},
}
當激活或關閉時,supply 會發射 consumers 和 active 事件,你可以使用 watch 其屬性和 $on 監聽其 'is-active' 和 'is-not-active' 事件。
// xxx.supply.js
import base from "./base";
export default {
extends: base,
data() {
return {
...
}
},
meteor: {
...
},
watch: {
// 監聽 supply 是否激活
active(val){
console.log(val);
},
// 監聽 組件消費者個數
consumers(val){
console.log(val);
}
}
}
你也可以使用 supply.ensureActive(),返回一個 Promise(that resolves as soon as the supply is activated )
TestResource.ensureActive().then(() => {
// The supply is active
})
Registration
建議注冊 supply 定義,以便注入到組件和 vuex stroe 中。
import { register } from 'vue-supply'
import TestResourceDef from 'supply/test-resource'
register('TestResource', TestResourceDef)
Usage in components
在組件內部,use(name,manageKeepAlive = true)添加一個mixin,使用注冊中使用的名稱(如上所述),創建和銷毀組件時自動消費或釋放 supply:
// todo-list.component.js
import { use } from "vue-supply";
export default {
name: "app",
components: {
"todo-list": TodoList
},
mixins: [use("TodoSupply")],
data() {
return {
newTodo: ""
};
},
computed: {
todos() {
return this.$supply.TodoSupply.todos;
},
ready() {
return this.$supply.TodoSupply.active;
},
type() {
return this.$supply.TodoSupply.type;
}
},
....
通過計算 this.$supply.TestResource.[someData]
該響應屬性獲取數據。
Usage in Vuex store
Collections
aldeed:simple-schema (設計數據模式)
Mongo 數據雖然是無模式,但這不意味著我們就不可以用模式去設計規范驗證我們的數據。使用 aldeed:simple-schema ,在寫入數據操作時驗證數據。
Installation
$ meteor add aldeed:simple-schema
Use
定義 Schema
// todos.collection.js
export const TodoSchema = new SimpleSchema({
title: {
type: String,
max: 200,
min: 1,
// 自定驗證器
custom: function () {
if(this.value.trim().length == 0){
return '不能為空'
}
}
},
checked: {
type: Boolean
},
date: {
type: Date
}
})
todos.schmea = TodoSchema;
驗證
// App.vue
data() {
return {
newTodo: "",
// 定義驗證空間,針對不同區域驗證
context: Todos.schmea.namedContext("myContext")
};
},
computed: {
todos() {
return this.$supply.TodoSupply.todos;
},
ready() {
return this.$supply.TodoSupply.ready;
},
type() {
return this.$supply.TodoSupply.type;
}
},
methods: {
submit() {
let newtodo = {
title: this.newTodo,
date: new Date(),
checked: false
};
// 驗證
if (this.context.validate(newtodo)) {
Todos.insert(newtodo);
}
this.newTodo = "";
},
錯誤信息提示
<span v-show="context.keyIsInvalid('title')" class="has-text-danger">不能為空</span>
<div class="control has-icons-left has-icons-right">
<input class="input is-medium" :class="{'is-danger': context.keyIsInvalid('title')}" type="text" placeholder="write it..." v-model="newTodo" @keyup.enter="submit">
<span class="icon is-small is-left">
<i class="fa fa-file-o"></i>
</span>
</div>
這里不多述 SimpleSchema 的用法,請自行查看 api 。
Publications and Data Loading(發布訂閱)
為了提高數據安全性,我們不應該直接在客戶端使用 Collections 全部詳細字段,不應該直接調用 collection.insert() 等方法對數據庫進行寫入。我們應該服務端發布可訪問的公有數據,定義數據寫入接口:
- Meteor.pulish() 定義數據發布接口
- Meteor.methods() 定義數據操作接口
具體 api 查看。
在使用之前我們必須刪除以下的包:
meteor remove autopublish
meteor remove insecure
注意:publisher 在沒有 cursor 返回的情況下要返回
this.ready()
服務端發布
// todos.collection.js
if (Meteor.isServer) {
// 定義數據發布接口
Meteor.publish('todos', function tasksPublication() {
return todos.find({});
});
// 定義數據操作接口
Meteor.methods({
['todos.insert'](val) {
todos.insert(val);
},
['todo.update.checked']({_id: _id, checked: _checked}) {
Todos.update(
{ _id: _id },
{ $set: { checked: _checked } },
{ multi: true }
);
}
})
}
客戶端訂閱
const handle = Meteor.subscribe('lists.public');
/**
handle:
{
.ready():boolean(true:當this.ready()明確調用,或者返回的游標的初始內容將被發送)
.stop():停止訂閱,清除緩存
}
*/
你能夠自定義錯誤信息發送到客戶端:
// on the server, pick a code unique to this error
// the reason field should be a useful debug message
throw new Meteor.Error("logged-out",
"The user must be logged in to post a comment.");
// on the client
Meteor.call("methodName", function (error) {
// identify the error
if (error && error.error === "logged-out") {
// show a nice error message
Session.set("errorMessage", "Please log in to post a comment.");
}
});
aldeed:collection2(自動驗證數據)
擴展 Mongo.Collection,提供對 Collection 指定 Schmea,在進行插入和更新數據時自動驗證數據模式。
// todos.collection.js
if (Meteor.isServer) {
// 定義數據發布接口
Meteor.publish('todos', function tasksPublication() {
return todos.find({});
});
// 定義數據操作接口
Meteor.methods({
['todos.insert'](val) {
try {
todos.insert(val);
} catch (error) {
if (error.sanitizedError.error == 400) {
// 由于驗證只在服務端,所以必須把驗證錯誤信息反饋給前臺
// 發送 驗證錯誤消息
error.sanitizedError.error = 'ValidationErrors';
throw error.sanitizedError;
}
}
},
...
})
}
...
todos.schema = TodoSchema;
// 指定附加 Schema
todos.attachSchema(TodoSchema);
// app.vue
submit() {
let newtodo = {
title: this.newTodo,
date: new Date(),
checked: false
};
// 重置驗證器
this.context.resetValidation()
// 調用遠程服務
Meteor.call("todos.insert", newtodo, (error) => {
// 動態添加錯誤驗證消息
if(error && error.error == 'ValidationErrors')
this.context.addInvalidKeys(JSON.parse(error.details))
});
this.newTodo = "";
},
// 響應反饋錯誤消息
<span v-show="context.keyIsInvalid('title')" class="has-text-danger">{{context.keyErrorMessage('title')}}</span>
分頁
分頁是一種非常常見的數據訪問模式。通常有兩種分頁樣式,即“逐頁”樣式,您只能在一段時間只顯示一頁結果,從某些偏移開始(用戶可以控制),以及“無限滾動“樣式。
在逐頁技術中,如果我們要達到以下效果:
我至少要關注三個參數:
- skip,跳過第幾頁
- limit,每頁顯示數據數量
- pages,總頁數
通過在 $subscribe 子屬性值中返回 vue響應屬性數組(訂閱參數),我們可以響應式向服務端發布者獲取不同頁碼數據。
//todos.supply.js
...
data() {
return {
// 初始化屬性值
todos: [],
type: false, // type 用來標志 todos 列表顯示完成或未完成
skip: 0, // 跳過頁數
limit: 5, // 顯示數據數量
pages: 0 // 頁數
}
},
meteor: {
// 無參訂閱 todos
$subscribe: {
["todos"]: function () {
// 響應式訂閱
return [this.type, this.limit, this.skip] //查詢 是否已標記, 數據量, 跳躍點
}
},
todos() {
this.pages = Math.ceil(Counts.get('todosCounts')/this.limit) || 1; // 計算頁數
return Todos.find({}, {sort: { date: -1 }});
}
},
...
// todos.collection.js
Meteor.publish('todos', function tasksPublication(checked, limit, skip) {
// 實時訂閱 todos 總數
Counts.publish(this, 'todosCounts', todos.find({ checked: checked }));
return todos.find({ checked: checked }, { limit: limit, skip: skip * limit, sort: { date: -1 } });
});
tmeasday:publish-counts(實時獲取 Collection Count)
在上面代碼中,使用 tmeasday:publish-counts 包,來實時獲取 todos 總數量,再計算出總頁數。publish-counts 有以下主要方法:
- Counts.publish [server] ,服務端代碼中訂閱集合
- Counts.get [client]
一旦你在服務端調用 Counts.publish , 你就可以在客戶端調用 Counts.get('name-of-counter') 去響應獲取計數器.
該方法會返回一個整數, 返回 0 意味著你還沒發布或訂閱不成功。 - Counts.has [client],判斷是否有指定計數器。