update main concepts

This commit is contained in:
dntzhang 2019-03-14 17:56:22 +08:00
parent 4025878659
commit 0cb9d4f91a
2 changed files with 122 additions and 114 deletions

View File

@ -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>
![](https://github.com/Tencent/omi/raw/master/assets/store.jpg)
## 一段代码完全上手 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]', //也支持 pathJSX 里可通过 this.use[1] 访问
//支持 json
{
//aliasJSX 里可通过 this.use.reverseMotto 访问
reverseMotto: [
'motto', //path
target => target.split('').reverse().join('') //computed
]
},
{ name: 'arr[1]' }, //{ alias: path }JSX 里可通过 this.use.name 访问
{
//aliasJSX 里可通过 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

View File

@ -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).