Grace
一個精巧、易用的微信小程式開發輔助庫
Github: github.com/wendux/grac…
特點
- 輕量、小巧、上手簡單
- 支援和Vue一樣優雅的資料響應式
- 支援資料自動更新、更改快取、批量更新
- 強大的網路功能
- 支援全域性事件匯流排
- 支援跨頁面傳值
- 支援mixins
Demo
示例工程在原始碼 “quickstart-grace-demo”目錄下, 用微信小程式開發工具開啟即可。
使用
- 將 https://github.com/wendux/grace 工程中src目錄中所有檔案拷貝到小程式根目錄下的grace目錄
- 建立頁面時用
grace.page
替換Page
即可。
import grace from "../../grace/index.js"
grace.page({
data: {
userInfo: {},
canIUse: true
},
onLoad() {
//直接通過$data賦值更新資料
this.$data.canIUse = false
//通過$http發起網路請求
this.$http.post("http://www.dtworkroom.com/doris/1/2.0.0/test", {xx: 7}).then((d) => {
console.log(d)
}).catch(err => {
console.log(err.status, err.message)
})
//全域性事件匯流排-監聽事件
this.$bus.$on("enventName", (data) => {
console.log(data)
})
//返回上一頁,並傳遞資料
this.$goBack({retValue: "8"})
},
//跨頁面傳值
$onBackData(data) {
//接收頁面返回的資料,
}
...
})
複製程式碼
如果是註冊元件(component)的話, 只需用 grace.component
替換 Component
構造器即可:
// grace.component 替換 Component
grace.component({
properties: {
},
data: {
text:"我是自定義元件",
times:1
},
methods: {
onTap(){
//賦值更新
this.$data.text="自定義元件點選 +"+this.$data.times++
}
}
}
複製程式碼
注意:Grace 注入到例項中的所有方法和屬性命名都以“$”開始。
資料響應式
微信小程式中資料發生變化後都要通過setData顯式更新如:
//更新單個欄位
this.setData({
userInfo: res.userInfo
})
//更新多個欄位
this.setData({
userInfo: res.userInfo
canIUse: false
})
複製程式碼
這很明顯是受了React的影響,好的不學?,如果你用過Vue, 你應該會覺得這看起來很不優雅,尤其是程式碼中零零散散要更新的值多的時候,程式碼看起來會很冗餘,還有,有時為了改變一個變數,也得調一次setData
.
現在,有了Grace, 它會讓你的程式碼變的優雅,你可以像使用Vue一樣更新資料:
this.$data.userInfo=res.userInfo;
//更新多個欄位,並非重新賦值
this.$data={
userInfo: res.userInfo
canIUse: false
}
複製程式碼
現在,你可以直接通過賦值就能更新介面了。當然,您依舊可以使用this.setData
來更新資料,grace會自動同步 this.$data
.
陣列更新檢測
grace的資料響應式原理和Vue是一樣的,(如果你熟悉Vue,可以跳過)對於陣列:
變異方法
grace包含一組觀察陣列的變異方法,所以它們也將會觸發檢視更新。這些方法如下:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
替換陣列
變異方法 (mutation method),顧名思義,會改變被這些方法呼叫的原始陣列。相比之下,也有非變異 (non-mutating method) 方法,例如:filter()
, concat()
和 slice()
。這些不會改變原始陣列,但總是返回一個新陣列。當使用非變異方法時,可以用新陣列替換舊陣列:
this.$data.items = this.$data.items.filter(function (item) {
return item.message.match(/Foo/)
})
複製程式碼
注意事項
由於 JavaScript 的限制,grace不能檢測以下變動的陣列:
- 當你利用索引直接設定一個項時,例如:
this.$data.items[indexOfItem] = newValue
- 當你修改陣列的長度時,例如:
this.$data.items.length = newLength
為了解決第一類問題,以下兩種方式都可以實現和 this.$data.items[indexOfItem] = newValue
相同的效果,同時也將觸發狀態更新:
this.$data.$set(example1.items, indexOfItem, newValue)
複製程式碼
// Array.prototype.splice
this.$data.items.splice(indexOfItem, 1, newValue)
複製程式碼
為了解決第二類問題,你可以使用 splice
:
this.$data.items.splice(newLength)
複製程式碼
物件屬性的新增
還是由於 JavaScript 的限制,grace 不能檢測物件屬性的新增或刪除:
grace.page({
data: {
a: 1
}
onLoad(){
//a現在是響應式的
this.$data.a=2;
//b不是響應式的
this.$data.b = 2
}
})
複製程式碼
對於已經建立的例項,grace 不能動態新增根級別的響應式屬性。但是,可以使用 $data.$set(object, key, value)
方法向巢狀物件新增響應式屬性。例如:
this.$data.$set(this.$data, 'b', 2)
複製程式碼
資料變更快取
根據微信小程式官方優化建議,grace可以避免如下問題:
-
頻繁的去 setData
為了解決這個問題,grace引入了資料變更快取機制,下面看一個例子:
//開始快取資料變更 this.$data.$cache(); //接下來是n次密集的資料更新 this.$data.name="doris" this.$data.userCard.no="610xxx889" this.$data.balance=66666 .... //統一提交變更 this.$data.$commit(); 複製程式碼
在呼叫
$cache()
之後,所有資料的變化將會快取起來(不會觸發setData
), 知道呼叫$commit
後,才會統一重新整理,這樣即避免了頻繁呼叫setData
帶來的效能消耗。 -
後臺態頁面進行 setData
當頁面進入後臺態(使用者不可見),不應該繼續去進行
setData
,後臺態頁面的渲染使用者是無法感受的,另外後臺態頁面去setData
也會搶佔前臺頁面的執行。當頁面進入後臺時,grace會自動停止資料更新,當頁面再次轉到前臺時會自動開啟渲染。
Http
Grace通過Promise封裝了wx.request, 並支援攔截器、請求配置等:
-
Restful API
$http.get(url, [data], [options]) $http.post(url, data, [options]) $http.put(url, data, [options]) $http.delete(url,[data],[options]) $http.patch(url,[data],[options]) 複製程式碼
-
多個併發請求
var getUserRecords=()=>{ return this.$http.get('/user/133/records'); } var getUserProjects=()=>{ return this.$http.get('/user/133/projects'); } this.$http.all([getUserRecords(), getUserProjects()]) .then(this.$http.spread(function (records, projects) { // Both requests are now complete })) .catch(function(error){ console.log(error) }) 複製程式碼
-
攔截器
// Add a request interceptor this.$http.interceptors.request.use((config,promise)=>{ // Do something before request is sent config.headers["X-Tag"]="grace"; // Complete the request with custom data // promise.resolve("fake data") return config; }) // Add a response interceptor this.$http.interceptors.response.use( (response,promise) => { // Do something with response data . // Just return the data field of response return response.data }, (err,promise) => { // Do something with response error //promise.resolve("ssss") } ) 複製程式碼
Grace使用的http請求庫是 FLY , $http
是 FLY的一個例項,詳情可以參照其官網,如果您想建立新的 FLY 例項:
var newHttp=grace.createHttpClient();
複製程式碼
注意:grace建立頁面時,所有頁面的$http
都是同一個FLY 例項,所以對this.$http
的配置,會在全域性生效,所以如果你想要配置全域性的攔截器、請求基地址、超時時間等可以建立一個幫助檔案,然後頁面引入這個檔案即可:
import grace from "../grace/index.js"
grace.http.config.baseURL = 'http://www.dtworkroom.com/doris/1/2.0.0/'
grace.http.config.timeout = 5000;
grace.http.interceptors.request.use((config, promise) => {
//攔截器邏輯
//console.log(config.body);
});
export default grace;
複製程式碼
事件匯流排
全域性事件匯流排可以在全域性(跨頁面)觸發、監聽事件。
$on(eventName,handler)
監聽事件
this.$bus.$on("enventName",(arg1,arg2)=>{
//事件處理器引數為$emit觸發事件時傳遞的引數
console.log(arg1)
})
複製程式碼
$emit(eventName,[…arguments])
觸發事件
this.$bus.$emit("enventName", 1,2)
複製程式碼
$off(eventName,[handler])
取消監聽
this.$bus.$off("eventName",cb)
複製程式碼
當提供hanlder時,只將該hanlder移出監聽者佇列,如果沒有傳handler,則清空該事件的監聽者佇列。
跨頁面傳值
在小程式中開啟新頁面時可以通過url的query向新頁面傳值,這很容易,如:
wx.navigateTo({
//傳遞id,在新頁面onLoad中獲取
url: 'test?id=1'
})
複製程式碼
但是,新頁面關閉時如何向前一個頁面返回資料? 小程式中沒有提供直接的方法,grace給所有頁面新增了一個回撥,用於接收頁面回傳的資料,如下:
grace.page({
data:{}
$onBackData(data){
//接收頁面返回的資料,
}
...
})
複製程式碼
上面的頁面我們記為A, 假設你開啟了一個新頁面B, 你需要在B中選擇一些資訊後回傳給A,那麼你在B中應該:
grace.page({
data: {},
bindViewTap(){
//返回上一個頁面,並回傳一些資料
this.$goBack({xxx:5});
}
...
}
複製程式碼
$goBack([data],[delta])
關閉當前頁面,返回上一頁面或多級頁面,如果存在data
, 則會呼叫返回到的頁面的$onBackData
回撥,若data
不存在,則不會回撥$onBackData
.
delta
意義同 wx.navigateBack
引數的delta, 表示回退的頁面數,預設為1(上一頁),如果如果 delta 大於現有頁面數,則返回到首頁。
mixin
混入 (mixins) 是一種分發頁面(Page)可複用功能的非常靈活的方式。簡而言之,他可以在小程式建立頁面時,混合頁面選項,可以實現給所有頁面新增一些鉤子的功能,如果還不理解,不要緊,下面來看一個例子:
實現:在任何頁面呼叫onLoad
、onShow
時列印日誌,並輸出當前頁面id.
-
建立一個help.js檔案
import grace from "../grace/index.js" var page=grace.page; grace.page=function(ob){ mixin(ob,{ onLoad(){ //頁面呼叫onShow時列印出當前頁面id console.log("onLoad, pageID:"+this.$id) }, onShow(){ //頁面呼叫onShow時列印出當前頁面id console.log("onShow, pageID:"+this.$id) } }) //建立頁面 page.call(grace,ob) } export default grace; 複製程式碼
-
在建立Page時引入help.js
import grace from "../../utils/help.js" grace.page({ data:{} }) //控制檯輸出 > onLoad, pageID:1 > onShow, pageID:1 複製程式碼
這樣一來,相當於給所有的Page新增了onLoad
、onShow
預處理。
可以看到,mixin通過混入頁面建立引數給頁面新增統一的預處理功能,相當於新增了頁面鉤子。
選項合併
當頁面構建物件和混入物件含有同名選項時,這些選項將以恰當的方式混合。
-
資料物件在內部會進行淺合併 (一層屬性深度),在和頁面構建數物件發生衝突時以頁面構建數物件資料優先。
-
同名鉤子函式將混合為一個陣列,因此都將被呼叫。另外,混入物件的鉤子將在頁面自身鉤子之前呼叫。
grace.mixin(ob,{ onShow(){ console.log("mixin onShow") } }); ... grace.page({ onShow(){ console.log("page onShow") } }) //頁面顯示時會輸出: > mixin onShow > page onShow 複製程式碼
和wepy比較
請參考:https://juejin.im/post/5aa0e45af265da23a404635a
最後
再次貼出github地址,如果你喜歡,歡迎star , Github: github.com/wendux/grac…