# begonia

> A library for wx-miniprogram development.

Latest version **2.3.4** (published 2021-12-12) · MIT license · 0 weekly downloads

## Install

```sh
npm install begonia
pnpm add begonia
yarn add begonia
bun add begonia
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.3.4 |
| Published | 2021-12-12 |
| First published | 2019-05-08 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 76.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | Brave Chan |
| Maintainers | brave_cgx |
| Keywords | begoniajs, miniprogram |

## Links

- npm: https://www.npmjs.com/package/begonia
- Repository: https://github.com/begoniajs/begonia
- Homepage: https://github.com/begoniajs/begonia#readme
- Issues: https://github.com/begoniajs/begonia/issues
- npm.io page: https://npm.io/package/begonia

## Recent versions

- 2.3.4 (latest) — 2021-12-12
- 2.3.2 — 2021-11-04
- 2.3.1 — 2021-11-04
- 2.3.0 — 2021-11-04
- 2.2.0 — 2021-07-06
- 2.1.20 — 2021-06-20
- 2.1.19 — 2021-06-20
- 2.1.18 — 2021-06-20
- 2.1.17 — 2021-06-20
- 2.1.16 — 2021-05-01
- 2.1.15 — 2021-05-01
- 2.1.14 — 2021-05-01
- 2.1.13 — 2021-04-26
- 2.1.12 — 2021-04-23
- 2.1.11 — 2021-04-23
- … 23 more at https://npm.io/package/begonia/versions

## README

# Begonia 介绍

[begonia](https://github.com/begoniajs/begonia/tree/dev-1.x)是一个为微信小程序开发而建立的开源、简单和轻量的开发框架。

具有如下特性:

- 基于代理模式构建小程序App实例、Page实例和Component实例
- 提供属性延迟生效的功能，减少多次调用setData；通过延迟时间在宏观上控制setData提交的频次和数量。
- 自动将Page实例的`data`和Component实例的`data`中的属性转换为同名的`getter`和`setter`（自动提交属性变动），简化使用方式。
- 提供增强模块管理，可以基于begonia扩展功能。并借由模块生命周期细粒度的控制创建小程序Page实例和Component实例的过程。
- 支持npm安装，并符合小程序npm开发部署要求。
  
## 微信小程序基础库版本

```
^2.2.1
```

## 快速使用

### 1. 安装

请在小程序项目的根目录下(即 `project.config.js` 中的 `miniprogramRoot` 字段)执行`npm`安装:

```
$ npm install begonia
```

接下来，我们需要做的，就是使用微信开发者工具中的工具->构建npm命令，对已经安装好的npm模块进行构建。
关于如何使用微信开发者工具构建npm模块，你可以参考[官方文档](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html)

### 2. 导入模块

在小程序的`app.js`、页面或者自定义组件实例中，导入入口文件:

```js
import BE from 'begonia';
```

### 3. 创建实例

然后，就可以通过变量`BE`来使用套件的具体功能:

#### 创建根级`App`实例

```js
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方式渲染

```

#### 创建页面对象

```js
// /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()`改变的只有第三次的提交，框架在内部会舍去前两次的重复提交。

如果您想在提交一次属性变动之后，立即使其生效。可以使用如下形式：

```js
//...

this.commit('userId', 10);
this.validateNow();

//...
```
通过调用框架赋予实例的`validateNow()`方法，会使属性变动立即生效，其本质和直接使用`setData`没有区别。当然，为了避免频繁使用`setData`提交变动，请谨慎使用`validateNow`。确保只在必要时使用它。

#### 创建组件实例

```js
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`执行时)。

假设，我们在编码时，会这样调用函数：

```js
Page({
  onLoad() {
    this.foo();
    this.bar();
  },
  foo() {

  },
  bar() {

  }
});
```
当我们利用`BE()`的第二个参数时，却可以这样：

```js
BE({
  created() {

  },
  methods: {
    foo() {

    },
    bar() {

    }
  }
}, ['foo', 'bar'])(PAGE);
```
其本质等同于第一个例子中调用`foo()`和`bar()`的方式。

#### 考虑异步

普通的数组所形成的方法队列只能适用于同步的方式，而对于串行异步执行的方法则不能保证正确的顺序。
此时，我们可以使用`begonia`提供的异步数组包装器来编排串行异步执行函数队列：

```js
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`上的。
如果是一个单独的函数，也可以直接传入函数对象：

```js
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`，框架也为实例创建了同名属性的`getter`和`setter`方法，用于获取属性值和提交属性值。
其中`setter`方法的内部，也采用了延迟生效的机制(即与使用`commit()`情况类似)。

##### 形式1：提交一项属性更改:

```js
this.commit('groupList',[{
    id:'1800',
    name:'一年级B班',
}]);
```
##### 形式2：直接传入一个对象:

```js
this.commit({
  groupList:[{
    id:'1800',
    name:'一年级B班',
  }],
});
```

##### 形式3：直接为属性赋值(本质是利用setter间接提交):

```js
this.groupList = [{
    id:'1800',
    name:'一年级B班',
}];
```

#### 更新间隔到期，属性变动生效

默认设置是`100`毫秒更新间隔，当间隔到期，VMP内部会使用`setData()`方法，将搜集到的属性改动一次性提交微信小程序框架进行计算生效。

某些情况下，也许你想将提交的属性立即生效，可以使用
```js
this.validateNow();
```
这样，到当前时间为止，所有提交的属性变更将会立即生效。VMP会清空缓存的对象，等待下一轮时间间隔内提交的属性变动。

延迟更新的时间间隔是可以改变的，首先使用`BE`的方法`getModules`获取已经装载模块的映射，然后调用`vmp`模块的`interval`即可，方法接受安全的、非零自然数作为值。

这种方式较`1.x`有了改变，原因是内部将`VMP`模块隔离为一个更加独立的模块进行装载，减少了`1.x`中的耦合部分。

```js
import BE from 'begonia';

//...
BE.getModules.vmp.interval = 200; //设置200毫秒间隔
```

### 销毁并回收

当页面发生切换，页面实例和组件实例会被微信小程序框架销毁，此时`onUnload`方法会被触发。
在钩子函数中，begonia会**自动清理**附加在实例对象上的内部属性和方法，释放内部的代理对象。


## 使用增强模块

begonia遵循模块化原则，提供的各项功能均保持相对独立的状态。包括内部使用的代理对象和延迟提交模块`VMP`也是独立的。
只不过，框架在建立之初就进行了自动装载。

`begonia`提供的装载模块的方法非常简单：

```js
BE.use(MyModule);
```

例如，我们也提供了一个简版的`redux`模块，您可以首先在一个独立的名为`store.js`的文件中，编写`store`相关的代码:

```js
// store.js

//导入begonia
import BE from 'begonia';
//导入beleaf模块
import Bex from 'beleaf';

//=====>>>装载bex模块<<<=========
BE.use(Bex);

```
完成之后，在小程序页面或组件实例中:

```js
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项目仓库](https://github.com/begoniajs/begonia-leaf)，详细了解。

## 说明文档和开发文档

诚如所见，为方便使用，`begonia`和`beleaf`在API的名称设计上借鉴了很多[vue框架](https://cn.vuejs.org/)的API名称，
不过内部实现和实际使用还是不同的。并且从整体上来说，begonia也远不如vue框架及其衍生的众多代码库的功能强大，限于其使用的场景，够用即好。

如果想要具体了解各种使用方法，可以查看如下文档:
- [创建小程序页面和组件对象](https://github.com/begoniajs/begonia/tree/master/doc)
- [VMP代理对象](https://github.com/begoniajs/begonia/tree/master/doc)
- [开发自定义模块](https://github.com/begoniajs/begonia/blob/dev-1.x/doc/%E5%BC%80%E5%8F%91%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A2%9E%E5%BC%BA%E6%A8%A1%E5%9D%97.md)
- [API](https://github.com/begoniajs/begonia/tree/master/doc/api)

## 初衷

begonia框架是适用于小程序开发的框架，其所追求的也仅仅是提高小程序开发的效率和改善。
更多的意义在于借由对其他框架优点的认识，自行实现，进而达到研究原理的目的。
也许以后的发展中会追求多种小程序平台开发的统一，但绝不会努力实现在多种设备终端开发中的统一。

# 开源协议

MIT

## 关于名称

秋海棠（学名：`Begonia` grandis Dry）：秋海棠科秋海棠属多年生草本植物。根状茎近球形，茎直立，高可达60厘米，有纵棱无毛。茎生叶互生，叶片轮廓宽卵形至卵形两侧不相等，上面褐绿色，常有红晕，下面色淡，带紫红色，托叶长圆形至披针形膜质，花葶有纵棱，无毛；花较多数粉红色，苞片长圆形，先端钝，早落；花药倒卵球形，子房长圆形，蒴果下垂，轮廓长圆形，种子长圆形小，淡褐色数极多，7月开花，8月开始结果。

分布中国河北、河南、湖北、福建等地。有栽培。生山谷潮湿石壁上、密林、灌丛中，该种花、叶、茎、根均可入药。花形多姿，叶色柔媚。盆栽秋海棠常用来点缀客厅、橱窗或装点家庭窗台、阳台、茶几等地方。

---
_Source: https://npm.io/package/begonia · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
