Gathering detailed insights and metrics for mobx-provide-pro
Gathering detailed insights and metrics for mobx-provide-pro
Gathering detailed insights and metrics for mobx-provide-pro
Gathering detailed insights and metrics for mobx-provide-pro
npm install mobx-provide-pro
Typescript
Module System
Node Version
NPM Version
TypeScript (55.25%)
JavaScript (28.96%)
HTML (12.94%)
CSS (2.85%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
10 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Jun 08, 2020
Latest Version
1.1.5
Package Id
mobx-provide-pro@1.1.5
Unpacked Size
16.06 kB
Size
5.35 kB
File Count
4
NPM Version
6.13.4
Node Version
12.14.0
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
npm i mobx-provide-pro --save
provide(provideName, provideClass, storeId)
provideName
声明一个name
,在同一组嵌套关系中此 name 唯一,重复的 name 会覆盖最近父节点的同名 store
provideClass
store 构造方法,必须继承自IStoreBase
storeId
声明一个全局storeId
,此 id 全局唯一,同名的 storeid 会显示抛出异常,通过使用getStoreById
可以在任何地方获取到这个 store ,前提是 provide 此 store 的组件必须存在。
provide
向当前组件提供一个 store, 基于 react 的 context 特性,在该组件和其所有的后代组件中都可以通过connect
方法获取到这个 store
通过 provide 可以无视组件嵌套层级而共享一组状态,此状态在该组件和其所有的后代组件中都可见,默认在组件层级之外无法访问,除非提供 storeId
store 具有生命周期,在组件之前创建并且在组件之后销毁,这意味着在组件的所有生命周期中都可以访问_store_,包括constructor
和componentWillUnmount
。可以在 store 的onDestory
方法中做一些清理工作,例如:轮询任务,定时器,mobx reaction
等。
1st=>start: store constructor 2op2=>operation: ...组件生命周期... 3end=>end: store onDestory 4 5st->op2->end
提供storeId
将会在一个全局的 HashMap 中注册该 store ,在组件卸载后会自动从 HashMap 中移除。通过getStoreById
可以在组件嵌套层级之外获取到这个状态,例如:在页面中与顶部栏或者侧边栏进行交互,而页面可能与其并不具有父子关系。解决此问题还可以使用 状态提升
connect(...storeNames)
storeNames
store 的name
序列,所有的name
都必须在此次connect
的组件的上层组件中被provide
过,否则会抛出异常。可以嵌套provide
只需保证命名不同,组件之中使用this.props.name
的方式获取 store , 在mobx非严格模式下可以修改状态并刷新视图。
getStoreById(id)
id
通过provide
方法或者provide属性
指定的全局ID,此ID全局唯一,重复则会抛出异常。<App provide={storeInstance} />
<App provide={[storeInstance]} />
<App provide={[storeIntance, storeId]} />
storeInstance
store 实例,通过provide
提供的 store 会在每次组件创建时创建,此参数会阻止其默认行为,storeInstance
会替换默认生成的 store 实例,这意味着可以在组件外部去管理状态,可以参考状态提升章节。但即使传入全局实例也会在组件卸载时执行onDestory
方法,而此实例却只会创建一次,这在数据持久化存储中发挥作用。
storeId
全局的storeId
,作用同provide
方法的第三个参数,一旦在属性中提供则会覆盖provide
中的storeId
值。及时使用全局实例,在 provide 组件卸载时其对应的 store 依然从全局 HashMap 中移除,所以通过id
获取状态之前请确认组件是否还在挂载中,否则会返回undefined
1class AppStore extends IStoreBase{ 2 3 @observable public message = "hello"; 4 5 @action setMessage(message: string) { 6 this.message = message; 7 } 8} 9 10interface IProps extends IProvideProps { 11 db?: AppStore, 12} 13 14 15@provide("db", AppStore) 16@connect("db") 17export default class App extends React.Component<IProps> { 18 19 public render() { 20 return ( 21 <div className="App"> 22 App {this.props.db?.message} 23 <Wrap> 24 <Inner /> 25 </Wrap> 26 </div> 27 ); 28 } 29} 30 31const Wrap = (props: any) => <div>{props.children}</div> 32 33const Inner = connect("db")((props: IProps) => { 34 const onClick = () => { 35 props.db?.setMessage("world"); 36 } 37 return <button onClick={onClick}>{props.db?.message}</button> 38})
App
和Inner
共享同一组状态,由于connect
的内部已经实现了 observer,而不需要再次声明,任何时候只要改变message
都会同时刷新这两个组件。注意到Inner
并非App
的直接子组件。
对于需要在App
和Inner
之间交互的状态,我们都应该将其放在AppStore
中。由于AppStore
会在App
组件卸载时销毁,因此其是状态安全的,我们也可以将非交互状态也放置其中,或者使用AppStore
取代组件的state
,任何时候组件只需要负责渲染而不需要关心数据来源。
1// table.tsx 2 3class TableStore extends IStoreBase{ 4 @observable public count = 10; 5 @observable public page = 1; 6 @observable public data = []; 7 8 @action queryData() { 9 fetch("/data.action").then((res: Response) => res.json()).then((json) => { 10 this.count = json.count; 11 this.page = json.page; 12 this.data = json.data || []; 13 }); 14 } 15} 16 17interface ITableProps extends IProvideProps { 18 db?: TableStore, 19} 20 21@provide("db", TableStore) 22@connect("db") 23class Table extends React.Component<ITableProps> { 24 25 componentDidMount() { 26 this.props.db?.queryData(); 27 } 28 29 public render() { 30 const {count, page, data} = this.props.db || {}; 31 return <div> 32 <div>{data}</div> 33 <p>第{page}页,共{count}条</p> 34 </div>; 35 } 36}
在Table
的 store 中声明了三个变量分别表示数据总数、当前页、表格数据,在componentDidMount
中进行数据加载。
1// app.tsx 2 3class AppStore extends IStoreBase{ 4 public table = new TableStore(); 5} 6 7interface IAppProps extends IProvideProps { 8 db?: AppStore, 9} 10 11@provide("db", AppStore) 12@connect("db") 13export default class App extends React.Component<IAppProps> { 14 15 private onClick = () => { 16 this.props.db?.table.queryData(); 17 } 18 19 public render() { 20 return <div> 21 <Table provide={this.props.db?.table} /> 22 <button onClick={this.onClick}>刷新</button> 23 </div> 24 } 25}
在App
中实现对Table
的数据刷新,这里使用了状态提升,即将子组件的 store 提升至其父组件中,以便对父组件完全受控,状态提升也可以跨越层级。
这里的App
和Table
使用了相同的provideName
, 这意味着Table
组件会覆盖App
提供的 store,从而无法访问该状态。
App
的provide属性
会覆盖Table
组件默认的provide
,对Table
来说没有任何变化,它与 store 交互而无需知道该 store 由谁提供。而App
可以像操纵自己的状态一样随意操纵Table
的状态,因此可以在App中复制多个Table
,甚至实现它们之间的联动。
1class AppStore extends IStoreBase{ 2 public table1 = new TableStore(); 3 public table2 = new TableStore(); 4} 5 6interface IAppProps extends IProvideProps { 7 db?: AppStore, 8} 9 10@provide("db", AppStore) 11@connect("db") 12export default class App extends React.Component<IAppProps> { 13 14 private onClick = () => { 15 this.props.db?.table1.queryData(); 16 this.props.db?.table2.queryData(); 17 } 18 19 public render() { 20 return <div> 21 <Table provide={this.props.db?.table1} /> 22 <Table provide={this.props.db?.table2} /> 23 <button onClick={this.onClick}>刷新</button> 24 </div> 25 } 26}
也可以对两个Table
提供相同的 store 使它们共用同一个状态,任意一个Table
修改状态也会同时反映到另一个上。
有时候我们需要在两个组件之间通信,但他们并不具备嵌套关系。可以使用状态提升将他们的状态提升至共同父组件、根组件,甚至可以提升至全局。
1// loading.tsx 2 3export class LoadingStore extends IStoreBase { 4 @observable public visible = false; 5 6 @action public setVisible(visible: boolean) { 7 this.visible = visible; 8 } 9} 10 11interface ILoadingProps extends IProvideProps { 12 db?: LoadingStore, 13} 14 15@provide("db", LoadingStore) 16@connect("db") 17class Loading extends React.Component<ILoadingProps> { 18 19 public render() { 20 const {visible} = this.props.db || {}; 21 return visible ? <div>加载中...</div> : <i />; 22 } 23 24}
1// app.tsx 2 3export const loadingStore = new LoadingStore(); 4 5export const App = () => { 6 return <div> 7 <Loading provide={loadingStore}/> 8 <Wrap> 9 <Inner /> 10 </Wrap> 11 </div> 12}
使用storeId
将状态注册到全局 HashMap 中,在需要访问的地方使用getStoreById
获取状态。
1// loading.tsx 2 3export class LoadingStore extends IStoreBase { 4 @observable public visible = false; 5 6 @action public setVisible(visible: boolean) { 7 this.visible = visible; 8 } 9} 10 11interface ILoadingProps extends IProvideProps { 12 db?: LoadingStore, 13} 14 15@provide("db", LoadingStore, "loading") 16@connect("db") 17export class Loading extends React.Component<ILoadingProps> { 18 19 public render() { 20 const {visible} = this.props.db || {}; 21 return visible ? <div>加载中...</div> : <i />; 22 } 23 24}
1// app.tsx 2 3const App = () => { 4 return <div> 5 <Loading /> 6 <Wrap> 7 <Inner /> 8 </Wrap> 9 </div> 10} 11 12const Wrap = (props: any) => <div>{props.children}</div> 13 14const Inner = observer(() => { 15 const onClick = () => { 16 const loading: LoadingStore = getStoreById("loading"); 17 loading.setVisible(true); 18 } 19 return <button onClick={onClick}>显示Loading</button> 20}) 21 22export default App;
使用mobx-provide可以很容易进行视图重构,因为进行重构不需要关心数据,我们可以很容易复杂组件拆分成众多小组件,也可以将小组件合并成大组件,甚至重新写一套视图组件。
一般情况下,每个状态改变都会引起组件重新渲染,observer
包裹的组件会自动浅层渲染,将组件拆分成更小的单元,可以避免某些视图不必要的渲染,这对于大数据渲染有很大的性能提升。
1class AppStore extends IStoreBase{ 2 3 @observable public list = [...Array(1000).keys()]; 4 @observable public count = 0; 5 6 @action increase() { 7 this.count ++; 8 } 9} 10 11interface IProps extends IProvideProps { 12 db?: AppStore, 13} 14 15@provide("db", AppStore) 16@connect("db") 17export default class App extends React.Component<IProps> { 18 19 private click = () => { 20 this.props.db?.increase(); 21 } 22 23 public render() { 24 const { list = [], count } = this.props.db || {}; 25 return ( 26 <div className="App"> 27 <ul> 28 {list.map((e: number) => <li key={e}>{e}</li>)} 29 </ul> 30 <button onClick={this.click}>{count}</button> 31 </div> 32 ); 33 } 34}
上面的App
组件会在每次click
按钮时递增,并且每次点击都会渲染一个长度为1000的列表,为了避免列表不必要的渲染,可以考虑将按钮放置到一个单独组件中。
1class AppStore extends IStoreBase{ 2 3 @observable public list = [...Array(1000).keys()]; 4 @observable public count = 0; 5 6 @action increase() { 7 this.count ++; 8 } 9} 10 11interface IProps extends IProvideProps { 12 db?: AppStore, 13} 14 15@provide("db", AppStore) 16@connect("db") 17export default class App extends React.Component<IProps> { 18 public render() { 19 const { list = [] } = this.props.db || {}; 20 return ( 21 <div className="App"> 22 <ul> 23 {list.map((e: number) => <li key={e}>{e}</li>)} 24 </ul> 25 <Button /> 26 </div> 27 ); 28 } 29} 30 31const Button = connect("db")((props: IProps) => { 32 const click = () => { 33 props.db?.increase(); 34 } 35 const { count } = props.db || {}; 36 return <button onClick={click}>{count}</button> 37})
对于同样的点击事件,后者只会渲染Button
组件。
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
Found 0/10 approved changesets -- score normalized to 0
Reason
no SAST tool detected
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
license file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
123 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More