小程序


2018-12-22 wepy mpvue

wepy

小程序框架 wepy 文档

Github地址

快速入门

安装 wepy

npm install wepy-cli -g
1

在开发目录生成开发DEMO。

wepy new myproject
1

开发实时编译。

wepy build --watch
1

项目目录结构

dist
   node_modules
   src
       components
           com_a.wpy
           com_b.wpy
       pages
           index.wpy
           page2.wpy
       app.wpy
   package.json
1
2
3
4
5
6
7
8
9
10
11

代码规范:

  1. 变量与方法使用尽量使用驼峰式命名,避免使用 $ 开头。
    以 $ 开头的方法或者属性为框架内建方法或者属性,可以被使用,使用前请参考API文档。

  2. 入口,页面,组件的命名后缀为.wpy。外链的文件可以是其它后缀。
    请参考wpy文件说明

  3. 使用 ES6 语法开发。
    框架在 ES6 下开发,因此也需要使用 ES6 开发小程序,ES6中有大量的语法糖可以让我们的代码更加简洁高效。

  4. 使用 Promise
    框架默认对小程序提供的 API 全都进行了 Promise 处理,甚至可以直接使用 async/await 等新特性进行开发。

主要解决问题:

1. 开发模式转换

在原有的小程序的开发模式下进行再次封装,更贴近于现有 MVVM 框架开发模式。框架在开发过程中参考了一些现在框架的一些特性,并且融入其中,以下是使用 wepy 前后的代码对比图。
官方DEMO代码:

//index.js
//获取应用实例
var app = getApp()
Page({
  data: {
    motto: 'Hello World',
    userInfo: {}
  },
  //事件处理函数
  bindViewTap: function() {
    console.log('button clicked')
  },
  onLoad: function () {
    console.log('onLoad')
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

基于 wepy 的实现:

import wepy from 'wepy';
 
export default class Index extends wepy.page {
 
    data = {
        motto: 'Hello World',
        userInfo: {}
    };
    methods = {
        bindViewTap () {
            console.log('button clicked');
        }
    };
    onLoad() {
        console.log('onLoad');
    };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2. 支持组件化开发。

参见章节:组件
示例代码:

// index.wpy
<template>
    <view>
        <component id="pannel" path="pannel"></component>
        <component id="counter1" path="counter"></component>
        <component id="counter2" path="counter"></component>
        <component id="list" path="list"></component>
    </view>
</template>
<script>
import wepy from 'wepy';
import List from '../components/list';
import Panel from '../components/panel';
import Counter from '../components/counter';
 
export default class Index extends wepy.page {
 
    config = {
        "navigationBarTitleText": "test"
    };
    components = {
        panel: Panel,
        counter1: Counter,
        counter2: Counter,
        list: List
    };
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3. 单文件模式,使得目录结构更加清晰。

官方目录结构要求app必须有三个文件 app.json,app.js,app.wxss,页面有4个文件 index.json,index.js,index.wxml,index.wxss。而且文件必须同名。
所以使用wepy开发前后开发目录对比如下:
官方DEMO:

project
    pages
        index
            index.json
            index.js
            index.wxml
            index.wxss
        log
            log.json
            log.wxml
            log.js
            log.wxss
    app.js
    app.json
    app.wxss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

使用wepy框架后目录结构:

project
    src
        pages
            index.wpy
            log.wpy
        app.wpy
1
2
3
4
5
6
4. 默认使用 babel 编译,支持 ES6/7 的一些新特性。

用户可以通过修改 .wepyrc 配置文件,配置自己熟悉的babel环境进行开发。默认开启使用了一些新的特性如 promise,async/await 等等。
示例代码

import wepy from 'wepy';
 
export default class Index extends wepy.page {
 
    getData() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve({data: 123});
            }, 3000);
        });
    };
    async onLoad() {
        let data = await this.getData();
        console.log(data.data);
    };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

问题收集与解决

1. wepy 中使用 wx:if,只阻止视图渲染,不会阻止组件初始化。
2. 图片引入正常,但是无缘无故报错问题

原因:在于初始化的时候,变量还没渲染进去,导致src为错误的值。
解法:

<image wx:if="{{postData.avatar}}" class="avatar" src="{{postData.avatar}}"></image>
1
3. 微信小程序界面跳转传 json 对象,出现 object 对象变字串。

解法:
将 JSON 转成字符串传值 JSON.stringify(user);
将字符串转成对象接收 JSON.parse(options.userStr);

#传值 js (母页面)
personInfoAction: function(event) {
    var user = this.data.user;
    //将json转成字符串
    let userStr=JSON.stringify(user);
    console.log(user);
    if(user) {
        wx.navigateTo({
            url: 'personInfo/index?userStr='+userStr,
            success: function(res){
            // success
            },
        })
    } else {
        wx.navigateTo({
            url: 'login/index',
            success: function(res){
            // success
            },
        })
    }
}
 
 
# 接收 js (目标页面)
onLoad: function(options) {
    console.log(options);
    //将字符串转成json
    let user = JSON.parse(options.userStr);
    console.log(user);
    this.setData({
        userListInfo: [
        {
            title: '头像',
            subTitle: '',
            icon:'../../../images/icon_img_tx.png',//user.avatar,
            hasIcon:true
        },{
            title: '昵称',
            subTitle: user.nickname,
            icon:'',
            hasIcon:false
        }, {
            title: '手机号',
            subTitle: user.phone,
            icon:'',
            hasIcon:false
        }, {
            title: '实名认证',
            subTitle: user.truename,
            icon:'',
            hasIcon:false
        }]
    });
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
4. this.$parent 更改没反应

需要多加

this.$parent.$apply();
1
5. component 可以使用 parent 的 usingComponents ,若是跳转的页面及无法。
6. 若 onLoad() 因为是组件在进画面时已被加载,可加入 this.$apply() 帮助进画面时重新渲染
7. 微信小程序的网络请求必须走 Https 协议,就是说微信小程序一定要通过 HTTPS 加密。
8. page 呼叫 global => this.$parent;
9. page里的子组件呼叫 global => this.$root.$parent;
10. 价钱的加减乘除会有出现浮点数,如 12.0000000000001

解法: 浮点数计算 bug JavaScript 数字前补“0”的五种方法

解法:
仿 cookie

12. 抓取 目标 DOM
that.$apply();
var query = wx.createSelectorQuery();
query.select('.aslide-item-info').boundingClientRect();
query.exec(function(res) {
console.log(res);
that.boxHeight = res[0].height;
});
1
2
3
4
5
6
7
13. textarea 高度永远最高,且卷动时会出现异常,此部份尚无解,仅能用条件判断避开

解法:
textarea 坑
当前小程序作法:

  1. 上方有物件时,让文字区块隐藏,如优惠券浮窗
  2. 卷动时文字停留 bug ,做一个伪文字区块(以 view 模拟),编辑时点击伪文字区块,换成 该 textarea,unfocus 或卷动视窗时,又切回伪文字区块,并将编辑内容放入。

mpvue

目录结构

project-name
 ┣ build  // webpack 配置
 ┣ config // html 2 wxml, wxss 2 css 等配置
 ┣ dist // 输出小程序用的 wxml 等文件
 ┣ node_modules
 ┣ src
 ┃ ┣ components // 组件
 ┃ ┣ assets // 图片
 ┃ ┣ pages // 页面
 ┃ ┃ ┣ counter // vuex 示例
 ┃ ┃ ┃ ┣ index.vue
 ┃ ┃ ┃ ┣ main.js
 ┃ ┃ ┃ ┗ store.js
 ┃ ┃ ┣ index // 普通示例页面
 ┃ ┃ ┃ ┣ index.vue
 ┃ ┃ ┃ ┗ main.js
 ┃ ┃ ┗ logs // 普通示例页面
 ┃ ┃ ┃ ┣ index.vue
 ┃ ┃ ┃ ┣ main.js
 ┃ ┃ ┃ ┗ main.json
 ┃ ┣ styles // stylus 基础文件
 ┃ ┃ ┣ base.styl // 全局公共 class
 ┃ ┃ ┣ iconfont.styl // 字体图标
 ┃ ┃ ┣ reset.styl // 重置默认样式
 ┃ ┃ ┗ variable.styl // 样式变量
 ┃ ┣ utils
 ┃ ┃ ┣ index.js
 ┃ ┃ ┣ request.js // wx.request 二次封装
 ┃ ┃ ┣ static.js // 静态变量配置
 ┃ ┃ ┗ toast.js // 简化 wx 弹框
 ┃ ┣ app.json // 页面配置
 ┃ ┣ App.vue // 全局入口文件
 ┃ ┗ main.js
 ┣ static
 ┣ tes
 ┃ ┣ e2e
 ┃ ┣ unit
 ┃ ┗ mock // mock 数据
 ┣ .editorconfig
 ┣ .eslintignore
 ┣ .eslintrc.js
 ┣ .gitignore
 ┣ index.html
 ┣ package.json
 ┣ package.swan.json
 ┣ project.config.json
 ┗ README.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

特性

以 mpvue 为基础架构,支持 vue 的大部分功能. 开发上与 vue 有少许差异,参考 mpvue使用手册.

极速开发体验

渲染一个列表只需要几行熟悉的代码

<template lang="pug">
div.container
  div(v-for="(item,i) in list" :key="i")
    span {{item.name}}
</template>

mounted () {
  const result = await this.$get('api/list');
  this.list = result;
}

<style lang="stylus">
$mainColor = #ababab
.container
  color $mainColor
  div
    border 1rpx solid $mainColor
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Last Updated: 2019-8-14 6:29:41 PM