前言
部落格小程式第一版本釋出了 搜尋小程式 ==遙近部落格== , 就可以在手機上看文章了
生命週期
關於Vue的生命週期,你可以看 Vue生命週期, 相比Vue,小程式的生命週期有點特別,它有全域性生命週期、頁面生命週期以及元件生命週期
全域性生命週期
全域性生命週期需要你在app.js檔案中定義,有以下幾個生命週期
onLaunch – 小程式初始化完成,全域性只觸發一次
onShow – 小程式啟動時,或者從後臺進入前臺
onHide – 小程式從前臺進入後臺時執行
onError – 小程式執行指令碼出錯或者api呼叫失敗時執行,會帶上錯誤資訊
==執行順序: onLaunch–> onShow –> onHide==
其中, ==onShow以及 onHiden會多次觸發==,比如你從小程式切換到微信聊天再切換回來,可以監察使用者的行為
頁面生命週期
頁面的生命週期主要有以下幾種:
onLoad
一個頁面只會執行一次, 並且==可以獲取當前頁面的路徑中的 query 引數==
onShow
頁面顯示/切入前臺時觸發,會執行多次
onReady
表示頁面初始渲染完畢, 只會執行一次, ==對介面內容進行設定的API需要該鉤子結束後執行==
onHide
頁面隱藏/切入後臺時觸發,==例如 wx.navigateTo或者tab切換到別的頁面執行==
onUnload
頁面解除安裝時觸發, ==例如 wx.redirectTo或wx.navigateBack到其他頁面時==
==注意點==:當切換頁面需要多次渲染資料改變狀態,建議在onShow中使用,當只需初始化一次的時候,可在onLoad或者onReady中使用。當需要清除定時器時,可在onUnload中使用
==切換頁面時觸發的生命週期==:
當首次載入A頁面,A觸發的生命週期為:onLoad –> onShow –> onReady,從A頁面切換到B頁面時,A頁面觸發onHide,B頁面觸發的生命週期順序與上面一致,當B頁面返回到A頁面時,觸發onUnload,當不清快取,再次進入A頁面時,只觸發onShow
想了解更多,你可以檢視 PageApi
元件生命週期
常用的有以下幾種:
created
元件剛剛被建立,==此時還不能呼叫this.setData方法==
attached
在元件例項進入頁面節點樹時執行, ==此時可以使用this.setData方法,讀取節點資料, 例如wx.createSelectorQuery==
detached
在元件例項被從頁面節點樹移除時執行
想了解更多: 檢視 元件生命週期
頁面/路由 跳轉
在Vue中,我們通過router物件的 push 或者 replce 方法進行路由的跳轉, 已達到顯示對應的頁面,
小程式有所區別, 因為它有tab頁,跳轉會有所區別
wx.switchTab
可以跳轉到對應的tab頁面,==需要在app.json檔案中定義tabBar欄位設定對應的路徑以及名稱==
wx.reLaunch
關閉所有頁面,開啟到應用內的某個頁面
路徑為程式碼包中對應頁面的路徑,可以傳遞引數
wx.redirectTo
關閉當前頁面,跳轉到應用內的某個頁面。但是不允許跳轉到 tabbar 頁面
wx.navigateTo
保留當前頁面,跳轉到應用內的某個頁面。但是不能跳到 tabbar 頁面。使用 wx.navigateBack 可以返回到原頁面。
==頁面跳轉的時候,想傳遞資料==
定義succsee方法, 將需要傳遞的資料進行傳送, 如index頁面跳轉到page1頁面
// index.js
wx.navigateTo({
url: '/page1/page1?id=666',
success: function (res) {
// 通過eventChannel向被開啟頁面傳送資料
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
在 page1 中 ==onLoad== 鉤子進行接收
onLoad: function (option) {
console.log(option) // {id: 666}
const eventChannel = this.getOpenerEventChannel()
eventChannel.on('acceptDataFromOpenerPage', function (data) {
console.log(data) // {data: test}
})
}
如果頁面跳轉成功後, 跳轉到的頁面某些資料想傳遞給原來的頁面
在index.js檔案中,在==定義一個events物件==, 接收資料(監聽事件)
events: {
// 為指定事件新增一個監聽器,獲取被開啟頁面傳送到當前頁面的資料
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
}
在page1.js檔案中, 傳遞資料(發出事件)
eventChannel.emit('acceptDataFromOpenedPage', {data: 'test'});
eventChannel.emit('someEvent', {data: 'test'})
想了解更多, 你可以檢視微信路由API
語法相關
資料繫結
在Vue中,我們通過bind來進行硬繫結
<img :src="imgSrc"/>
而在小程式,你需要通過大括號的方式表示
<image src="{{imgSrc}}"></image>
列表展示
在Vue中,我們通過v-for, 小程式我們使用wx:for
顯示與隱藏元素
vue中,使用v-if 和v-show控制元素的顯示和隱藏
小程式中,使用wx-if和hidden控制元素的顯示和隱藏
事件繫結
vue中,我們通過@click 來繫結點選事件,stop時間修飾符來阻止冒泡, 在小程式,你需要使用bindtap來繫結點選事件(傳遞事件的字串名稱), ==catchtap來定義阻止冒泡的點選事件==
或者你可以定義一個wxs檔案, 裡面寫相應的邏輯
<wxs module="wxs" src="./test.wxs"></wxs>
<view id="tapTest" data-hi="WeChat" bindtap="{{wxs.tapName}}"> Click me! </view>
function tapName(event, ownerInstance) {
console.log('tap wechat', JSON.stringify(event))
}
module.exports = {
tapName: tapName
}
觸發事件的時候,vue想傳遞資料,只需要在函式中進行傳參即可
小程式事件傳遞引數, 需要在元件的wxml中定義dataset,通過currentTarget物件獲取
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
Page({
bindViewTap:function(event){
event.currentTarget.dataset.alphaBeta === 1 // 會轉為駝峰寫法
event.currentTarget.dataset.alphabeta === 2 // 大寫會轉為小寫
}
})
資料雙向繫結
vue中,通過使用v-model可以很方便的實現, 小程式需要使用bindinput來繫結一個事件,再setData來改變值
取值
vue中通過this.xxx 讀取, 小程式需要使用this.data.xxx讀取
通訊
開發中, 元件之間通訊幾乎是必不可少的,下面是vue和小程式通訊之間的一些總結
父元件傳遞子元件
==Vue傳遞==
Vue中父元件傳遞資料給子元件,我們通過prop將需要傳遞的資料給到子元件中
<parent>
<child :list="list"></child> //在這裡繫結list物件
</parent>
子元件定義props物件接受相應的資料
props:{
list:{
type:Array,//type為Array,default為函式
default(){
return [
"hahaxixihehe"//預設初始值
]}}
},//用props屬性進行傳資料,此時子元件已經獲取到list的資料了
data(){
return {}
}
==父元件傳遞給子元件的資料,不能改變==
==小程式傳遞==
小程式傳遞跟Vue類似, 一樣通過props傳遞,只是語法有所區別
<articleItem wx:for="{{articles}}" wx:key="{{index}}" articleItem="{{item}}"/>
子元件定義properties物件接受對應的資料
properties: {
articleItem: {
type: Object,
value: {}
}
}
子元件與父元件通訊
在Vue中, 子元件跟父元件通訊,通過$emit來實現
在子元件中我們通過 $emit 向父元件傳送一個事件,並且傳遞資料
this.$emit('success',false);
父元件通過繫結自定義事件接受
<app-form v-bind:dialogCreate = "dialogCreate" v-on:success="success(res)"></app-form>
methods: {
success(res){
this.dialogCreate = res;
}
}
小程式中,跟Vue差不多, 只是語法不一樣, 小程式不是 $emit ,而是 使用 ==triggerEvent== 傳送事件給父元件, 然後在wxml中bind: 方法名稱 來繫結自定義事件觸發
兄弟之間通訊
vue中兄弟之間通訊,可以將需要傳遞到的資料放到父元件,父元件提供一個方法給到子元件,子元件觸發方法改變資料, 父元件再將新的資料給到兄弟元件, 讓父做一箇中間人,當然,我們也可以使用事件匯流排(eventBus)來進行
主要是在Vue的原型上新增一個Vue的例項,或者建立一個Vue的例項,需要使用到的地方引入, 我們就使用這個vue的例項通過on 和emit 來實現通訊, 它的原理就是通過公用一個vue的例項來進行事件的發放和監聽,已達到資料共享的目的,==關於小程式兄弟元件通訊,目前比較常用的方法是,通過父元件作為中間人==
父元件獲取子元件
在vue中,父元件呼叫子元件的方法比較簡單,可以給元件定義ref或者通過$children來讀取到子元件,直接呼叫元件對應的方法即可,==ref需要確保你的子元件已經在頁面渲染, 不然沒法獲取==
// 父元件
<template>
<component-a ref="comA"></component-a>
</template>
<script>
export default {
mounted () {
const comA = this.$refs.comA;
console.log(comA.title); // Vue.js
comA.sayHello(); // 彈窗
}
}
</script>
在小程式中,也有類似的方法, 我們可以通過給子元件繫結一個id值, 然後在 通過 ==selectComponent== 函式獲取對應id的元件例項,就可以輕鬆的呼叫子元件的方法和訪問對應的資料了
父元件中我們如下定義
// index.wxml
<test id='test'></test>
<button bindtap="test">觸發子元件方法</button>
// index.js
test () {
let child = this.selectComponent('#test')
console.log(child) // 子元件例項
child.fun() // 呼叫子元件的方法
console.log(child.data.test) // 讀取子元件的資料或者改變都可以
}
子元件js檔案
data: {
test: '我的子元件資料'
},
methods: {
fun () {
console.log('我的子元件方法')
}
}
子元件獲取父元件
既然我們可以通過$children獲取子元件的,相應的我們子元件可以獲取父組,vue中我們可以通過this.$parent來獲取父元件,這樣就可以輕鬆訪問父的方法或者資料
小程式中,我們可以在子元件使用 ==selectOwnerComponent== 來獲取父元件的例項
全域性通訊方式
vue中如果該資料使用地方較多,推薦使用vuex來管理, 在小程式中,建議使用 globalData 來存放多個地方使用到的資料
vue通訊擴充
vue還有2種用的比較少用的通訊的方式,這些通訊方式適合在一些高階元件
$attrs和$listeners
==它們可以實現父元件的資料傳遞到深層次的子元件中,改變父元件的資料==
我們平時通過prop將資料傳遞給子元件, 子元件需要props物件來進行接收, 但是如果我們沒有在props中接收對應的資料,那麼這個資料就沒法使用的,那麼這些資料去哪裡了呢, 它會作為父元件根元素的attribute顯示在dom元素中
而在子元件中, ==$attrs 可以訪問到沒有給使用到的props屬性==
// 父元件傳遞資料
<Button type='success' @click="test" size="medium" to="/btnTest">跳</Button>
// 子元件中的prop中我們並不接收to的值
<span>{{this.$attrs}}</span>
這個時候this.$attrs列印的值就是 to 傳遞過來的資料,我們就可以通過v-bind的方式傳遞給更深層次的元件, 為了不讓父元件的attribute中顯示to的值, 我們需要在子元件中設定==inheritAttrs: false==, 這樣你的父元件就不會顯示你子元件中沒在props中接受的資料,保證你的資料安全
// 子元件中的prop中我們並不接收to的值
<span>{{this.$attrs}}</span>
<test v-bind="$attrs"></test> // 傳遞給更深的子元件
那最終的子元件拿到了資料之後,我應該如何改變我父級的資料呢, 這個時候我們就可以在子元件中v-on繫結 $listeners 讓更深層次的子元件可以獲取到父元件中的自定義事件,我們就可以在更深層次的子元件中 $emit 傳送事件,來觸發父元件的方法從而達到資料的更新
<span>{{this.$attrs}}</span>
<test v-bind="$attrs" @test2="handleClick" v-on="$listeners"></test> // 傳遞給更深的子元件
// 更深層次的子元件中
methods: {
changeParentData () {
this.$emit("change", 'ninhao') // 爺爺的方法
this.$emit("test2", 'ninhao') // 父級的方法
}
}
provide/inject
剛剛的方法的確幫我們解決了很多的通訊的問題,但是視乎有點麻煩, provide/inject可以更好的幫助我們深層次的通訊
我們可以在父元件中定義provide物件/物件函式,它可以讓所有的子孫元素都可以使用到你在其定義的值
// 父元件中
provide() {
return {
color: this.color
},
data () {
return {
size: 'medium',
color: 'green'
}
}
},
子元件中通過inject通過key獲取對應的值
inject: ['color']
==需要注意的是, 子元件中獲取到的父元件的值,是不響應的,也就是父改變了,子不會改變==
==如果想父改變子同時改變,可以傳遞的是父級的例項==,那麼父改變的時候,子的資料也會相應的改變,但是這樣會造成不必要的methods等父級資料傳遞
第二種方法就是==通過 observable 方法 來讓你的物件是可監聽的==
這個時候,我們在provide中定義data的值, 這樣確保你傳遞的物件是可響應的, 那麼父級改變的時候,你的子級也會相應的改變了
// 父元件中
provide() {
this.data = Vue.observable({color: 'green'})
return {
data: this.data
}
},
methods: {
changeColor () {
this.data.color = 'red'
console.log(this.color,23232)
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結