0.6.12 • Published 2 months ago

hooks-view-model v0.6.12

Weekly downloads
-
License
-
Repository
github
Last release
2 months ago

hooks-view-model

Table of Contents

Online demo

快速介绍

一个可以让 react hooks 支持 mvvm 的解决方案而无需引入任何第三方库,旨在将 UI 与业务逻辑分离,并提供不可变数据和全局状态管理、内存管理和持久数据管理,并提供直观的 API。使用hooks-view-model将带来如下诸多便利:

  • 💼 提供全局与局部state管理,无需引入reducer或redux等状态管理方案;
  • 🌲 提供全局缓存与持久化数据存储管理;
  • 🎩 可使业务代码更具有组织性,可维护性和可测试性,职责划分更清晰。
  • 🍰 有效避免组件内部太多state需要管理的问题,以对象形式简化useState,setState写法。
  • 🍷 基于class的ViewModel内部无需关心hooks,可以做到更加专注业务逻辑开发。
  • 👋 可实现全局数据更新,跨组件数据传递,无需useReducer或context
  • 🌲 依据key划分不同store,view组件不会响应未使用到的store的状态变化,可解约性能开销
  • 🍳 ViewModel将提供基础的生命周期函数,相较于useEffect 处理异步函数更方便
  • 🍖 ViewModel 会根据react hooks生命周期自动触发内存回收,内存管理更方案
  • 🥒 无需使用useCallback 处理因避免函数引用变动所导致的组件重渲染问题。
  • 🍰 调用updater更新后,可同步获取最新的state值
  • 👋 可实现细粒度更新对象的属性值,可实现immutable data

与hooks对比

hooks-view-model` 主要用于分离UI与业务逻辑,可以解决 纯hooks组件的问题:

hooks组件问题hooks-view-model
通常需要设置多个useState,无法细粒度更新属性值可通过对象形式更新与解构数据,可细粒度更新属性值
使用useReducer+context全局共享状态思维负担大全局状态更新只需使用useGlobalStatehooks,api符合直觉,用法简单
useEffect模拟mounted缺乏语义化,请求异步函数处理麻烦提供mounted和unmounted 钩子函数,语义化友好。非常适合异步处理
当组件达到一定复杂度的时候,堆积到一起的代码会变得越来越难以维护UI与逻辑做到了很好的分离,代码组织性强
React Hook的闭包陷阱问题由于方法都提到class中去维护了,所以不存在此问题
useState 调用updater更新后,无法同步获取最新state值可通过调用getCurrentState 同步获取最新值
useState updater 无法实现细粒度更新对象属性值,需浅拷贝对象后覆盖可通过updateImmerState实现细粒度更新
useState updater 无法实现immutable 数据,即使memo 包裹子组件也会re-render可通过updateImmerState实现immutable 数据,不会re-render子组件

安装

$ yarn add hooks-view-model

什么时候使用这个库

  1. 当你的业务项目很复杂,需要考虑分离UI与业务逻辑时
  2. 当你进行团队协作时,你想要统一团队成员一致风格时
  3. 当你想要在项目解决以上hooks缺陷或者闭包带来的困惑时

什么时候不用这个库

  1. 当你正在开发组件库时,或者你的项目与业务无关时
  2. 如果你不喜欢class的写法时,可以尝试这个库 use-better-state

实例

Counter.View.tsx is only for display ui and responding to updates to useCurrentState and useGlobalState

// Counter.View.tsx
import { CounterViewModel } from './Counter.ViewModel'
import { useVM } from 'hooks-view-model'

const CounterView = () => {
  const {  useCurrentState, increment, changeUserAge } = useVM(CounterViewModel, {
    count: 0, // 作为props传递给 CounterViewModel
  })
  const { user , count } = useCurrentState({
    user: { name: 'nilu', age: 0}
  });
  console.log('user', user);// {name: 'nilu', age: 10}
  return (
    <div>
      <button onClick={increment}>click to count</button>
      <button onClick={changeUserAge}>click to change user age</button>
      <span>{count}</span>
    </div>
  )
}

Counter.ViewModel.ts

// Counter.ViewModel.ts
import  StoreViewModel from 'hooks-view-model'

class CounterViewModel extends StoreViewModel {
  increment = () => {
    const { count } = this.props;// 通过this.props访问来自useVM传递过来的数据
    updateCurrentState({ count: count + 1 });
  };
   changeUserAge = () => {
    this.updateImmerState((draft) => {
      draft.user.age = 10;
    })
  },
  mounted = async () => {
    await someAsyncRequest();//当 componentDidMount 时自动运行
  }
  unmounted = () => {
    window.removeEventListener('');// 当componentWillUnmount 时自动运行
  }
}
export { CounterViewModel } 

模板生成

你可以根据如下步骤快速生成项目模板:

scripts: {
  "generate": "plop --plopfile ./node_modules/hooks-view-model/generators/index.js"
}

2、在根目录创建 template.config.js :

const dir_to_generate = './src/pages/';

module.exports = dir_to_generate;

API 文档

更多使用方法和api 文档相关信息,可访问如下链接:

English Api docs | 中文Api文档

Q & A

更多问题与解答,请访问: Q & A

0.6.10

2 months ago

0.6.12

2 months ago

0.6.11

2 months ago

0.6.6

1 year ago

0.6.2

1 year ago

0.6.1

1 year ago

0.5.1

2 years ago

0.4.10

2 years ago

0.4.1

2 years ago

0.3.12

2 years ago

0.3.11

2 years ago

0.3.10

2 years ago

0.3.7

2 years ago

0.3.6

2 years ago

0.3.5

2 years ago

0.3.4

2 years ago

0.3.2

2 years ago

0.2.4

2 years ago