2.3.4 • Published 2 years ago

begonia v2.3.4

Weekly downloads
4
License
MIT
Repository
github
Last release
2 years ago

Begonia 介绍

begonia是一个为微信小程序开发而建立的开源、简单和轻量的开发框架。

具有如下特性:

  • 基于代理模式构建小程序App实例、Page实例和Component实例
  • 提供属性延迟生效的功能,减少多次调用setData;通过延迟时间在宏观上控制setData提交的频次和数量。
  • 自动将Page实例的data和Component实例的data中的属性转换为同名的gettersetter(自动提交属性变动),简化使用方式。
  • 提供增强模块管理,可以基于begonia扩展功能。并借由模块生命周期细粒度的控制创建小程序Page实例和Component实例的过程。
  • 支持npm安装,并符合小程序npm开发部署要求。

微信小程序基础库版本

^2.2.1

快速使用

1. 安装

请在小程序项目的根目录下(即 project.config.js 中的 miniprogramRoot 字段)执行npm安装:

$ npm install begonia

接下来,我们需要做的,就是使用微信开发者工具中的工具->构建npm命令,对已经安装好的npm模块进行构建。 关于如何使用微信开发者工具构建npm模块,你可以参考官方文档

2. 导入模块

在小程序的app.js、页面或者自定义组件实例中,导入入口文件:

import BE from 'begonia';

3. 创建实例

然后,就可以通过变量BE来使用套件的具体功能:

创建根级App实例

import BE, { APP } from 'begonia';

// 打开debug模式,可以在console面板查看运行时的日志输出
BE.debug = true;

// app.js
BE({
  // 将转化为globalData
  data() {
    return {};
  },
  onLaunch(options) {},
  onShow(options) {},
  onHide() {},
  onError(msg) {
    console.error(msg);
  },
  onPageNotFound() {
    console.error(msg);
  },
  methods: {
    // 自定义方法
    myInit() {
      this.foo();      
    },
    setUIDatas() {
      this.bar();
    }
  },
  methodAres: [
    {
      // 自定义方法分组
      foo() {},
      bar() {}
    }
  ]
}, ['myInit', 'setUIDatas'])(APP); // 最后使用app方式渲染

创建页面对象

// /pages/example/example.js
import BE, { PAGE } from 'begonia';

BE({
    /**
     * 页面的初始数据
     */
    data(){
      return {
        userId: 0
      };
    },
    /**
     * 生命周期函数--监听页面加载
     * 相当于onLoad
     */
    created(options) {
      // 使用begonia为实例提供的commit()方法提交属性变动
      this.commit('userId', 10);
      // 另外一种提交形式
      this.commit({
        userId: 12
      });
      // 甚至,还可以这样
      this.userId = 14;
    },

    /**
     * 生命周期函数--监听页面初次渲染完成
     * 相当于onReady
     */
    ready () { },

    /**
     * 生命周期函数--监听页面显示
     */
    onShow () { },

    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide () { },

    /**
     * 生命周期函数--监听页面卸载
     * 相当于onUnload
     */
    destroyed () { },
    // 自定义方法
    methods: {
      pageInit() {
        this.foo();
      },
      setUIData() {
        this.bar();
      }
    },
    // 函数分组
    methodAreas: [
      {
        foo() {},
        bar() {}
      }
    ]
  }, ['pageInit', 'setUIData'])(PAGE);

created方法中,有3次属性的提交,但是最终会真正采用setData()改变的只有第三次的提交,框架在内部会舍去前两次的重复提交。

如果您想在提交一次属性变动之后,立即使其生效。可以使用如下形式:

//...

this.commit('userId', 10);
this.validateNow();

//...

通过调用框架赋予实例的validateNow()方法,会使属性变动立即生效,其本质和直接使用setData没有区别。当然,为了避免频繁使用setData提交变动,请谨慎使用validateNow。确保只在必要时使用它。

创建组件实例

import BE, { COMPONENT } from 'begonia';

BE({
    /**
     * 组件的属性列表
     */
    properties: {
      sysId: {
        type: Number,
        value: 0
      }
    },
    /**
     * 组件的初始数据
     */
    data(){
      return {
        userId: 0
      };
    },
    // 相当于lifetimes.created
    created() {
      // 根据小程序组件的内部机制,不可以在此提交属性变动
    },
    // 相当于lifetimes.attached
    mounted() {
      // 使用begonia为实例提供的commit()方法提交属性变动
      this.commit('userId', 10);
      // 另外一种提交形式
      this.commit({
        userId: 12
      });
      // 甚至,还可以这样
      this.userId = 14;
    },
    // 相当于lifetimes.ready
    ready() {},
    // 相当于lifetimes.detached
    destroyed() {},
    // 相当于lifetimes.error
    error(err) {},
    // 相当于pageLifetimes.show
    pageShow() {},
    // 相当于pageLifetimes.hide
    pageHide() {},
    // 相当于pageLifetimes.resize
    pageResize() {},
    /**
     * 组件的方法列表
     */
    methods: {
      comInit() {
        this.foo();
      }
      setUIDatas() {
        this.bar();
      }
    },
    methodAreas: [
      {
        foo() {},
        bar() {}
      }
    ]
  }, ['comInit', 'setUIDatas'])(COMPONENT);

编排方法队列

你可能注意到上面的例子在使用BE()时传入了第二个参数,是一个元素为字符串的数组。 这是一个自定义的函数执行队列,可以编排方法的执行顺序。实际则是在特定的方法执行时(App是在onLaunch执行时,Page在onLoad执行时,Component是在lifetimes.attached执行时)。

假设,我们在编码时,会这样调用函数:

Page({
  onLoad() {
    this.foo();
    this.bar();
  },
  foo() {

  },
  bar() {

  }
});

当我们利用BE()的第二个参数时,却可以这样:

BE({
  created() {

  },
  methods: {
    foo() {

    },
    bar() {

    }
  }
}, ['foo', 'bar'])(PAGE);

其本质等同于第一个例子中调用foo()bar()的方式。

考虑异步

普通的数组所形成的方法队列只能适用于同步的方式,而对于串行异步执行的方法则不能保证正确的顺序。 此时,我们可以使用begonia提供的异步数组包装器来编排串行异步执行函数队列:

import BE, { PAGE, BEAsyncList } from 'begonia';
BE(
  {
    created() {

    },
    methods: {
      foo({ next, error, end }, ...args) {
        post('/api/foo', {})
          .then(function(res) {
            next(res);
          });
          .catch(function(err) {
            console.error(err);
            error(err);
            // or end()
          });

      },
      bar({ next, error, end }, ...args) {
        console.log(args[0]); // 等于foo函数传入next()的res
        // 执行同步逻辑或异步逻辑
        end(); // 队列执行到此为止
        // 或者 next(),执行下一步,如果bar是队列的最后一个,那么等同于end()
      }
    }
  }, 
  BEAsyncList(
    ['foo', 'bar'], 
    function(err, ...args) {
      // Be invoked when async-list executed complete
    }
  )
)(PAGE);

使用序列的目的

当你的方法函数,纯度很高(不需要绝对),只专注于完成一项功能时,预定义的函数执行序列,可以更清楚的标明函数的执行顺序。

此外,数组的元素也不仅限于字符串。这里使用字符串的意思是,指明方法和函数时挂载在this上的。 如果是一个单独的函数,也可以直接传入函数对象:

import BE, { PAGE, BEAsyncList } from 'begonia';

function baz() {
  console.log('other function', this); // this 为page的实例
}

BE({
  created() {

  },
  methods: {
    foo() {

    },
    bar() {
      
    }
  }
}, ['foo', 'bar', baz])(PAGE);

baz被调用时,函数的this变量将会指向页面的实例。

其他功能

使用默认带有的延迟属性变更的功能

小程序开发中,如果想要修改实例的data对象中属性,必须使用setData()方法。

begonia框架内部使用ViewModelProxy(VMP)提供了延迟属性更改,从而可以收集一段时间内的属性变动, 在规定的更新间隔到来时,一次性的提交属性变动。

在实例创建的过程中,框架会为每个实例附加2个方法commit()validateNow(),用来提交属性变动。 此外,对于页面实例和组件实例的data,框架也为实例创建了同名属性的gettersetter方法,用于获取属性值和提交属性值。 其中setter方法的内部,也采用了延迟生效的机制(即与使用commit()情况类似)。

形式1:提交一项属性更改:
this.commit('groupList',[{
    id:'1800',
    name:'一年级B班',
}]);
形式2:直接传入一个对象:
this.commit({
  groupList:[{
    id:'1800',
    name:'一年级B班',
  }],
});
形式3:直接为属性赋值(本质是利用setter间接提交):
this.groupList = [{
    id:'1800',
    name:'一年级B班',
}];

更新间隔到期,属性变动生效

默认设置是100毫秒更新间隔,当间隔到期,VMP内部会使用setData()方法,将搜集到的属性改动一次性提交微信小程序框架进行计算生效。

某些情况下,也许你想将提交的属性立即生效,可以使用

this.validateNow();

这样,到当前时间为止,所有提交的属性变更将会立即生效。VMP会清空缓存的对象,等待下一轮时间间隔内提交的属性变动。

延迟更新的时间间隔是可以改变的,首先使用BE的方法getModules获取已经装载模块的映射,然后调用vmp模块的interval即可,方法接受安全的、非零自然数作为值。

这种方式较1.x有了改变,原因是内部将VMP模块隔离为一个更加独立的模块进行装载,减少了1.x中的耦合部分。

import BE from 'begonia';

//...
BE.getModules.vmp.interval = 200; //设置200毫秒间隔

销毁并回收

当页面发生切换,页面实例和组件实例会被微信小程序框架销毁,此时onUnload方法会被触发。 在钩子函数中,begonia会自动清理附加在实例对象上的内部属性和方法,释放内部的代理对象。

使用增强模块

begonia遵循模块化原则,提供的各项功能均保持相对独立的状态。包括内部使用的代理对象和延迟提交模块VMP也是独立的。 只不过,框架在建立之初就进行了自动装载。

begonia提供的装载模块的方法非常简单:

BE.use(MyModule);

例如,我们也提供了一个简版的redux模块,您可以首先在一个独立的名为store.js的文件中,编写store相关的代码:

// store.js

//导入begonia
import BE from 'begonia';
//导入beleaf模块
import Bex from 'beleaf';

//=====>>>装载bex模块<<<=========
BE.use(Bex);

完成之后,在小程序页面或组件实例中:

Page(BE.page({
  //...
  onLoad: function () {
    //访问store实例
    let store = this.$store;
    //查看state状态树
    let state = this.$store.state;

    //通过getters对象访问具体的state属性
    let list = this.$getters.groupList;

    //发起一个action,引起状态变更
    this.$actions.getGroupList('10');
  },
  //...
}));

更多关于beleaf的使用细节,您可以访问模块的GitHub项目仓库,详细了解。

说明文档和开发文档

诚如所见,为方便使用,begoniabeleaf在API的名称设计上借鉴了很多vue框架的API名称, 不过内部实现和实际使用还是不同的。并且从整体上来说,begonia也远不如vue框架及其衍生的众多代码库的功能强大,限于其使用的场景,够用即好。

如果想要具体了解各种使用方法,可以查看如下文档:

初衷

begonia框架是适用于小程序开发的框架,其所追求的也仅仅是提高小程序开发的效率和改善。 更多的意义在于借由对其他框架优点的认识,自行实现,进而达到研究原理的目的。 也许以后的发展中会追求多种小程序平台开发的统一,但绝不会努力实现在多种设备终端开发中的统一。

开源协议

MIT

关于名称

秋海棠(学名:Begonia grandis Dry):秋海棠科秋海棠属多年生草本植物。根状茎近球形,茎直立,高可达60厘米,有纵棱无毛。茎生叶互生,叶片轮廓宽卵形至卵形两侧不相等,上面褐绿色,常有红晕,下面色淡,带紫红色,托叶长圆形至披针形膜质,花葶有纵棱,无毛;花较多数粉红色,苞片长圆形,先端钝,早落;花药倒卵球形,子房长圆形,蒴果下垂,轮廓长圆形,种子长圆形小,淡褐色数极多,7月开花,8月开始结果。

分布中国河北、河南、湖北、福建等地。有栽培。生山谷潮湿石壁上、密林、灌丛中,该种花、叶、茎、根均可入药。花形多姿,叶色柔媚。盆栽秋海棠常用来点缀客厅、橱窗或装点家庭窗台、阳台、茶几等地方。

2.3.4

2 years ago

2.3.0

3 years ago

2.3.2

3 years ago

2.3.1

3 years ago

2.2.0

3 years ago

2.1.18

3 years ago

2.1.19

3 years ago

2.1.20

3 years ago

2.1.17

3 years ago

2.1.8

3 years ago

2.1.7

3 years ago

2.1.9

3 years ago

2.1.16

3 years ago

2.1.14

3 years ago

2.1.15

3 years ago

2.1.12

3 years ago

2.1.13

3 years ago

2.1.10

3 years ago

2.1.11

3 years ago

2.1.4

3 years ago

2.1.3

3 years ago

2.1.6

3 years ago

2.1.5

3 years ago

2.1.2

3 years ago

2.1.1

3 years ago

2.1.0

3 years ago

2.0.1

3 years ago

1.0.12

5 years ago

1.0.11

5 years ago

1.0.10

5 years ago

1.0.9

5 years ago

1.0.8

5 years ago

1.0.7

5 years ago

1.0.6

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago