wepy 小程序開發(組件)

import wepy from 'wepy';

// 聲明一個App小程序實例
export default class MyAPP extends wepy.app {
}

// 聲明一個Page頁面實例
export default class IndexPage extends wepy.page {
}

// 聲明一個Component組件實例
export default class MyComponent extends wepy.component {
}
  1. App小程序實例中主要包含config配置對象globalData全局數據對象小程序生命週期函數、以及其餘自定義方法與屬性
  2. 在Page頁面實例中,能夠經過this.$parent來訪問App實例。
  3. 因爲Page頁面實際上繼承自Component組件。除擴展了頁面所特有的config配置以及特有的頁面生命週期函數以外,其它屬性和方法與Component一致。

組件小程序

  • 注意:WePY中的methods屬性只能聲明頁面wxml標籤的bind、catch事件不能聲明自定義方法,這與Vue中的用法是不一致的。
  • 原生小程序支持js模塊化,沒法實現組件化的鬆耦合與複用的效果。WePY中實現了小程序的組件化開發,組件的全部業務與功能在組件自己實現。
  • WePY中的組件都是靜態組件,是以組件ID做爲惟一標識的,每個ID都對應一個組件實例,當頁面引入兩個相同ID的組件時,這兩個組件共用同一個實例與數據,當其中一個組件數據變化時,另一個也會一塊兒變化。避免這個問題,則須要分配多個組件ID和實例。
<template>
    <view class="child1">
        <child></child>
    </view>

    <view class="child2">
        <anotherchild></anotherchild>
    </view>
</template>


<script>
    import wepy from 'wepy';
    import Child from '../components/child';

    export default class Index extends wepy.page {
        components = {
            //爲兩個相同組件的不一樣實例分配不一樣的組件ID,從而避免數據同步變化的問題
            child: Child,
            anotherchild: Child
        };
    }
</script>
  • 注意:在WePY中,不能將駝峯式命名轉換成短橫杆式命名(好比將childCom轉換成child-com),與Vue中的習慣不一樣。

 

計算屬性:promise

data = {
      a: 1
  }

  // 計算屬性aPlus,在腳本中可經過this.aPlus來引用,在模板中可經過{{ aPlus }}來插值
  computed = {
      aPlus () {
          return this.a + 1
      }
  }

 

props傳值:app

父子組件之間傳值的一種機制,包括靜態傳值與動態傳值。異步

1.靜態傳值模塊化

靜態傳值爲父組件向子組件傳遞常量數據,所以只能傳遞String字符串類型函數

2.動態傳值組件化

動態傳值是指父組件向子組件傳遞動態數據內容,父子組件數據徹底獨立互不干擾。但能夠經過使用.sync修飾符來達到父組件數據綁定至子組件的效果,也能夠經過設置子組件props的twoWay: true來達到子組件數據綁定至父組件的效果。那若是既使用.sync修飾符,同時子組件props中添加的twoWay: true時,就能夠實現數據的雙向綁定了。this

  • 注意:下文示例中的twoWaytrue時,表示子組件向父組件單向動態傳值,而twoWayfalse(默認值,可不寫)時,則表示子組件不向父組件傳值。這是與Vue不一致的地方。

//parent.wpyspa

<child :title="parentTitle" :syncTitle.sync="parentTitle" :twoWayTitle="parentTitle"></child>

data = {
    parentTitle: 'p-title'
};

// child.wpy雙向綁定

props = {
    // 靜態傳值
    title: String,

    // 父向子單向動態傳值
    syncTitle: {
        type: String,
        default: 'null'
    },

    twoWayTitle: {
        type: String,
        default: 'nothing',
        twoWay: true
    }
};

onLoad () {
    console.log(this.title); // p-title
    console.log(this.syncTitle); // p-title
    console.log(this.twoWayTitle); // p-title

    this.title = 'c-title';
    console.log(this.$parent.parentTitle); // p-title.
    this.twoWayTitle = 'two-way-title';
    this.$apply();
    console.log(this.$parent.parentTitle); // two-way-title.  --- twoWay爲true時,子組件props中的屬性值改變時,會同時改變父組件對應的值
    this.$parent.parentTitle = 'p-title-changed';
    this.$parent.$apply();
    console.log(this.title); // 'c-title';
    console.log(this.syncTitle); // 'p-title-changed' --- 有.sync修飾符的props屬性值,當在父組件中改變時,會同時改變子組件對應的值。
}

 

組件通訊與交互

wepy.component基類提供$broadcast$emit$invoke三個方法用於組件之間的通訊和交互。

this.$emit('some-event', 1, 2, 3, 4);

用於監聽組件之間的通訊與交互事件的事件處理函數須要寫在組件和頁面的events對象中:

import wepy from 'wepy'

export default class Com extends wepy.component {
    components = {};

    data = {};

    methods = {};

    // events對象中所聲明的函數爲用於監聽組件之間的通訊與交互事件的事件處理函數
    events = {
        'some-event': (p1, p2, p3, $event) => {
               console.log(`${this.$name} receive ${$event.name} from ${$event.source.$name}`);
        }
    };
    // Other properties
}

$broadcast

$broadcast事件是由父組件發起,全部子組件都會收到此廣播事件,除非事件被手動取消。事件廣播的順序爲廣度優先搜索順序。若是頁面Page_Index發起一個$broadcast事件,那麼按前後順序依次接收到該事件的組件爲:ComA、ComB、ComC、ComD、ComE、ComF、ComG、ComH。以下圖:

$emit

$emit$broadcast正好相反,事件發起組件的全部祖先組件會依次接收到$emit事件。若是組件ComE發起一個$emit事件,那麼接收到事件的前後順序爲:組件ComA、頁面Page_Index。以下圖:

$invoke

$invoke是一個頁面或組件對另外一個組件中的方法的直接調用,經過傳入組件路徑找到相應的組件,而後再調用其方法。

好比,想在頁面Page_Index中調用組件ComA的某個方法:(該事件只傳給ComA,而不是廣播)

this.$invoke('ComA', 'someMethod', 'someArgs');

若是想在組件ComA中調用組件ComG的某個方法:(不存在父子關係的兩個組件)

this.$invoke('./../ComB/ComG', 'someMethod', 'someArgs');

$apply : 組件發起髒檢查。

正常流程下,改變數據後,組件會在流程結束時自動觸發髒檢查。異步或者回調流程中改變數據時,須要手動調用$apply方法。

this.userName = 'Gcaufy';
this.$apply();

$nextTick: 組件數據綁定完成後的回調事件。在不傳入function時,返回一個promise對象。

this.userName = 'Gcaufy';
this.$nextTick(function () {
    console.log('UI updated');
});
this.userName = 'Gcaufy';
this.$nextTick().then(function () {
    console.log('UI updated');
});

 

自定義事件處理函數

能夠經過使用.user修飾符爲自定義組件綁定事件,如:@customEvent.user="myFn"

其中,@表示事件修飾符,customEvent 表示事件名稱,.user表示事件後綴。

目前總共有三種事件後綴:

  • .default: 綁定小程序冒泡型事件,如bindtap.default後綴可省略不寫);

  • .stop: 綁定小程序捕獲型事件,如catchtap

  • .user: 綁定用戶自定義組件事件,經過$emit觸發。注意,若是用了自定義事件,則events中對應的監聽函數不會再執行。

  • // index.wpy
    
    <template>
        <child @childFn.user="parentFn"></child>
    </template>
    
    <script>
        import wepy from 'wepy'
        import Child from '../components/child'
    
        export default class Index extends wepy.page {
            components = {
                child: Child
            }
    
            methods = {
                parentFn (num, evt) {
                    console.log('parent received emit event, number is: ' + num)
                }
            }
        }
    </script>
    // child.wpy
    
    <template>
        <view @tap="tap">Click me</view>
    </template>
    
    <script>
        import wepy from 'wepy'
    
        export default class Child extends wepy.component {
            methods = {
                tap () {
                    console.log('child is clicked')
                    this.$emit('childFn', 100)
                }
            }
        }
    </script>

slot組件內容分發插槽

首先在子組件template模板部分中聲明slot標籤做爲內容插槽,同時必須在其name屬性中指定插槽名稱,還可設置默認的標籤內容;而後在引入了該帶有插槽的子組件的父組件template模板部分中聲明用於「插拔」的內容分發標籤。這些父組件中的內容分發標籤必須具備slot屬性,而且其值爲子組件中對應的插槽名稱name

  • 注意:父組件中一旦聲明瞭對應於子組件插槽的內容分發標籤,即使沒有內容,子組件插槽中的默認內容也不會顯示出來,只有刪除了父組件中對應的內容分發標籤,才能顯示出來。

子組件

<view class="panel">
    <slot name="title">默認標題</slot>
    <slot name="content">默認內容</slot>
</view>

父組件

<panel>
    <view slot="title">新的標題</view>
    <view slot="content">
        <text>新的內容</text>
    </view>