wepy是官方推荐的微信小程序组件化开发框架,使用该框架可以类似开发vue项目的方式开发小程序,框架提供实时编译打包生成小程序原生代码的服务。

  • 安装

    1
    npm install wepy-cli -g
  • 初始化项目

    1
    wepy init standard myproject
  • 切换至项目目录/安装依赖

    1
    2
    3
    cd myproject
    npm install
  • 开启实时编译

    1
    2
    3
    4
    5
    wepy build --watch
    // 注意:此命令开启实时编译,但属于开发模式,存在代码冗余。如果需要上线生产环境,请执行打包命令:
    npm run build

wepy项目结构

此处只列举了src目录下的文件结构

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
│ app.wpy
├─components
│ counter.wpy
│ group.wpy
│ groupitem.wpy
│ list.wpy
│ panel.wpy
│ wepy-list.wpy
├─mixins
│ test.js
├─pages
│ index.wpy
└─store
│ index.js
├─actions
│ counter.js
│ index.js
├─reducers
│ counter.js
│ index.js
└─types
counter.js
index.js

在初始化项目的时候,我选择了使用redux,因此项目中会自动添加wepy-redux插件,并初始化一个基础的范例。wepy-redux的结构一会儿在后面会详细再介绍。

app.wpy

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
<script>
import wepy from 'wepy'
import 'wepy-async-function'
import { setStore } from 'wepy-redux'
import configStore from './store'
const store = configStore()
setStore(store)
wepy.$store = store /*定义wepy.$store,确保组件可使用wepy.$store获取状态管理或调用相关功能*/
export default class extends wepy.app {
config = {
pages: [
'pages/index'
],
/*此处定义分包配置*/
'subPackages': [{
// 分包入口A
'root': 'pages/packageA',
'pages': [
'pages/index',
'pages/finish',
'pages/cancelPay'
]
}, {
// 分包入口B
'root': 'pages/packageB',
'pages': [
'pages/index',
'pages/finish',
'pages/cancel',
'components/addressPick'
]
} ],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
}
}
...
constructor () {
super()
this.use('requestfix')
this.use('promisify') /*添加项目对promise语法的支持*/
}
...
}
</script>

wepy-redux

1
2
3
4
5
6
7
8
9
10
11
12
13
│ index.js
├─actions
│ counter.js
│ index.js
├─reducers
│ counter.js
│ index.js
└─types
counter.js
index.js
  • 入口文件index.js

    1
    2
    3
    4
    5
    6
    7
    8
    import { createStore, applyMiddleware } from 'redux'
    import promiseMiddleware from 'redux-promise' //promiseMiddleware中间件,用于action做异步处理
    import rootReducer from './reducers'
    export default function configStore () {
    const store = createStore(rootReducer, applyMiddleware(promiseMiddleware))
    return store
    }
  • types

    types文件夹下存放文件用于定义action名称

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // index.js
    export * from './counter'
    // counter.js
    export const INCREMENT = 'INCREMENT'
    export const DECREMENT = 'DECREMENT'
    export const ASYNC_INCREMENT = 'ASYNC_INCREMENT'
  • reducers

    reducers文件夹下存放纯函数,用来更改我们的状态。

    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
    // index.js
    import { combineReducers } from 'redux'
    import counter from './counter'
    export default combineReducers({
    counter
    })
    // counter.js
    import { handleActions } from 'redux-actions'
    import { INCREMENT, DECREMENT, ASYNC_INCREMENT } from '../types/counter'
    const defaultState = {
    num: 0,
    asyncNum: 0
    }
    export default handleActions({
    [INCREMENT] (state) {
    return {
    ...state,
    num: state.num + 1
    }
    },
    [DECREMENT] (state) {
    return {
    ...state,
    num: state.num - 1
    }
    },
    [ASYNC_INCREMENT] (state, action) {
    return {
    ...state,
    asyncNum: state.asyncNum + action.payload
    //此处多了个action,若在actions文件下无定义处理,则传递调用时携带的参数
    }
    }
    }, defaultState)
  • actions

    补充实现reducers下的数据异步操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // index.js
    export * from './counter'
    // counter.js
    import { ASYNC_INCREMENT } from '../types/counter'
    import { createAction } from 'redux-actions'
    export const asyncInc = createAction(ASYNC_INCREMENT, (val) => {
    return new Promise(resolve => {
    setTimeout(() => {
    resolve(1+val)
    }, 1000)
    })
    })
    /**
    *当组件调用'asyncInc'方法时,会触发调用'ASYNC_INCREMENT',其中携带的参数即异步函数return的值
    */

组件里如何调用wepy-redux

这里主要涉及到 connect 的用法: connect(states, actions),这里解释下:

  • states: 访问 state 上的值,可以是数组或者对象,如果是对象的话,则包含的是 K-V对,V 可以是函数还可以是字符串,如果是字符串的话则默认获取 state[V], 否则的话则是使用返回值;而对于如果是数组的话(数组中的项只能为字符串),则认为是相同的 K-V 对象结构。states 最终会附加到组件的 computed 属性值上。

  • actions: 只能传入对象,对象的 K-V 结构,如果 V 是字符串的话,则直接会 distatch如下的结构:

    1
    2
    3
    4
    5
    6
    7
    // args 就是调用传入参数
    {
    type: val,
    // 修正一般情况下的参数 一般支持只传一个参数
    // 如果真的是多个参数的话 那么 payload 就是参数组成的数组
    payload: args.length > 1 ? args : args[0]
    }

示例:

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
<template>
<view class="counter {{style}}">
<button @tap="plus" size="mini"> + </button>
<button @tap="minus" size="mini"> - </button>
<button @tap="incNum" size="mini"> INCREMENT </button>
<button @tap="decNum" size="mini"> DECREMENT </button>
<button @tap="test" size="mini"> ASYNC INCREMENT </button>
<text class="count"> {{num}} </text>
<text class="count"> {{stateNum}} </text>
<text class="count"> {{asyncNum}} </text>
</view>
</template>
<script>
import wepy from 'wepy'
import { connect } from 'wepy-redux'
import { INCREMENT, DECREMENT } from '../store/types/counter'
import { asyncInc } from '../store/actions'
@connect({
stateNum (state) {
return state.counter.num
},
asyncNum (state) {
return state.counter.asyncNum
}
}, {
incNum: INCREMENT,
decNum: DECREMENT,
asyncInc // action定义的方法需要以该方式引入
})
export default class Counter extends wepy.component {
...
methods = {
plus () {
this.num = this.num + 1
},
minus () {
this.num = this.num - 1
},
test() {
this.methods.asyncInc(5) //调用action里的asyncInc函数,并携带参数
wepy.$store.dispatch({ type: 'ASYNC_INCREMENT', payload: 1 })
// 直接调用reducers里的'ASYNC_INCREMENT'纯函数
}
}
}
</script>