用戶
 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

掃一掃,登錄網站

小程序社區 首頁 教程 查看內容

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

Rolan 2019-6-24 00:48

compilers: compilers為1.3.1版本之后的功能,如果需要使用其它語法,請先配置compilers,然后再安裝相應的compilers。目前支持wepy-compiler-less, wepy-compiler-postcss,wepy-compiler-sass、wepy-compiler-ba ...

compilers: compilers為1.3.1版本之后的功能,如果需要使用其它語法,請先配置compilers,然后再安裝相應的compilers。目前支持wepy-compiler-less, wepy-compiler-postcss,wepy-compiler-sass、wepy-compiler-babel、wepy-compiler-pug,其他compiler持續開發中......

plugins: plugins為1.1.6版本之后的功能,目前支持js壓縮wepy-plugin-ugliyjs、圖片壓縮wepy-plugin-imagemin,其他plugin持續開發中......

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

<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實例。

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傳值

靜態傳值為父組件向子組件傳遞常量數據,因此只能傳遞String字符串類型。

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

<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基類提供broadcast、emit、$invoke三個方法用于組件之間的通信和交互

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表示事件后綴。

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

.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>

請點贊!因為你的鼓勵是我寫作的最大動力!

鮮花
鮮花
雞蛋
雞蛋
分享至 : QQ空間
收藏
原作者: 達叔小生 來自: 簡書
致青春APP