zeno,发音 /ˈzeɪnoʊ/ 。杰诺是漫画全职猎人中揍敌客家的前任当家,变化系能力者。绝招是 龙头戏画 和 牙突 。
轻量灵活的小程序状态管理框架
- 基于
@vue/reactivity
,简单,灵活,性能优异 - Typescript 友好
全局 store 和小程序应用的生命周期保持一致,可在多个页面、组件之间共享。
首先,定义 /store/todo.js
import { reactive, computed } from 'zenojs';
let idx = 3;
const items = new Array(idx).fill(1).map((item, index) => {
return {
id: index,
text: `Todo item ${index}`,
completed: false
}
})
// 定义状态
const todos = reactive(items);
// 计算属性
const done = computed(() => todos.every(todo => todo.completed));
// 更新状态
function toggleCompleted(id, completed) {
const todo = todos.find(item => item.id === id);
todo.completed = completed;
}
function addTodo(text) {
todos.push({
text,
id: ++idx,
completed: false,
});
}
export { todos, done, toggleCompleted, addTodo };
映射状态到页面或组件 /pages/todos/todos.js
import { todos, done, toggleCompleted } from '../../store/todo';
import { observer } from 'zenojs';
const mapState = () => ({
todos,
done
})
Page({
add() {
store.tick();
},
onLoad() {
observer(this, mapState);
},
});
在 axml 中访问状态和计算属性
<view a:for="{{todos}}">
{{item.text}}
</view>
<view>All todo item has done ? {{done.value}}</view>
页面 store 和页面实例的生命周期保持一致,多个页面实例之间的状态是隔离的,无法相互访问。
import { provide, inject } from 'zenojs';
// store 初始化
const storeName = 'counter';
function setup() {
const state = reactive({
count: 0,
});
function increment() {
state.count++;
}
return {
state,
increment,
};
}
// 页面实例注册 store,同步 store 状态到 this.data
Page({
onLoad() {
provide(this, storeName, setup);
// 访问 store 方法
this.$store.increment();
},
});
// 页面子组件消费 store,同步 store 状态到 this.data
Component({
onInit() {
inject(this, storeName);
// 访问 store 方法
this.$store.increment();
},
});
store 应有独立的目录结构,不要和 page 或 component 放在一起
example
├── README.md
├── app.acss
├── app.js
├── app.json
├── assets
│ └── logo.png
├── components
│ ├── add-button
│ │ ├── add-button.acss
│ │ ├── add-button.axml
│ │ ├── add-button.js
│ │ └── add-button.json
│ └── counter
├── pages
│ ├── add-todo
│ │ ├── add-todo.acss
│ │ ├── add-todo.axml
│ │ ├── add-todo.js
│ │ └── add-todo.json
│ └── todos
│ ├── todos.acss
│ ├── todos.axml
│ ├── todos.js
│ └── todos.json
└── store
└── todo.js
不要在除 store 外的地方更新状态,见 /example
- 访问计算属性的要通过
computedRef.value
- 处于性能考量,状态同步到视图层是异步的,你可能需要通过
nextTick
来获取更新后的this.data
见 /example
目录