npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ystore

v1.0.1

Published

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

Downloads

2

Readme

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

安装

npm i ystore --save

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

架构

性质

  • Object-Oriented Programming: Ystore 强制小程序使用面向对象程序设计,开发者起手不是直接写页面,而是使用职责驱动设计 (Responsibility-Driven Design)的方式抽象出类、类属性和方法以及类之间的关联关系。
  • Write Once, Use Anywhere(Model): 通过面向对象分析设计出的 Model 可以表达整个业务模型,开发者可移植 100% 的 Model 代码不带任何改动到其他环境,并使用其他渲染技术承载项目的 View,比如小程序WebView、小游戏、Web浏览器、Canvas、WebGL。
  • Passive View: Ystore架构下的 View 非常薄,没有参杂任何业务逻辑,只做被动改变。
  • Simple and Intuitive: Ystore 内部使用 deepClone + dataDiff 换取最短路径, 比setData 更符合直觉的编程体验,只需修改数据,然后update,不需要再使用 setData(xxxxxxxxxxx)。
  • Testability: View 和 Model 之间没有直接依赖,开发者能够借助模拟对象注入测试两者中的任一方。
  • No invasion: 在使用Ystore的情况下,你依旧可以使用小程序原有的所有语法,Ystore不会带来副作用。

MVP

Ystore 架构和 MVP(Model-View-Presenter) 架构很相似:

  • View 和 Store 是双向通讯,View 和 Store 互相引用
  • View 与 Model 不发生联系,都通过 Store 传递
  • Store 引用 Model 里对象的实例,Model 不依赖 Store
  • View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性
  • Store 非常薄,只负责维护 View 需要的数据和桥接 View 和 Model
  • Model 非常厚,但是都是纯JS逻辑代码,你可以基于业务中的不同指责对你的Model类进行精心设计 所有逻辑都部署在那里,Model 可以脱离 Store 和 View 完整表达所有业务/游戏逻辑

Store 层可以理解成中介者模式中的中介者,使 View 和 Model 之间的多对多关系数量减少为 0,负责中转控制视图对象 View 和模型对象 Model 之间的交互。

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

Packages

| 项目 | 描述 | | ------------------------------- | ----------------------------------- | | src | Ystore 的核心代码 | | examples | Ystore 官方例子|

倒计时案例

应用截图

定义Model

class Countdown extends EventEmitter {
    constructor(endTimes, step = 200) {
        super()
        this.endTimes = endTimes
        this.step = step
        this.start()
    }

    start() {
        this.status = countdownStatus.running
        this.down()
        this.onTick()
    }
    
    down() {
        if(this.status !== countdownStatus.running) {
            return
        }
        const remainCount = Math.max(this.endTimes - Date.now(), 0)
        this.remainTime = this.parseRemainTime(remainCount)
        if(remainCount != 0) {
            this.timer = setTimeout(this.down.bind(this), this.step)
        }else {
            this.stop()
        }
        this.onTick()
    }

     onTick() {
        this.emit(UPDATE)
    }
}

model中封装了核心业务逻辑,当倒计时数据发生变化的时候,会通过发布事件UPDATE通知到相关订阅者

定义Store

import Store from 'Ystore'

class CountdownStore extends Store {
    constructor() {
        super()
        this.data = {
            remainTime: {},
            status: countdownStatus.paused,
        }
    }
    init(endTimes) {
        this.countdown = new Countdown(endTimes, 200)
        // 这里采用了发布订阅的方式进行数据更新通知,可以基于业务需求封装自己的一套
        this.countdown.on(UPDATE, () => {
            // 基于业务需要做数据同步更新的操作
            this.remainTime = this.countdown.remainTime
            Object.keys(this.remainTime).forEach(key => {
                this.remainTime[key] = toFixed(this.remainTime[key])
            })
            this.status = this.countdown.status
            this.update()
        })
    }

    destroy() {
        this.countdown.destroy()
        this.countdown = null
    }
}

store中会订阅Countdown数据更新事件,然后更新data的数据,调用父类Ystore提供的update方法将数据更新到视图层

编写视图

js

import countdownStore from "../../store/countdown-store"

Page({
  data: {},
  onLoad() {
    // 将page与store进行绑定,将store挂在到当前视图countdown路径上,wxml中就可以通过你countdown.xxx的方式直接使用store data定义的数据,当对应数据发生变更的时候会自动更新视图
    countdownStore.bind('countdown', this)
    // 启动倒计时
    countdownStore.init(Date.now() + 28 * 3600 * 1000)
  },
  unOnload() {
    countdownStore.remove(this)     // 进行视图内存回收
    countdownStore.destroy()        // 自定义销毁
  }
})

wxml

<view class="container">
  <view class="count-down">
    <text class="number">{{countdown.remainTime.days}}</text> 天 
    <text class="number">{{countdown.remainTime.hours}}</text> 时 
    <text class="number">{{countdown.remainTime.minutes}}</text> 分 
    <text class="number">{{countdown.remainTime.seconds}}</text> 秒 
    : <text class="number">{{countdown.remainTime.count}}</text>
  </view>
</view>

详细代码点击这里

对于这样简单的程序,或许不值得把这种逻辑分开,但随着需求的膨胀你会发现这么做带来的带来的巨大好处,下面再举一个稍微复杂一点点的例子

TodoApp 案例

扫码预览

应用截图

  

设计类图

todoApp设计类图

其中浅蓝色部分抽离了核心业务逻辑,纯JS代码,并且与平台无关,可以在小程序和web项目共用,不需要修改一行代码

详细代码点击这里

Model抽离的契机

再简单的程序,也有更好的实现

VUE3 做了很大的改动,其中一个比较核心的点是组合式APIVUE3借助组合式API可以很方便的进行业务逻辑的职责分离,使代码具有更好的可读性和可维护性。

在Ystore架构之下,使用面向对象的方式将核心业务逻辑抽离到Model之中,你将bu在纯业务逻辑的Model里面,相较于VUE3组合式API提供的能力,你能做的更多,你可以充分释放想象力,更加优雅的设计你的程序,更加灵活的对职责进行分离。。。写出更好的实现

声明

Ystore站在Westore的肩膀上,在其MVP架构思想的基础之上做了改进与优化,其中包括不限于

  • 支持单view关联多个store
  • 支持单个store服务多个view
  • view支持store与自定义data共存
  • 重写diff算法,提高代码可读性
  • 优化重复diff运算问题
  • 为属性data增加安全处理,防止其地址被篡改
  • 修复内存泄漏问题
  • 支持UI更新后回调

贡献

欢迎,并且非常感谢。按照规范流程提PR即可,提PR之前需运行npm run test保证测试用例全部通过。

License

MIT