微信小程序組件化開發框架WePY

compilers: compilers爲1.3.1版本以後的功能,若是須要使用其它語法,請先配置compilers,而後再安裝相應的compilers。目前支持wepy-compiler-less, wepy-compiler-postcss,wepy-compiler-sass、wepy-compiler-babel、wepy-compiler-pug,其餘compiler持續開發中…css

plugins: plugins爲1.1.6版本以後的功能,目前支持js壓縮wepy-plugin-ugliyjs、圖片壓縮wepy-plugin-imagemin,其餘plugin持續開發中…html

lang決定了其代碼編譯過程,src決定是否外聯代碼web

<style lang="less" src="page1.less"></style>
<template lang="wxml" src="page1.wxml"></template>
<script>
    // some code
</script>
<script>
import wepy from 'wepy';
export default class extends wepy.app {
    config = {
        "pages":[
            "pages/index/index"
        ],
        "window":{
            "backgroundTextStyle": "light",
            "navigationBarBackgroundColor": "#fff",
            "navigationBarTitleText": "WeChat",
            "navigationBarTextStyle": "black"
        }
    };
    onLaunch() {
        console.log(this);
    }
}
</script>
<style lang="less">
/** less **/
</style>
<script>
import wepy from 'wepy';
import Counter from '../components/counter';

export default class Page extends wepy.page {
    config = {};
    components = {counter1: Counter};

    data = {};
    methods = {};

    events = {};
    onLoad() {};
    // Other properties
}
</script>

<template lang="wxml">
    <view>
    </view>
    <counter1></counter1>
</template>

<style lang="less">
/** less **/
</style>
<template lang="wxml">
    <view>  </view>
</template>

<script>
import wepy from 'wepy';
export default class Com extends wepy.component {
    components = {};

    data = {};
    methods = {};

    events = {};
    // Other properties
}
</script>

<style lang="less">
/** less **/
</style>
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 {
}
import wepy from 'wepy';

export default class MyAPP extends wepy.app {
    customData = {};

    customFunction () { }

    onLaunch () {}

    onShow () {}

    config = {}  // 對應 app.json 文件

    globalData = {}
}

在Page頁面實例中,能夠經過this.$parent來訪問App實例。json

import wepy from 'wepy';

export default class MyPage extends wepy.page {
// export default class MyComponent extends wepy.component {
    customData = {}  // 自定義數據

    customFunction () {}  //自定義方法

    onLoad () {}  // 在Page和Component共用的生命週期函數

    onShow () {}  // 只在Page中存在的頁面生命週期函數

    config = {};  // 只在Page實例中存在的配置數據,對應於原生的page.json文件

    data = {};  // 頁面所需數據均需在這裏聲明,可用於模板數據綁定

    components = {};  // 聲明頁面中所引用的組件,或聲明組件中所引用的子組件

    mixins = [];  // 聲明頁面所引用的Mixin實例

    computed = {};  // 聲明計算屬性(詳見後文介紹)

    watch = {};  // 聲明數據watcher(詳見後文介紹)

    methods = {};  // 聲明頁面wxml中標籤的事件處理函數。注意,此處只用於聲明頁面wxml中標籤的bind、catch事件,自定義方法需以自定義方法的方式聲明

    events = {};  // 聲明組件之間的事件處理函數
}
// 錯誤示例

import wepy from 'wepy';

export default class MyComponent extends wepy.component {
    methods = {
        bindtap () {
            let rst = this.commonFunc();
            // doSomething
        },

        bindinput () {
            let rst = this.commonFunc();
            // doSomething
        },

        //錯誤:普通自定義方法不能放在methods對象中
        customFunction () {
            return 'sth.';
        }
    };

}
// 正確示例

import wepy from 'wepy';

export default class MyComponent extends wepy.component {
    methods = {
        bindtap () {
            let rst = this.commonFunc();
            // doSomething
        },

        bindinput () {
            let rst = this.commonFunc();
            // doSomething
        },
    }

    //正確:普通自定義方法在methods對象外聲明,與methods平級
    customFunction () {
        return 'sth.';
    }

}
/**
project
└── src
    ├── components
    |   └── child.wpy
    ├── pages
    |   ├── index.wpy    index 頁面配置、結構、樣式、邏輯
    |   └── log.wpy      log 頁面配置、結構、樣式、邏輯
    └──app.wpy           小程序配置項(全局公共配置、公共樣式、聲明鉤子等)
**/
// index.wpy

<template>
    <!-- 以`<script>`腳本部分中所聲明的組件ID爲名命名自定義標籤,從而在`<template>`模板部分中插入組件 -->
    <child></child>
</template>

<script>
    import wepy from 'wepy';
    //引入組件文件
    import Child from '../components/child';

    export default class Index extends wepy.page {
        //聲明組件,分配組件id爲child
        components = {
            child: Child
        };
    }
</script>


<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>
/**
project
└── src
    ├── components
    |   └── child.wpy
    ├── pages
    |   ├── index.wpy    index 頁面配置、結構、樣式、邏輯
    |   └── log.wpy      log 頁面配置、結構、樣式、邏輯
    └──app.wpy           小程序配置項(全局樣式配置、聲明鉤子等)
**/

// index.wpy

<template>
    <!-- 注意,使用for屬性,而不是使用wx:for屬性 -->
    <repeat for="{{list}}" key="index" index="index" item="item">
        <!-- 插入<script>腳本部分所聲明的child組件,同時傳入item -->
        <child :item="item"></child>
    </repeat>
</template>

<script>
    import wepy from 'wepy';
    // 引入child組件文件
    import Child from '../components/child';

    export default class Index extends wepy.page {
        components = {
            // 聲明頁面中要使用到的Child組件的ID爲child
            child: Child
        }

        data = {
            list: [{id: 1, title: 'title1'}, {id: 2, title: 'title2'}]
        }
    }
</script>


  data = {
      a: 1
  }

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

經過監聽器watcher可以監聽到任何屬性的更新。監聽器在watch對象中聲明,類型爲函數,函數名與須要被監聽的data對象中的屬性同名,每當被監聽的屬性改變一次,監聽器函數就會被自動調用執行一次。小程序

data = {
      num: 1
  }
// 監聽器函數名必須跟須要被監聽的data對象中的屬性num同名,
  // 其參數中的newValue爲屬性改變後的新值,oldValue爲改變前的舊值
  watch = {
      num (newValue, oldValue) {
          console.log(`num value: ${oldValue} -> ${newValue}`)
      }
  }

  // 每當被監聽的屬性num改變一次,對應的同名監聽器函數num()就被自動調用執行一次
  onLoad () {
      setInterval(() => {
          this.num++;
          this.$apply();
      }, 1000)
  }


props = {
    fromShopCar: Number
  }

props傳值sass

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

在父組件template模板部分的組件標籤中,使用子組件props對象中所聲明的屬性名做爲其屬性名來接收父組件傳遞的值。babel

<child title="mytitle"></child>

// child.wpy
props = {
    title: String
};

onLoad () {
    console.log(this.title); // mytitle
}


// parent.wpy

<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基類提供 b r o a d c a s t broadcast、 emit、$invoke三個方法用於組件之間的通訊和交互app

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
}

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

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

.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 組件內容分發插槽

在Panel組件中有如下模板:

<view class="panel">
    <slot name="title">默認標題</slot>
    <slot name="content">默認內容</slot>
</view>
在父組件中使用Panel子組件時,能夠這樣使用:

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


// mixins/test.js
import wepy from 'wepy';

export default class TestMixin extends wepy.mixin {
    data = {
        foo: 'foo defined by page',
        bar: 'bar defined by testMix'
    };
    methods = {
    tap () {
      console.log('mix tap');
    }
  }
}

// pages/index.wpy
import wepy from 'wepy';
import TestMixin from './mixins/test';

export default class Index extends wepy.page {
    data = {
        foo: 'foo defined by index'
    };
    mixins = [TestMixin ];
    onShow() {
        console.log(this.foo); // foo defined by index
        console.log(this.bar); // bar defined by testMix
    }
}

// mixins/test.js
import wepy from 'wepy';

export default class TestMixin extends wepy.mixin {
    methods = {
        tap () {
            console.log('mixin tap');
        }
    };
    onShow() {
        console.log('mixin onshow');
    }
}

// pages/index.wpy
import wepy from 'wepy';
import TestMixin from './mixins/test';

export default class Index extends wepy.page {

    mixins = [TestMixin];
    methods = {
        tap () {
            console.log('index tap');
        }
    };
    onShow() {
        console.log('index onshow');
    }
}


// index onshow
// mixin onshow
// ----- when tap
// index tap
// mixin tap


import wepy from 'wepy';

export default class extends wepy.app {
    constructor () {
        // this is not allowed before super()
        super();
        // 攔截request請求
        this.intercept('request', {
            // 發出請求時的回調函數
            config (p) {
                // 對全部request請求中的OBJECT參數對象統一附加時間戳屬性
                p.timestamp = +new Date();
                console.log('config request: ', p);
                // 必須返回OBJECT參數對象,不然沒法發送請求到服務端
                return p;
            },

            // 請求成功後的回調函數
            success (p) {
                // 能夠在這裏對收到的響應數據對象進行加工處理
                console.log('request success: ', p);
                // 必須返回響應數據對象,不然後續沒法對響應數據進行處理
                return p;
            },

            //請求失敗後的回調函數
            fail (p) {
                console.log('request fail: ', p);
                // 必須返回響應數據對象,不然後續沒法對響應數據進行處理
                return p;
            },

            // 請求完成時的回調函數(請求成功或失敗都會被執行)
            complete (p) {
                console.log('request complete: ', p);
            }
        });
    }
}

WePY髒數據檢查流程

// 原生代碼:

wx.request({
    url: 'xxx',
    success: function (data) {
        console.log(data);
    }
});
// WePY 使用方式, 須要開啓 Promise 支持,參考開發規範章節
wepy.request('xxxx').then((d) => console.log(d));

// async/await 的使用方式, 須要開啓 Promise 和 async/await 支持,參考 WIKI
async function request () {
   let d = await wepy.request('xxxxx');
   console.log(d);
}

// 原生的事件傳參方式:

<view data-id="{{index}}" data-title="wepy" data-other="otherparams" bindtap="tapName"> Click me! </view>

Page({
    tapName: function (event) {
        console.log(event.currentTarget.dataset.id)// output: 1
        console.log(event.currentTarget.dataset.title)// output: wepy
        console.log(event.currentTarget.dataset.other)// output: otherparams
    }
});

// WePY 1.1.8之後的版本,只容許傳string。

<view @tap="tapName({{index}}, 'wepy', 'otherparams')"> Click me! </view>

methods: {
    tapName (id, title, other, event) {
        console.log(id, title, other)// output: 1, wepy, otherparams
    }
}

// 原生代碼:

<view> {{ message }} </view>

onLoad: function () {
    this.setData({message: 'hello world'});
}


// WePY
<view> {{ message }} </view>

onLoad () {
    this.message = 'hello world';
}

// 原生代碼:

<!-- item.wxml -->
<template name="item">
  <text>{{text}}</text>
</template>

<!-- index.wxml -->
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>

<!-- index.js -->
var item = require('item.js')
// WePY
<!-- /components/item.wpy -->
 <text>{{text}}</text>

<!-- index.wpy -->
<template>
    <com></com>
</template>
<script>
    import wepy from 'wepy';
    import Item from '../components/item';
    export default class Index extends wepy.page {
        components = { com: Item }
    }
</script>

請點贊!由於你的鼓勵是我寫做的最大動力!

官方微信公衆號

吹逼交流羣:711613774

吹逼交流羣

相關文章
相關標籤/搜索