update main concepts
This commit is contained in:
parent
4025878659
commit
0cb9d4f91a
|
@ -308,101 +308,133 @@ define('my-element', class extends WeElement {
|
|||
|
||||
### Store
|
||||
|
||||
Omi 的 Store 体系: 从根组件注入,在所有子组件可以共享。使用起来非常简单:
|
||||
Store 是 Omi 内置的中心化数据仓库,他解决和提供了下面问题和能力:
|
||||
|
||||
```js
|
||||
import { define, render, WeElement } from 'omi'
|
||||
* 组件树数据共享
|
||||
* 数据变更按需更新依赖的组件
|
||||
|
||||
define('my-hello', class extends WeElement {
|
||||
render() {
|
||||
//任意子组件的任意方法都可以使用 this.store 访问注入的 store
|
||||
return <div>{this.store.name}</div>
|
||||

|
||||
|
||||
## 一段代码完全上手 Store
|
||||
|
||||
```jsx
|
||||
import { render, WeElement, define } from '../../src/omi'
|
||||
|
||||
define('my-counter', class extends WeElement {
|
||||
static use = [
|
||||
{ count: 'count' }
|
||||
]
|
||||
|
||||
add = () => this.store.add()
|
||||
sub = () => this.store.sub()
|
||||
|
||||
addIfOdd = () => {
|
||||
if (this.use.count % 2 !== 0) {
|
||||
this.store.add()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
define('my-app', class extends WeElement {
|
||||
handleClick = () => {
|
||||
//任意子组件的任意方法都可以使用 this.store 访问注入的 store
|
||||
this.store.reverse()
|
||||
this.update()
|
||||
addAsync = () => {
|
||||
setTimeout(() => this.store.add(), 1000)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<p>
|
||||
Clicked: {this.use.count} times
|
||||
{' '}
|
||||
<button onClick={this.add}>+</button>
|
||||
{' '}
|
||||
<button onClick={this.sub}>-</button>
|
||||
{' '}
|
||||
<button onClick={this.addIfOdd}>
|
||||
Add if odd
|
||||
</button>
|
||||
{' '}
|
||||
<button onClick={this.addAsync}>
|
||||
Add async
|
||||
</button>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
render(<my-counter />, 'body', {
|
||||
data: {
|
||||
count: 0
|
||||
},
|
||||
sub() {
|
||||
this.data.count--
|
||||
},
|
||||
add() {
|
||||
this.data.count++
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
* 通过 `static use` 声明依赖的 path
|
||||
* `store` 通过 render 的第三个参数从根节点注入到所有组件。
|
||||
|
||||
下面举一个复杂的 `use` 例子:
|
||||
|
||||
```jsx
|
||||
static use = [
|
||||
'count', //直接字符串,JSX 里可通过 this.use[0] 访问
|
||||
'arr[0]', //也支持 path,JSX 里可通过 this.use[1] 访问
|
||||
//支持 json
|
||||
{
|
||||
//alias,JSX 里可通过 this.use.reverseMotto 访问
|
||||
reverseMotto: [
|
||||
'motto', //path
|
||||
target => target.split('').reverse().join('') //computed
|
||||
]
|
||||
},
|
||||
{ name: 'arr[1]' }, //{ alias: path },JSX 里可通过 this.use.name 访问
|
||||
{
|
||||
//alias,JSX 里可通过 this.use.fullName 访问
|
||||
fullName: [
|
||||
['userInfo.firstName', 'userInfo.lastName'], //path array
|
||||
(firstName, lastName) => firstName + lastName //computed
|
||||
]
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
下面看看 JSX 中使用:
|
||||
|
||||
```jsx
|
||||
...
|
||||
...
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.sub}>-</button>
|
||||
<span>{this.use[0]}</span>
|
||||
<button onClick={this.add}>+</button>
|
||||
<div>
|
||||
<my-hello />
|
||||
<button onclick={this.handleClick}>reverse</button>
|
||||
<span>{this.use[1]}</span>
|
||||
<button onClick={this.rename}>rename</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const store = {
|
||||
name: 'abc',
|
||||
reverse: function() {
|
||||
this.name = this.name.split("").reverse().join("")
|
||||
}
|
||||
<div>{this.use.reverseMotto}</div><button onClick={this.changeMotto}>change motto</button>
|
||||
<div>{this.use.name}</div>
|
||||
<div>{this.use[3]}</div>
|
||||
<div>
|
||||
{this.use.fullName}
|
||||
<button onClick={this.changeFirstName}>change first name</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
//通过第三个参数注入
|
||||
render(<my-app />, document.body, store)
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
与全局变量不同的是, 当有多个根节点的时候就可以注入多个 store,而全局变量只有一个。
|
||||
如果不带有 alias ,你也可以直接通过 `this.store.data.xxx` 访问。
|
||||
|
||||
<!--
|
||||
```js
|
||||
define('my-first-element', class extends WeElement {
|
||||
//You must declare data here for view updating
|
||||
static get data() {
|
||||
return { name: null }
|
||||
}
|
||||
|
||||
onClick = () => {
|
||||
//auto update the view
|
||||
this.store.data.name = 'abc'
|
||||
}
|
||||
当 `store.data` 发生变化,依赖变更数据的组件会进行更新,举例说明 Path 命中规则:
|
||||
|
||||
render(props, data, store) {
|
||||
return (
|
||||
<h1 onClick={this.onClick}>Hello, {store.data.name}!</h1>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const store = {
|
||||
data: { name: 'Omi' }
|
||||
}
|
||||
render(<my-first-element name="world"></my-first-element>, 'body', store)
|
||||
```
|
||||
|
||||
当非纯 Element 使用 store 体系时,`static get data` 就仅仅被用来声明依赖,举个例子:
|
||||
|
||||
```js
|
||||
static get data() {
|
||||
return {
|
||||
a: null,
|
||||
b: null,
|
||||
c: { d: [] },
|
||||
e: []
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
会被转换成:
|
||||
|
||||
```js
|
||||
{
|
||||
a: true,
|
||||
b: true,
|
||||
'c.d':true,
|
||||
e: true
|
||||
}
|
||||
```
|
||||
|
||||
举例说明 Path 命中规则:
|
||||
|
||||
| Proxy Path(由数据更改产生) | updatePath(定义在组件的静态data上) | 是否更新 |
|
||||
| Proxy Path(由数据更改产生) | static use 中的 path | 是否更新 |
|
||||
| ---------- | ---------- | -------- |
|
||||
| abc | abc | 更新 |
|
||||
| abc[1] | abc | 更新 |
|
||||
|
@ -414,8 +446,7 @@ static get data() {
|
|||
|
||||
以上只要命中一个条件就可以进行更新!
|
||||
|
||||
总结就是只要等于 updatePath 或者在 updatePath 子节点下都进行更新! -->
|
||||
|
||||
总结: 只要注入组件的 path 等于 use 里声明 或者在 use 里声明的其中 path 子节点下就会进行更新!
|
||||
|
||||
### Slot
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ The `classNames` is the same as [classnames](https://github.com/JedWatson/classn
|
|||
|
||||
### Store
|
||||
|
||||
Omi Store Architecture: Injected from the root component and shared across all subcomponents. It's very simple to use:
|
||||
<!-- Omi Store Architecture: Injected from the root component and shared across all subcomponents. It's very simple to use:
|
||||
|
||||
```js
|
||||
import { define, render, WeElement } from 'omi'
|
||||
|
@ -362,26 +362,25 @@ const store = {
|
|||
}
|
||||
//Injection through a third parameter
|
||||
render(<my-app />, document.body, store)
|
||||
```
|
||||
``` -->
|
||||
|
||||
Unlike global variables, when there are multiple root nodes, multiple stores can be injected.
|
||||
|
||||
<!--
|
||||
```js
|
||||
define('my-first-element', class extends WeElement {
|
||||
//You must declare data here for view updating
|
||||
static get data() {
|
||||
return { name: null }
|
||||
}
|
||||
//You must declare use here for view updating
|
||||
static use = [
|
||||
{ myName: 'name' }
|
||||
]
|
||||
|
||||
onClick = () => {
|
||||
//auto update the view
|
||||
this.store.data.name = 'abc'
|
||||
}
|
||||
|
||||
render(props, data, store) {
|
||||
render() {
|
||||
return (
|
||||
<h1 onClick={this.onClick}>Hello, {store.data.name}!</h1>
|
||||
<h1 onClick={this.onClick}>Hello, {this.use.myName}!</h1>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -392,33 +391,10 @@ const store = {
|
|||
render(<my-first-element name="world"></my-first-element>, 'body', store)
|
||||
```
|
||||
|
||||
The static data will be transform to path for partial view updating, for example:
|
||||
|
||||
```js
|
||||
static get data() {
|
||||
return {
|
||||
a: null,
|
||||
b: null,
|
||||
c: { d: [] },
|
||||
e: []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Transformed path:
|
||||
|
||||
```js
|
||||
{
|
||||
a: true,
|
||||
b: true,
|
||||
'c.d':true,
|
||||
e: true
|
||||
}
|
||||
```
|
||||
|
||||
Exemplify the Path hit rule:
|
||||
|
||||
| proxy path | updatePath | Update |
|
||||
| proxy path | use path | Update |
|
||||
| ---------- | ---------- | ------ |
|
||||
| abc | abc | true |
|
||||
| abc[1] | abc | true |
|
||||
|
@ -432,6 +408,7 @@ If you hit one condition above, you can update it.
|
|||
|
||||
Summary is as long as updatePath or updatePath sub nodes are updated.
|
||||
|
||||
<!--
|
||||
#### Summary
|
||||
|
||||
- `store.data` is used to list all attributes and default values (except the components of the view decided by props).
|
||||
|
|
Loading…
Reference in New Issue