MCPcopy
hub / github.com/Tencent/westore

github.com/Tencent/westore @v0.1.8 sqlite

repository ↗ · DeepWiki ↗ · release v0.1.8 ↗
1,868 symbols 2,111 edges 57 files 888 documented · 48%
README

Westore - 更好的小程序项目架构

  • Object-Oriented Programming: Westore 强制使用面向对象程序设计,开发者起手不是直接写页面,而是使用职责驱动设计 (responsibility-driven design)的方式抽象出类、类属性和方法以及类之间的关联关系。
  • Write Once, Use Anywhere(Model): 通过面向对象分析设计出的 Model 可以表达整个业务模型,开发者可移植 100% 的 Model 代码不带任何改动到其他环境,并使用其他渲染技术承载项目的 View,比如小程序WebView、Web浏览器、Canvas、WebGL
  • Passive View: Westore 架构下的 View 非常薄,没有参杂任何业务逻辑,只做被动改变。

Westore 架构和 MVP 架构很相似,但是有许多不同。

  • View 和 Store 是双向通讯
  • View 与 Model 不发生联系,都通过 Store 传递
  • View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性
  • Store 非常薄,只复杂维护 View 需要的数据和桥接 View 和 Model
  • Model 非常厚,所有逻辑都部署在那里,Model 可以脱离 Store 和 View 完整表达所有业务/游戏逻辑

随着小程序承载的项目越来越复杂,合理的架构可以提升小程序的扩展性和维护性。把逻辑写到 Page/Component 是一种罪恶,当业务逻辑变得复杂的时候 Page/Component 会变得越来越臃肿难以维护,每次需求变更如履薄冰, westore 定义了一套合理的小程序架构适用于任何复杂度的小程序,让项目底座更健壮,易维护可扩展。

安装

npm i westore --save

npm 相关问题参考:小程序官方文档: npm 支持

举个例子

开发如下图所示的重命名 app

按照传统的小程序开发三部曲:

  • 写页面结构 wxml
  • 写页面样式 wxss
  • 写页面逻辑 js/ts

省略 wxml、wxss,js 如下:

Page({
  data: {
    nickName: ''
  },

  async onLoad() {
    const nickName = await remoteService.getNickName()
    this.setData({
      nickName: nickName
    })
  },

  async modifyNickName(newNickName) {
    await remoteService.modifyNickName(newNickName)
  },

  clearInput() {
    this.setData({
      nickName: ''
    })
  }
})

需求开发全部结束。

使用 Westore 重构

定义 User 实体:

class User {
  constructor({ nickName, onNickNameChange }) {
    this.nickName = nickName || ''
    this.onNickNameChange = onNickNameChange || function() { }
  }

  checkNickName() {
    // 省略 nickName 规则校验
  }

  modifyNickName(nickName) {
    if(this.checkNickName(nickName) && nickName !== this.nickName) {
      this.nickName = nickName
      this.onNickNameChange(nickName)
    }
  }
}

module.exports = User

定义 UserStore:

const { Store } = require('westore')
const User = require('../models/user')

class UserStore extends Store {
  constructor(options) {
    super()
    this.options = options
    this.data = {
      nickName: ''
    }
  }

  init() {
    const nickName = await remoteService.getNickName()
    this.user = new User({ 
      nickName,
      onNickNameChange: (newNickName)=>{
        this.data.nickName = newNickName
        this.update()
        await remoteService.modifyNickName(newNickName)
      } 
    })
  }

  async saveNickName(newNickName) {
    this.user.modifyNickName(newNickName)
  },

  modifyInputNickName(input) {
    this.data.nickName = input
    this.update()
  }
}

module.exports = new UserStore

页面使用 UserStore:

const userStore = require('../../stores/user-store')

Page({
  data: userStore.data,

  onLoad() {
    /* 绑定 view 到 store 
      也可以给 view 取名 userStore.bind('userPage', this)
      取名之后在 store 里可通过 this.update('userPage') 更新 view
      不取名可通过 this.update() 更新 view
    */
    userStore.bind(this)
  },

  saveNickName(newNickName) {
    userStore.saveNickName(newNickName)
  },

  onInputChange(evt) {
    userStore.modifyInputNickName(evt.currentTarget.value)
  },

  clearInput() {
    userStore.modifyInputNickName('')
  }
})

官方案例目录

目录如下:

├─ models    // 业务模型实体
│   └─ snake-game
│       ├─ game.js
│       └─ snake.js   
│  
│  ├─ log.js
│  ├─ todo.js   
│  └─ user.js   
│
├─ pages     // 页面
│  ├─ game
│  ├─ index
│  ├─ logs   
│  └─ other.js  
│
├─ stores    // 页面的数据逻辑,page 和 models 的桥接器
│  ├─ game-store.js   
│  ├─ log-store.js      
│  ├─ other-store.js    
│  └─ user-store.js   
│
├─ utils

详细代码点击这里

官方例子

贡献者

License

MIT

Extension points exported contracts — how you extend this code

CameraFrameListener (Interface)
(no doc) [4 implementers]
packages/westore-example-ts/typings/types/wx/lib.wx.api.d.ts
Current (Interface)
(no doc)
packages/westore/index.d.ts
BaseEvent (Interface)
基础事件参数
packages/westore-example-ts/typings/types/wx/lib.wx.event.d.ts
Previous (Interface)
(no doc)
packages/westore/index.d.ts
CustomEvent (Interface)
自定义事件
packages/westore-example-ts/typings/types/wx/lib.wx.event.d.ts
diffResult (Interface)
(no doc)
packages/westore/index.d.ts
TouchDetail (Interface)
Touch 对象
packages/westore-example-ts/typings/types/wx/lib.wx.event.d.ts
TouchCanvasDetail (Interface)
canvas Touch 对象
packages/westore-example-ts/typings/types/wx/lib.wx.event.d.ts

Core symbols most depended-on inside this repo

cloneArray
called by 20
packages/westore-example/miniprogram_npm/rfdc/index.js
cloneArray
called by 20
packages/westore-example-ts/miniprogram/miniprogram_npm/rfdc/index.js
diffData
called by 17
packages/westore/index.esm.js
push
called by 14
packages/westore-example-ts/typings/types/wx/lib.wx.cloud.d.ts
pop
called by 12
packages/westore-example-ts/typings/types/wx/lib.wx.cloud.d.ts
unshift
called by 12
packages/westore-example-ts/typings/types/wx/lib.wx.cloud.d.ts
triggerEvent
called by 10
packages/westore-example-ts/typings/types/wx/lib.wx.component.d.ts
setResult
called by 8
packages/westore/index.common.js

Shape

Method 965
Interface 707
Function 119
Class 73
Enum 4

Languages

TypeScript100%

Modules by API surface

packages/westore-example-ts/typings/types/wx/lib.wx.api.d.ts1,355 symbols
packages/westore-example-ts/typings/types/wx/lib.wx.cloud.d.ts136 symbols
packages/westore-example-ts/typings/types/wx/lib.wx.component.d.ts43 symbols
packages/westore-example-ts/typings/types/wx/lib.wx.page.d.ts26 symbols
packages/westore-example/miniprogram_npm/westore/index.js16 symbols
packages/westore-example-ts/miniprogram/models/snake-game/game.ts16 symbols
packages/westore-example-ts/miniprogram/miniprogram_npm/westore/index.js16 symbols
packages/westore-example/models/snake-game/game.js15 symbols
packages/westore/index.esm.js12 symbols
packages/westore/index.common.js12 symbols
packages/westore-example-ts/typings/types/wx/lib.wx.app.d.ts12 symbols
packages/westore-example/stores/game-store.js11 symbols

Dependencies from manifests, versioned

jest27.2.0 · 1×
miniprogram-api-typings2.8.3-1 · 1×
rfdc1.3.0 · 1×
westore0.1.8 · 1×

For agents

$ claude mcp add westore \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact