小程序開發(fā)之wepy


title: 小程序教程之wepy

參考文檔
  1. 中文文檔:https://tencent.github.io/wepy/document.html#/?id=app%e5%b0%8f%e7%a8%8b%e5%ba%8f%e5%ae%9e%e4%be%8b
  2. github:https://github.com/Tencent/wepy
  3. 微信小程序開發(fā)資源導(dǎo)航:http://www.yimijili.com/xcxwzdh.html
  4. over
VSCode自動(dòng)補(bǔ)齊Vue語(yǔ)法

打卡VScode郁油、首選項(xiàng) 什猖、設(shè)置兜材,或者直接Comand+的榛,快捷鍵

補(bǔ)全的語(yǔ)法為類Vue語(yǔ)法

用戶設(shè)置一欄中改成:

// {
//     "window.zoomLevel": 0,
//     "editor.fontSize": 16,
//     "files.associations": {
//         "*.wpy": "vue",
//         "*.wxss": "css",
//         "*.wxml": "html"
//     }
// }

// Place your settings in this file to overwrite the default settings
{

// 配置 glob 模式以排除文件和文件夾字旭。
"files.exclude": {
  "**/.git": true,
  "**/.svn": true,
  "**/.hg": true,
  "**/CVS": true,
  "**/.DS_Store": true,
  // "**/node_modules": true,
  "**/bower_components": true
  // "**/dist": true
},
// 配置語(yǔ)言的文件關(guān)聯(lián)(如: "*.extension": "html")。這些關(guān)聯(lián)的優(yōu)先級(jí)高于已安裝語(yǔ)言的默認(rèn)關(guān)聯(lián)温治。
"files.associations": {
  "*.vue": "vue",
  "*.wpy": "vue",
  "*.wxss": "postcss",
  "*.tpl": "vue",
  "*.md@xxx": "markdown",
  "*.wepy": "vue"
},
// 一個(gè)制表符等于的空格數(shù)悠菜。該設(shè)置在 `editor.detectIndentation` 啟用時(shí)根據(jù)文件內(nèi)容進(jìn)行重寫。
"editor.tabSize": 2,
// 當(dāng)打開文件時(shí)抓歼,將基于文件內(nèi)容檢測(cè) "editor.tabSize" 和 "editor.insertSpaces"讥此。
"editor.detectIndentation": false,
"window.zoomLevel": 1,
"editor.wordWrap": "on",
"workbench.iconTheme": "vs-seti",
"editor.wordSeparators": "`~!@#$%^&*()=+[{]}\\|;:'\",.<>/?。",
"editor.minimap.enabled": true,
// 控制鍵入時(shí)是否應(yīng)自動(dòng)顯示建議
"editor.quickSuggestions": {
  "other": true,
  "comments": true,
  "strings": true
},
// 配置 glob 模式以在搜索中排除文件和文件夾锭部。從 files.exclude 設(shè)置中繼承所有 glob 模式。
"search.exclude": {
  "**/node_modules": true,
  "**/bower_components": true,
  "**/dist": true
},
// 控制編輯器是否應(yīng)呈現(xiàn)縮進(jìn)參考線
"editor.renderIndentGuides": true,
"emmet.syntaxProfiles": {
  "vue-html": "html",
  "vue": "html"
},

// 配置內(nèi)置 HTML 語(yǔ)言支持是否建議 Angular V1 標(biāo)記和屬性面褐。
"html.suggest.angular1": false,
// 自動(dòng)更新擴(kuò)展
"extensions.autoUpdate": true,
// 對(duì)屬性進(jìn)行換行拌禾。
"html.format.wrapAttributes": "auto",
// Link file types to the beautifier type
"beautify.language": {
  "js": {
    "type": [
      "javascript",
      "json"
    ],
    "filename": [
      ".jshintrc",
      ".jsbeautify",
      ".eslintrc.js"
    ]
  },
  "css": [
    "css",
    "scss"
  ],
  "html": [
    "htm",
    "html"
  ]
},
"git.enabled": false,
"editor.renderControlCharacters": true,
"typescript.check.npmIsInstalled": false,
"extensions.ignoreRecommendations": false,
// 覆蓋當(dāng)前所選顏色主題的顏色。 此為實(shí)驗(yàn)性設(shè)置展哭,因?yàn)橄乱话姹局袑⒏念伾Q湃窍。
// "workbench.experimental.colorCustomizations": {
//   "statusBarBackground": "#666666",
//   "panelBackground": "#555555",
//   "sideBarBackground": "#444444"
// }
// When enabled, emmet abbreviations are expanded when pressing TAB.
"emmet.triggerExpansionOnTab": true,
"workbench.panel.location": "bottom",
  "editor.fontSize": 16
}

over

快速入門
  1. 初始化項(xiàng)目

    1.全局安裝或者更新wepy命令行工具
    $ npm install wepy-cli -g
    
    2.在開發(fā)目錄中生成Demo開發(fā)項(xiàng)目
    wepy new myproject
    # 1.7.0之后的版本使用 wepy init standard myproject 初始化項(xiàng)目,使用 wepy list 查看項(xiàng)目模板
    
    3.編譯
    $ cd project
    $ npm install 
    $ wepy build --watch 或者
    $ npm run dev
    
  2. 項(xiàng)目目錄

    ├── dist                   微信開發(fā)者工具指定的目錄(該目錄由WePY的build指令自動(dòng)編譯生成匪傍,請(qǐng)不要直接修改該目錄下的文件)
    ├── node_modules           
    ├── src                    代碼編寫的目錄(該目錄為使用WePY后的開發(fā)目錄)
    |   ├── components         WePY組件目錄(組件不屬于完整頁(yè)面您市,僅供完整頁(yè)面或其他組件引用)
    |   |   ├── com_a.wpy      可復(fù)用的WePY組件a
    |   |   └── com_b.wpy      可復(fù)用的WePY組件b
    |   ├── pages              WePY頁(yè)面目錄(屬于完整頁(yè)面)
    |   |   ├── index.wpy      index頁(yè)面(經(jīng)build后,會(huì)在dist目錄下的pages目錄生成index.js役衡、index.json茵休、index.wxml和index.wxss文件)
    |   |   └── other.wpy      other頁(yè)面(經(jīng)build后,會(huì)在dist目錄下的pages目錄生成other.js手蝎、other.json榕莺、other.wxml和other.wxss文件)
    |   └── app.wpy            小程序配置項(xiàng)(全局?jǐn)?shù)據(jù)、樣式棵介、聲明鉤子等钉鸯;經(jīng)build后,會(huì)在dist目錄下生成app.js邮辽、app.json和app.wxss文件)
    └── package.json           項(xiàng)目的package配置
    
  3. 重要提醒

    1. 微信開發(fā)者工具添加dist目錄
    2. 微信開發(fā)者工具關(guān)閉ES6轉(zhuǎn)ES5
    3. 運(yùn)行 wepy build --watch 實(shí)時(shí)編譯
    唠雕。。吨述。
    
  4. 代碼高亮和代碼規(guī)范

  5. over

主要功能特性
  1. 開發(fā)模式轉(zhuǎn)換

    原生代碼
    //index.js
    
    //獲取應(yīng)用實(shí)例
    var app = getApp()
    
    //通過(guò)Page構(gòu)造函數(shù)創(chuàng)建頁(yè)面邏輯
    Page({
        //可用于頁(yè)面模板綁定的數(shù)據(jù)
        data: {
            motto: 'Hello World',
            userInfo: {}
        },
    
        //事件處理函數(shù)
        bindViewTap: function() {
            console.log('button clicked')
        },
    
        //頁(yè)面的生命周期函數(shù)
        onLoad: function () {
            console.log('onLoad')
        }
    

    基于wepy的代碼

    //index.wpy中的<script>部分
    
    import wepy from 'wepy';
    
    //通過(guò)繼承自wepy.page的類創(chuàng)建頁(yè)面邏輯
    export default class Index extends wepy.page {
        //可用于頁(yè)面模板綁定的數(shù)據(jù)
        data = {
            motto: 'Hello World',
            userInfo: {}
        };
    
        //事件處理函數(shù)(集中保存在methods對(duì)象中)
        methods = {
            bindViewTap () {
                console.log('button clicked');
            }
        };
    
        //頁(yè)面的生命周期函數(shù)
        onLoad() {
            console.log('onLoad');
        };
    }
    
  2. 支持組件式開發(fā)

    // index.wpy
    
    <template>
        <view>
            <panel>
                <h1 slot="title"></h1>
            </panel>
            <counter1 :num="myNum"></counter1>
            <counter2 :num.sync="syncNum"></counter2>
            <list :item="items"></list>
        </view>
    </template>
    
    <script>
    import wepy from 'wepy';
    //引入List岩睁、Panel和Counter組件
    import List from '../components/list';
    import Panel from '../components/panel';
    import Counter from '../components/counter';
    
    export default class Index extends wepy.page {
        //頁(yè)面配置
        config = {
            "navigationBarTitleText": "test"
        };
    
        //聲明頁(yè)面中將要使用到的組件
        components = {
            panel: Panel,
            counter1: Counter,
            counter2: Counter,
            list: List
        };
    
        //可用于頁(yè)面模板中綁定的數(shù)據(jù)
        data = {
            myNum: 50,
            syncNum: 100,
            items: [1, 2, 3, 4]
        }
    }
    </script>
    

    ?

  3. 支持加載外部npm包

  4. 單文件模式,目錄結(jié)構(gòu)更加清晰揣云,開發(fā)方便

  5. WePY中則使用了單文件模式笙僚,將原生小程序app實(shí)例的3個(gè)文件統(tǒng)一為app.wpy,page頁(yè)面的4個(gè)文件統(tǒng)一為page.wpy

  6. 默認(rèn)babel編譯灵再,支持ES7新特性

  7. 針對(duì)原生API進(jìn)行優(yōu)化肋层,如wx.request的并發(fā)問(wèn)題等亿笤。

  8. over

進(jìn)階介紹
  1. wepy.config.js配置文件

    執(zhí)行wepy new demo 后,會(huì)生成類似下面的配置文件

    let prod = process.env.NODE_ENV === 'production';
    module.exports = {
        'output': 'dist',
        'source': 'src',
        'wpyExt': '.wpy',
        'compilers': {
            less: {
                'compress': true
            },
            /*sass: {
                'outputStyle': 'compressed'
            },*/
            babel: {
                'presets': [
                    'es2015',
                    'stage-1'
                ],
                'plugins': [
                    'transform-export-extensions',
                    'syntax-export-extensions',
                    'transform-runtime'
                ]
            }
        },
        'plugins': {
        }
    };
    
    if (prod) {
        // 壓縮sass
        module.exports.compilers['sass'] = {'outputStyle': 'compressed'};
    
        // 壓縮less
        module.exports.compilers['less'] = {'compress': true};
    
        // 壓縮js
        module.exports.plugins = {
            'uglifyjs': {
                filter: /\.js$/,
                config: {
                }
            },
            'imagemin': {
                filter: /\.(jpg|png|jpeg)$/,
                config: {
                    'jpg': {
                        quality: 80
                    },
                    'png': {
                        quality: 80
                    }
                }
            }
        };
    }
    
    wpyExt: 默認(rèn)值為.wpy
    compilers: sass\less\stylus\babel\typscript
    plugins
    
    

    ?

  2. .wepy文件說(shuō)明

    .wepy 文件編譯過(guò)程:

    圖片

    .wpy文件分為三個(gè)部分

    • 腳本部分栋猖,即<script></script>標(biāo)簽中的內(nèi)容净薛,又可分為兩個(gè)部分:

    邏輯部分,除了config對(duì)象之外的部分蒲拉,對(duì)應(yīng)于原生的.js文件肃拜;

    配置部分,即config對(duì)象雌团,對(duì)應(yīng)于原生的.json文件燃领。

    • 結(jié)構(gòu)部分,即<template></template>模板部分锦援,對(duì)應(yīng)于原生的.wxml文件猛蔽。
  • 樣式部分,即<style></style>樣式部分灵寺,對(duì)應(yīng)于原生的.wxss文件曼库。

  • .wpy文件中的scripttemplate略板、style這三個(gè)標(biāo)簽都支持langsrc屬性毁枯,lang決定了其代碼編譯過(guò)程,src決定是否外聯(lián)代碼叮称,存在src屬性且有效時(shí)种玛,會(huì)忽略內(nèi)聯(lián)代碼。

  • 各標(biāo)簽對(duì)應(yīng)的lang值如下表所示:

    標(biāo)簽 lang默認(rèn)值 lang支持值
    style css css瓤檐、less蒂誉、scssstylus
    template wxml wxml距帅、xml右锨、pug(原jade)
    script babel babelTypeScript
  1. over

  2. over

腳本部分介紹
  1. 小程序入口app.wpy

    <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>
    入口文件app.wpy中所聲明的小程序?qū)嵗^承自wepy.app類碌秸,包含一個(gè)config屬性和其它全局屬性绍移、方法、事件讥电。其中config屬性對(duì)應(yīng)原生的app.json文件蹂窖,build編譯時(shí)會(huì)根據(jù)config屬性自動(dòng)生成app.json文件,如果需要修改config中的內(nèi)容恩敌,請(qǐng)使用微信提供的相關(guān)API瞬测。
    
  2. 頁(yè)面page.wpy

    <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>
    
    屬性 說(shuō)明
    config 頁(yè)面配置對(duì)象,對(duì)應(yīng)于原生的page.json文件,類似于app.wpy中的config
    components 頁(yè)面組件列表對(duì)象月趟,聲明頁(yè)面所引入的組件列表
    data 頁(yè)面渲染數(shù)據(jù)對(duì)象灯蝴,存放可用于頁(yè)面模板綁定的渲染數(shù)據(jù)
    methods wxml事件處理函數(shù)對(duì)象,存放響應(yīng)wxml中所捕獲到的事件的函數(shù)孝宗,如bindtap穷躁、bindchange
    events WePY組件事件處理函數(shù)對(duì)象,存放響應(yīng)組件之間通過(guò)$broadcast因妇、$emit问潭、$invoke所傳遞的事件的函數(shù)
    其它 小程序頁(yè)面生命周期函數(shù),如onLoad婚被、onReady等狡忙,以及其它自定義的方法與屬性
  3. 組件com.wpy

    <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>
    組件文件com.wpy中所聲明的組件實(shí)例繼承自wepy.component類,除了不需要config配置以及頁(yè)面特有的一些生命周期函數(shù)之外址芯,其屬性與頁(yè)面屬性大致相同灾茁。
    
  4. over

實(shí)例
  1. 實(shí)例

    wepy中,小程序被分為三個(gè)實(shí)例:

    import wepy from 'wepy';
    
    // 聲明一個(gè)App小程序?qū)嵗?export default class MyAPP extends wepy.app {
    }
    
    // 聲明一個(gè)Page頁(yè)面實(shí)例
    export default class IndexPage extends wepy.page {
    }
    
    // 聲明一個(gè)Component組件實(shí)例
    export default class MyComponent extends wepy.component {
    }
    
  2. App小程序?qū)嵗?/p>

    在Page頁(yè)面實(shí)例中是复,可以通過(guò)this.$parent來(lái)訪問(wèn)App實(shí)例删顶。

  3. Page頁(yè)面實(shí)例和Component組件實(shí)例

    Page實(shí)際上繼承自Component組件竖螃,即Page也是組建淑廊。

    import wepy from 'wepy';
    
    // export default class MyPage extends wepy.page {
    export default class MyComponent extends wepy.component {
        customData = {}  // 自定義數(shù)據(jù)
    
        customFunction () {}  //自定義方法
    
        onLoad () {}  // 在Page和Component共用的生命周期函數(shù)
    
        onShow () {}  // 只在Page中存在的頁(yè)面生命周期函數(shù)
    
        config = {};  // 只在Page實(shí)例中存在的配置數(shù)據(jù),對(duì)應(yīng)于原生的page.json文件
    
        data = {};  // 頁(yè)面所需數(shù)據(jù)均需在這里聲明特咆,可用于模板數(shù)據(jù)綁定
    
        components = {};  // 聲明頁(yè)面中所引用的組件季惩,或聲明組件中所引用的子組件
    
        mixins = [];  // 聲明頁(yè)面所引用的Mixin實(shí)例
    
        computed = {};  // 聲明計(jì)算屬性(詳見(jiàn)后文介紹)
    
        watch = {};  // 聲明數(shù)據(jù)watcher(詳見(jiàn)后文介紹)
    
        methods = {};  // 聲明頁(yè)面wxml中標(biāo)簽的事件處理函數(shù)。注意腻格,此處只用于聲明頁(yè)面wxml中標(biāo)簽的bind画拾、catch事件,自定義方法需以自定義方法的方式聲明
    
        events = {};  // 聲明組件之間的事件處理函數(shù)
    }
    
    WePY中的methods屬性只能聲明頁(yè)面wxml標(biāo)簽的bind菜职、catch事件青抛,不能聲明自定義方法,這與Vue中的用法是不一致的
    

    ?

  4. ?

組件
  1. WePY中實(shí)現(xiàn)了小程序的組件化開發(fā)酬核,組件的所有業(yè)務(wù)與功能在組件本身實(shí)現(xiàn)蜜另,組件與組件之間彼此隔離

  2. 普通組件引用

    當(dāng)頁(yè)面需要引入子組件時(shí),

    必須 在.wpy文件的<script>腳本部分先import組件文件嫡意;

    然后 在components對(duì)象中給組件聲明唯一的組件ID;

    接著在<template>模板部分中添加以components對(duì)象中所聲明的組件ID進(jìn)行命名的自定義標(biāo)簽以插入組件;

    如下:

    /**
    project
    └── src
        ├── components
        |   └── child.wpy
        ├── pages
        |   ├── index.wpy    index 頁(yè)面配置欠气、結(jié)構(gòu)铁孵、樣式、邏輯
        |   └── log.wpy      log 頁(yè)面配置、結(jié)構(gòu)耸序、樣式忍些、邏輯
        └──app.wpy           小程序配置項(xiàng)(全局公共配置、公共樣式佑吝、聲明鉤子等)
    **/
    
    // index.wpy
    
    <template>
        <!-- 以`<script>`腳本部分中所聲明的組件ID為名命名自定義標(biāo)簽坐昙,從而在`<template>`模板部分中插入組件 -->
        <child></child>
    </template>
    
    <script>
        import wepy from 'wepy';
        //引入組件文件
        import Child from '../components/child';
    
        export default class Index extends wepy.component {
            //聲明組件,分配組件id為child
            components = {
                child: Child
            };
        }
    </script>
    
  3. 組件的循環(huán)渲染

    當(dāng)需要循環(huán)渲染W(wǎng)ePY組件時(shí)(類似于通過(guò)wx:for循環(huán)渲染原生的wxml標(biāo)簽)芋忿,必須使用WePY定義的輔助標(biāo)簽<repeat>

    
    // index.wpy
    
    <template>
        <!-- 注意炸客,使用for屬性,而不是使用wx:for屬性 -->
        <repeat for="{{list}}" key="index" index="index" item="item">
            <!-- 插入<script>腳本部分所聲明的child組件戈钢,同時(shí)傳入item -->
            <child :item="item"></child>
        </repeat>
    </template>
    
    <script>
        import wepy from 'wepy';
        // 引入child組件文件
        import Child from '../components/child';
    
        export default class Index extends wepy.component {
            components = {
                // 聲明頁(yè)面中要使用到的Child組件的ID為child
                child: Child
            }
    
            data = {
                list: [{id: 1, title: 'title1'}, {id: 2, title: 'title2'}]
            }
        }
    </script>
    
  4. computed計(jì)算屬性

    computed計(jì)算屬性痹仙,是一個(gè)有返回值的函數(shù),可直接被當(dāng)做綁定數(shù)據(jù)來(lái)使用殉了。需要注意的是开仰,只要是組件中有任何數(shù)據(jù)發(fā)生了改變,那么所有計(jì)算屬性就都會(huì)被重新計(jì)算

    data = {
          a: 1
      }
    
      // 計(jì)算屬性aPlus薪铜,在腳本中可通過(guò)this.aPlus來(lái)引用众弓,在模板中可通過(guò){{ aPlus }}來(lái)插值
      computed = {
          aPlus () {
              return this.a + 1
          }
      }
    
  5. watcher監(jiān)聽(tīng)器

    通過(guò)監(jiān)聽(tīng)器watcher能夠監(jiān)聽(tīng)到任何屬性的更新。監(jiān)聽(tīng)器在watch對(duì)象中聲明隔箍,類型為函數(shù)谓娃,函數(shù)名與需要被監(jiān)聽(tīng)的data對(duì)象中的屬性同名,每當(dāng)被監(jiān)聽(tīng)的屬性改變一次蜒滩,監(jiān)聽(tīng)器函數(shù)就會(huì)被自動(dòng)調(diào)用執(zhí)行一次

    data = {
          num: 1
      }
    
      // 監(jiān)聽(tīng)器函數(shù)名必須跟需要被監(jiān)聽(tīng)的data對(duì)象中的屬性num同名滨达,
      // 其參數(shù)中的newValue為屬性改變后的新值,oldValue為改變前的舊值
      watch = {
          num (newValue, oldValue) {
              console.log(`num value: ${oldValue} -> ${newValue}`)
          }
      }
    
      // 每當(dāng)被監(jiān)聽(tīng)的屬性num改變一次俯艰,對(duì)應(yīng)的同名監(jiān)聽(tīng)器函數(shù)num()就被自動(dòng)調(diào)用執(zhí)行一次
      onLoad () {
          setInterval(() => {
              this.num++;
              this.$apply();
          }, 1000)
      }
    
  6. props傳值

    傳值包括三種:父組件向子組件傳值捡遍,子組件向父組件傳值,雙向傳值

    props傳值在WePY中屬于父子組件之間傳值的一種機(jī)制竹握,包括靜態(tài)傳值與動(dòng)態(tài)傳值画株。

    <child title="mytitle"></child>
    
    // child.wpy
    props = {
        title: String
    };
    
    onLoad () {
        console.log(this.title); // mytitle
    }
    

    動(dòng)態(tài)傳值,雙向綁定

    動(dòng)態(tài)傳值是指父組件向子組件傳遞動(dòng)態(tài)數(shù)據(jù)內(nèi)容啦辐,父子組件數(shù)據(jù)完全獨(dú)立互不干擾谓传。但可以通過(guò)使用.sync修飾符來(lái)達(dá)到父組件數(shù)據(jù)綁定至子組件的效果,也可以通過(guò)設(shè)置子組件props的twoWay: true來(lái)達(dá)到子組件數(shù)據(jù)綁定至父組件的效果昧甘。那如果既使用.sync修飾符良拼,同時(shí)子組件props中添加的twoWay: true時(shí),就可以實(shí)現(xiàn)數(shù)據(jù)的雙向綁定了充边。

    // parent.wpy
    
    <child :title="parentTitle" :syncTitle.sync="parentTitle" :twoWayTitle="parentTitle"></child>
    
    data = {
        parentTitle: 'p-title'
    };
    

// child.wpy

props = {
// 靜態(tài)傳值
title: String,

   // 父向子單向動(dòng)態(tài)傳值
   syncTitle: {
       type: String,
       default: 'null'
   },

   twoWayTitle: {
       type: Number,
       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時(shí)庸推,子組件props中的屬性值改變時(shí)常侦,會(huì)同時(shí)改變父組件對(duì)應(yīng)的值
   this.$parent.parentTitle = 'p-title-changed';
   this.$parent.$apply();
   console.log(this.title); // 'c-title';
   console.log(this.syncTitle); // 'p-title-changed' --- 有.sync修飾符的props屬性值,當(dāng)在父組件中改變時(shí)贬媒,會(huì)同時(shí)改變子組件對(duì)應(yīng)的值聋亡。

}


?

7. 組件通信與交互

`wepy.component`基類提供`$broadcast`、`$emit`际乘、`$invoke`三個(gè)方法用于組件之間的通信和交互坡倔,如:

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

用于監(jiān)聽(tīng)組件之間的通信與交互事件的事件處理函數(shù)需要寫在組件和頁(yè)面的events對(duì)象中,如:

import wepy from 'wepy'

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

    data = {};

    methods = {};

    // events對(duì)象中所聲明的函數(shù)為用于監(jiān)聽(tīng)組件之間的通信與交互事件的事件處理函數(shù)
    events = {
        'some-event': (p1, p2, p3, $event) => {
               console.log(`${this.$name} receive ${$event.name} from ${$event.source.$name}`);
        }
    };
    // Other properties
}

$broadcast 廣播

$emit 出發(fā)

$invoke 直接調(diào)用

?

  1. 組件自定義事件處理函數(shù)

    可以通過(guò)使用.user修飾符為自定義組件綁定事件脖含,如:@customEvent.user="myFn" 其中罪塔,@表示事件修飾符,customEvent 表示事件名稱养葵,.user表示事件后綴征堪。

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

    • .default: 綁定小程序冒泡型事件,如bindtap关拒,.default后綴可省略不寫佃蚜;
    • .stop: 綁定小程序捕獲型事件,如catchtap着绊;
    • .user: 綁定用戶自定義組件事件谐算,通過(guò)$emit觸發(fā)。注意归露,如果用了自定義事件洲脂,則events中對(duì)應(yīng)的監(jiān)聽(tīng)函數(shù)不會(huì)再執(zhí)行。
    // 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>
    

    ?

  2. slot組件內(nèi)容分發(fā)插槽

    相當(dāng)于占位符

    在Panel組件中有以下模板
    <view class="panel">
        <slot name="title">默認(rèn)標(biāo)題</slot>
        <slot name="content">默認(rèn)內(nèi)容</slot>
    </view>
    在父組件中使用Pannel子組件時(shí)靶擦,可以這樣使用:
    <panel>
        <view slot="title">新的標(biāo)題</view>
        <view slot="content">
            <text>新的內(nèi)容</text>
        </view>
    </panel>
    

    ?

  3. over

第三方組件

WePY允許使用基于WePY開發(fā)的第三方組件腮考,開發(fā)第三方組件規(guī)范請(qǐng)參考wepy-com-toast雇毫。

Mixin混合

混合可以將組之間的可復(fù)用部分抽離玄捕,從而在組件中使用混合時(shí),可以將混合的數(shù)據(jù)棚放,事件以及方法注入到組件之中枚粘。混合分分為兩種:

  • 默認(rèn)式混合
  • 兼容式混合
  1. 默認(rèn)式混合
  2. 兼容式混合
WXS
interceptor攔截器

over

數(shù)據(jù)綁定
  1. 原生小程序數(shù)據(jù)綁定方式

    this.setData({title: 'this is title'});
    
  2. wepy數(shù)據(jù)綁定方式

    WePY使用臟數(shù)據(jù)檢查對(duì)setData進(jìn)行封裝飘蚯,在函數(shù)運(yùn)行周期結(jié)束時(shí)執(zhí)行臟數(shù)據(jù)檢查馍迄,一來(lái)可以不用關(guān)心頁(yè)面多次setData是否會(huì)有性能上的問(wèn)題,二來(lái)可以更加簡(jiǎn)潔去修改數(shù)據(jù)實(shí)現(xiàn)綁定局骤,不用重復(fù)去寫setData方法

    this.title = 'this is title';
    

    需注意的是攀圈,在異步函數(shù)中更新數(shù)據(jù)的時(shí),必須手動(dòng)調(diào)用$apply方法峦甩,才會(huì)觸發(fā)臟數(shù)據(jù)檢查流程的運(yùn)行

    setTimeout(() => {
        this.title = 'this is title';
        this.$apply();
    }, 3000);
    

    ?

  3. wepy臟數(shù)據(jù)檢查流程

    ?

  4. over

其他優(yōu)化細(xì)節(jié)
  1. wx.request 接受參數(shù)修改
  2. 優(yōu)化事件參數(shù)傳遞
  3. 改變數(shù)據(jù)綁定方式
  4. 組件地帶模板和模塊

實(shí)戰(zhàn)開發(fā)

文件結(jié)構(gòu)
  1. src/components/config 文件夾結(jié)構(gòu)

    api.js 存放借口給
    config.js存放全局赘来、服務(wù)器地址等常量
    utils.js 存放 toast现喳、網(wǎng)絡(luò)請(qǐng)求等方法
    
  2. src/pages/diary文件夾結(jié)構(gòu)

暫無(wú)


  1. 微信開發(fā)者工具自定義編譯

    0.查看Network列表(在Console旁邊),該列表為當(dāng)前頁(yè)面所有接口犬辰,查看info發(fā)現(xiàn)嗦篱,Response返回值
    1.打開微信開發(fā)者工具
    2.在上方編譯處選擇 添加編譯模式
    3.自定義編譯條件
    模式名稱:便于記錄 日記詳情頁(yè)
    啟動(dòng)頁(yè)面:打開相應(yīng)頁(yè)面,會(huì)自動(dòng)生成 pages/diary/DiaryInfo
    啟動(dòng)參數(shù) catDiaryId=1513
    進(jìn)入場(chǎng)景 
    
  2. 頁(yè)面導(dǎo)航

  3. over

開發(fā)流程
  1. 熟悉目錄結(jié)構(gòu)
  2. 熟悉服務(wù)端接口流程
  3. 先開發(fā)網(wǎng)絡(luò)請(qǐng)求
  4. 構(gòu)造數(shù)據(jù)
  5. 拆解sketch原型幌缝,開始template頁(yè)面開發(fā)
布局

參考文獻(xiàn):http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

  1. 盒子模型
  2. Flex布局

wepy API
  1. wepy.app Class

    $wxapp:Object: this.$wxapp等同于getApp()灸促。
    
    $pages:List<Page>: 所有頁(yè)面列表
    
    $interceptors:List<Object>:所有攔截器列表
    
    use(middleWare:String|Function):使用中間件。
    
    
  2. wepy.component Class

    屬性
    
    $name:String: 組件名稱涵卵。
    $isComponent:Boolean:是否是組件浴栽,如果是頁(yè)面,此值為false轿偎。
    $wxpage:Object: 小程序原生page吃度。
    $parent:Page|App:組件的父組件,如果當(dāng)前是組件是Page對(duì)象贴硫,那么$parent的值為App對(duì)象椿每。
    $root:Page: 組件所在的Page對(duì)象,如果當(dāng)前組件是Page對(duì)象英遭,那么$root的值就是自己本身间护。
    $coms:List<Component>:組件的子組件列表。
    $mixins:Array[Mixin]:組件所注入的Mixin對(duì)象挖诸。
    data:Object: 組件需要綁定的數(shù)據(jù)汁尺。
    methods:List<Function>:組件需要響應(yīng)的事件列表。
    props:List<Props>:組件允許傳遞的props列表多律。
    events:List<Function>:組件通信時(shí)所需要的事件表現(xiàn)痴突。
    
    方法
    getCurrentPages():相當(dāng)于全局方法getCurrentPages()。
    $getComponent(com:String):通過(guò)組件名稱路徑查找組件對(duì)象狼荞。
    $invoke(com:String|Component):調(diào)用另一組件的方法辽装。
     // coma.js
      this.$invoke('./ComB', 'func1', 'p1', 'p2');
      this.$invoke('./ComB', 'func2', 'p1', 'p2');
    
      // comb.js
      export class ComB extends wepy.component {
          methods = {
              func1 (p1, p2, evt) {}
          },
          func2 (p1, p2) {}
      }
      
      $broadcast(eventName:String, [args]):組件發(fā)起一個(gè)廣播事件。
      // page1.js
      components = { ComA };
      this.$broadcast('broadcast-event', 'p1', 'p2');
    
      // coma.js
      events = {
          'broadcast-event': (p1, p2, event) {}
      }
      
      $emit(eventName:String, [args]):組件發(fā)起一個(gè)冒泡事件相味。
       // coma.js
      this.$emit('emit-event', 'p1', 'p2');
    
      // page1.js
      components = { ComA };
      events = {
          'emit-event': (p1, p2, event) => {}
      }
    
    $apply([func:Function]):組件發(fā)起臟檢查拾积。
    正常流程下,改變數(shù)據(jù)后丰涉,組件會(huì)在流程結(jié)束時(shí)自動(dòng)觸發(fā)臟檢查拓巧。 在異步或者回調(diào)流程中改變數(shù)據(jù)時(shí),需要手動(dòng)調(diào)用$apply方法一死。
    
    $nextTick([func:Function]):組件數(shù)據(jù)綁定完成后的回調(diào)事件肛度,v1.6.1以上可用。
    
  3. wepy.page Class

    頁(yè)面類投慈,繼承自wepy.component承耿,擁有頁(yè)面所有的屬性與方法策吠。
    $preload(key:String|Object, [value:Object]):給頁(yè)面加載preload數(shù)據(jù)
    $redirect(url:String|Object, [params:Object]):wx.redirectTo的封裝方法。
    this.$redirect('./page2', {a: 1, b: 2});
      this.$redirect({
          url: './pages?a=1&b=2'
      });
    

    ?

  4. wepy.event Class

  5. wepy.mixin Class

    Mixin基類瘩绒,用于復(fù)用不同組件中的相同功能猴抹。
    // mymixn.js
    export class MyMixin extends wepy.mixin {
        // my logic here
    }
    
    // mycom.js
    import MyMixin from './mymixin';
    export class MyCom extends wepy.component {
        mixins = [MyMixin];
    }
    
  6. over

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锁荔,隨后出現(xiàn)的幾起案子蟀给,更是在濱河造成了極大的恐慌,老刑警劉巖阳堕,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跋理,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡恬总,警方通過(guò)查閱死者的電腦和手機(jī)前普,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)壹堰,“玉大人拭卿,你說(shuō)我怎么就攤上這事〖溃” “怎么了峻厚?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)谆焊。 經(jīng)常有香客問(wèn)我惠桃,道長(zhǎng),這世上最難降的妖魔是什么辖试? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任辜王,我火速辦了婚禮,結(jié)果婚禮上罐孝,老公的妹妹穿的比我還像新娘呐馆。我一直安慰自己,他們只是感情好肾档,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布摹恰。 她就那樣靜靜地躺著辫继,像睡著了一般怒见。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上姑宽,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天遣耍,我揣著相機(jī)與錄音,去河邊找鬼炮车。 笑死舵变,一個(gè)胖子當(dāng)著我的面吹牛酣溃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纪隙,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼赊豌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了绵咱?” 一聲冷哼從身側(cè)響起碘饼,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悲伶,沒(méi)想到半個(gè)月后艾恼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡麸锉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年钠绍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片花沉。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柳爽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碱屁,到底是詐尸還是另有隱情泻拦,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布忽媒,位于F島的核電站争拐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏晦雨。R本人自食惡果不足惜架曹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闹瞧。 院中可真熱鬧绑雄,春花似錦、人聲如沸奥邮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)洽腺。三九已至脚粟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蘸朋,已是汗流浹背核无。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留藕坯,地道東北人团南。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓噪沙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吐根。 傳聞我的和親對(duì)象是個(gè)殘疾皇子正歼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容