wxa-core

Build Status NPM version codecov

@wxa/core是一个非常小巧的包,用于增强小程序原生的能力。可以单独使用,但是一般推荐配合@wxa/cli一起使用,体验更佳:)

@wxa/core提供了下面几个Decorator,开发者可以选择性的引入,或者直接使用预定好的两个Decorator@App@Page

全局

setMaxRequest

  • Type: Function
  • Default: maxRequest = 5
  • Usage:
// app.js
import {wxa} from '@wxa/core'

wxa.setMaxRequest(4);

// ...other logic

设置最多同时并发的网络请求。

微信wx.request接口最多同时并发10个请求,超过10个请求将会被抛弃。wxa提供了一层request包装,引入队列控制并发请求。小程序业务层可以不关心并发多少个请求的问题,wxa将会保证每个请求都发出去。

注意

最大并发请求不应该设置超过10
超过最大并发的请求都会在队列等待其他请求完成后按顺序发出

setRequestExpiredTime

  • Type: Function
  • Default: expiredTime=500ms
  • Usage:
// app.js
import {wxa} from '@wxa/core'

wxa.setRequestExpiredTime(1000);

// ...other logic

设置post请求失效缓存失效时间。

使用wxa的fetch方法发送网络请求,wxa会缓存每个post请求,当客户端在一定时间内连续发送同一个请求的时候,wxa会主动reject并返回{code: -101}。相当于做一层前端post请求防重复。

注意

wxa的前端防重机制大部分时间下可以很好的处理绝大多数请求重复的case。但是如果业务比较复杂,例如遇到多异步请求的事务性业务的时候,http层的请求防重并不能解决问题,wxa另外提供了一个Lock装饰器来处理这种情况。

addNoPromiseApi

  • Type: Function
  • Usage:
import {wxa} from '@wxa/core'

wxa.addNoPromiseApi('getRecorderManager')

// ...other logic

wxa尝试为所有wx.**的方法做一次promise化,但是有一些同步的api却不应该这么做,因为他们会直接返回某个句柄或者结果值,如果为他们做了promise化,这些返回将会被损失。

Storage API

storage方法包装了同步的wx.storage方法,提供简单,容易记得api

提示

wxa提供了装饰器Storage和单独的storage

Decorators:

import {Storage} from '@wxa/core'

@Storage
class Idx {
    methods = {
        foo() {
            let abc = this.storage.get('abc')
        }
    }
}

直接使用:

import {storage} from '@wxa/core'

export default function foo() {
    let abc = this.storage.get('abc')
}

set

  • Pattern:
    • set( key, value )
  • Arguments :
    • {String} key
    • {Any} value
  • Usage:
this.storage.set(key, data)

同步保存数据到storage

注意

storage并不能存Function类型的数据

get

  • Pattern:
    • get( key )
  • Arguments :
    • {String} key
  • Usage:
let data = this.storage.get(key)

同步的获取数据

remove

  • Pattern:
    • remove( key )
  • Arguments :
    • {String} key
  • Usage:
this.storage.remove(key)

清除指定key的数据

clear

  • Pattern:
    • clear( )
  • Usage:
this.storage.clear()

清除所有的storage数据

Wxapi

包装了一层小程序的异步方法,使得开发者可以直接使用promise处理异步问题。 对于同步的方法,不做任何包装直接返回,示例如下:

  1. navigateToMiniProgram
this.wxapi.navigateToMiniProgram({params}).then(succ=>{}).catch(fail=>{})
  1. getSystemInfoSync
let value = this.wxapi.getSystemInfoSync();

注意

wxapi对所有微信api一次promise化。其中不会做promisify的方法有:create*方法,*Sync方法和getUpdateManager方法。

使用wxa.addNoPromiseApi可以手动添加方法,避免被方法被错误的promise化

Router

vue-router的api风格,包装了一层小程序的跳转方法。

get

  • Pattern:
    • get( )
  • Usage:
// {_webviewid: 1, route: 'pages/index/index', ...}
let currentPage = this.router.get(); 

获取当前路由页面信息

getAll

  • Pattern:
    • getAll( )
  • Usage:
// [{...}, {...}, {...}]
let stack = this.router.getAll();

获取当前路由栈,相当于调用了小程序的getCurrentPages()

push

  • Pattern:
    • push( url )
  • Arguments
    • {String} url
  • Usage:
let url = '/pages/index';
this.router.push(url);

// 跳转完成后做一些特殊处理
this.router.push(url)
.then((succ)=>{
    this.storage.set('isCutomer', true);
})
.catch((fail)=>{
    toast('跳转失败');
})

跳转到新路由页面,压栈路由

replace

  • Pattern:
    • replace( url )
  • Arguments
    • {String} url
  • Usage:
let url = '/pages/index';
this.router.replace(url);

关闭当前页面,打开新的指定页面

reLaunch

  • Pattern:
    • reLaunch( url )
  • Arguments
    • {String} url
  • Usage:
this.router.reLaunch(url)

关闭所有调用栈,重新打开指定页面

switch

  • Pattern:
    • switch( url )
  • Arguments
    • {String} url
  • Usage:
this.router.switch(url);

切换tabar页面

go

  • Pattern:
    • go( delta )
  • Arguments
    • {Number} delta 回退的页面数
  • Usage:
this.router.go(-1);

回退页面, key为欲回退页面数

goBack

  • Pattern:
    • goBack( )
  • Usage:
this.router.goBack();

回退上一个页面,相当于调用go(-1)

close

  • Pattern:
    • close( )
  • Usage:
this.router.close();

关闭小程序。⚠️谨慎调用,将会直接关闭小程序。

提示

router提供的函数除了get, getAll之外都有返回一个promise的回调。

Eventbus

wxa提供了一个简易的自定义事件管理,允许用户跨页面,跨组件的共享信息。

on( name, handler )

  • arguments
    • {String} name
    • {Function} handler
  • Usage:
@Eventbus
class Foo {
    boo() {
        this.eventbus.on('event', this.handler);
    }
    handler(e) {
        console.log('event, handle here');
    }
}

监听一个自定义事件,当事件触发的时候执行回调队列。

off( name, handler )

  • arguments
    • {String} name
    • {Function} handler
  • Usage:
@Eventbus
class Foo {
    boo() {
        this.eventbus.on('event', this.handler);
    }
    handler(e) {
        console.log('event, handle here');
        this.eventbus.off('event', this.handler);
    }
}

取消监听一个自定义事件

emit( name )

  • arguments
    • {String} name
  • Usage:
this.eventbus.emit('my-event')

触发一个自定义事件

clear( name )

  • arguments
    • {String} name
  • Usage:
this.eventbus.clear(); // 注意这么写会清空所有事件
this.eventbus.clear('event'); // 清楚所有event事件监听

清空指定事件回调,或者清空所有事件回调

Fetch

wxa为网络请求提供了一个好用的Fetch装饰器,通过fetch,开发者可以快速的发起请求,而不需要担心wx.request引发的其他问题。

fetchapi具有promise化,队列化请求的能力,同时具备对post请求的短时间防重。

fetch

  • pattern
    • fetch( url, data, configs, methods )
  • arguments
    • {String} url
    • {Object} data 请求携带的数据
    • {Object} configs 请求的配置
      • {Boolean} $top 高优先级请求,直接压入等待队列的列首
      • {Boolean} $noCache 指定该请求不做防重处理
      • other 其他小程序默认的配置都放在这里,例如header,dataType
    • {String} methods 请求方式, get, post
  • Usage:
@Fetch
class UserInfo {
    get(){
        this.fetch('/remote/user/get', {}, {}, 'get')
        .then((succ)=>{
            // handle response here
        })
    }
}

Utils

常用的工具函数

formatDate

  • pattern
    • fetch( timestap, format )
  • arguments
    • {Number or String} timestap
    • {String} format 格式化后的时间格式,默认'yyyy-MM-dd hh:mm:ss'
  • Usage:
@Utils
class T {
    foo() {
        let dateStr = this.utils.formatDate(Date.now());
        
        // .... other control
    }
}

格式化时间戳为指定格式的字符串

trim

  • pattern
    • trim( str )
  • arguments
    • {String} str
  • Usage:
@Utils
class T {
    foo(str) {
        str = this.utils.trim(str);
        
        // .... other control
    }
}

由于小程序部分终端不支持.trim方法,所以wxa提供了一个补丁方法。

compareVersion

  • pattern
    • compareVersion( v1, v2 )
  • arguments
    • {String} v1
    • {String} v2
  • Usage:
@Utils
class T {
    foo(str) {
        let ret = this.utils.compareVersion('1.2.1', '1.1.0'); // 1
        
        // .... other control
    }
}

小程序官方提供的基础库比较函数。

debounce

  • pattern
    • debounce( fn, [wait=0], [options={}] )
  • arguments
    • {Function} fn The function to debounce.
    • {Number} wait The number of milliseconds to delay.
    • {Object} options The options object.
      • {Boolean} leading Specify invoking on the leading edge of the timeout.
      • {Number} maxWait The maximum time func is allowed to be delayed before it's invoked
      • {Boolean} trailing Specify invoking on the trailing edge of the timeout.
  • Usage:
@Utils
class T {
    foo(str) {
        let release = ()=>this.isDone=true;
        let ret = this.utils.debounce(release, 300); // 1
        
        // .... other control
    }
}

debounce函数,详见lodash debounce;

throttle

  • pattern
    • throttle( fn, [wait=0], [options={}] )
  • arguments
    • {Function} fn The function to throttle.
    • {Number} wait The number of milliseconds to delay.
    • {Object} options The options object.
      • {Boolean} leading Specify invoking on the leading edge of the timeout.
      • {Boolean} trailing Specify invoking on the trailing edge of the timeout.
  • Usage:
@Utils
class T {
    foo(str) {
        let release = ()=>this.isDone=true;
        let ret = this.utils.throttle(release, 300); // 1
        
        // .... other control
    }
}

throttle节流函数,详见lodash throttle;

Redux全局状态管理

@wxa提供了一个redux集成小程序方案,方便开发者管理全局应用状态

挂载

要使用@wxa/redux首先需要挂载插件到wxa。

// app.wxa or app.js
import {wxa} from '@wxa/core'
import {wxaRedux, combineReducers} from '@wxa/redux'
import promiseMiddleware from 'redux-promise';

wxa.use(wxaRedux, {
    reducers: combineReducers(...your reducer),
    middlewares: [promiseMiddleware]
})

挂载完毕后,wxa会在所有调用launchApp,launchPagelaunchComponent的地方自动connect store到相应示例。

映射

@wxa/redux并不会把所有reducer都映射到实例,只有在实例中指定了的reducer才能自动从store同步。

映射到Page

// page.js
import {Page, wxa} from '@wxa/core'

@Page
class Index {
    mapState = {
        todolist : (state)=>state.todo
    }
    methods = {
        bindtap() {
            // dispatch your commit here
            this.store.dispatch({type: 'Add_todo_list', payload: 'coding today'});
            // and your page data will auto update.
        }
    }
} 

wxa.launchPage(Index)

映射到Component

// component.js
import {GetApp} from '@wxa/core'

// redux need mount app to com.
@GetApp
class Com {
    mapState = {
        todolist : (state)=>state.todo
    }
    methods = {
        bindtap() {
            // dispatch your commit here
            this.store.dispatch({type: 'Add_todo_list', payload: 'coding today'});
            // and your page data will auto update.
        }
    }
} 

wxa.launchComponent(Com);

具体的实现细节可以参考@wxa/redux

插件

wxa在调用launchApp,launchPagelaunchComponent生成实例的时候会自动应用每个注册的插件,插件机制允许开发者为wxa开发新的功能。

插件示例

// somthing report error message to remote server
import wa from 'wa'

export default (options)=>{
    return (vm, type)=>{
        if(['App', 'Page'].indexOf(type) > -1){
            vm.logger = wa;
        }
    }
}

插件将拿到当前实例vm, 以及实例的类型AppPageComponent