omi/docs/main-concepts.cn.md

362 lines
7.0 KiB
Markdown
Raw Normal View History

2018-10-28 21:39:27 +08:00
[English](./main-concepts.md) | 简体中文 | [한국어](./main-concepts.kr.md)
2018-10-18 10:27:55 +08:00
## Omi 文档
2018-10-18 08:22:41 +08:00
2018-10-22 03:50:09 +08:00
- [Omi 文档](#omi-文档)
2018-10-25 21:30:18 +08:00
- [My First Element](#my-first-element)
- [Props](#props)
- [Event](#event)
- [Custom Event](#custom-event)
- [CSS](#css)
- [Ref](#ref)
- [Store](#store)
- [Slot](#slot)
2018-10-28 18:35:11 +08:00
- [Observe](#observe)
2018-10-25 21:30:18 +08:00
- [SSR](#ssr)
2018-10-18 08:22:41 +08:00
2018-10-26 16:11:59 +08:00
[→ Omi Simple Examples](https://github.com/Tencent/omi/tree/master/packages/omi/examples)
2018-10-18 08:22:41 +08:00
### My First Element
```js
2018-10-30 07:18:59 +08:00
import { WeElement, define, render } from 'omi'
2018-10-18 08:22:41 +08:00
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
render() {
return (
<h1>Hello, world!</h1>
)
}
2018-10-18 08:22:41 +08:00
}
render(<my-first-element></my-first-element>, 'body')
```
在 HTML 开发者工具里看看渲染得到的结构:
![fe](../assets/first-element.jpg)
除了渲染到 body你可以在其他任意自定义元素中使用 `my-first-element`
### Props
```js
2018-10-30 07:18:59 +08:00
import { WeElement, define, render } from 'omi'
2018-10-18 08:22:41 +08:00
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
render(props) {
return (
<h1>Hello, {props.name}!</h1>
)
}
2018-10-18 08:22:41 +08:00
}
render(<my-first-element name="world"></my-first-element>, 'body')
```
你也可以传任意类型的数据给 props:
```js
2018-10-30 07:18:59 +08:00
import { WeElement, define, render } from 'omi'
2018-10-18 08:22:41 +08:00
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
render(props) {
return (
<h1>Hello, {props.myObj.name}!</h1>
)
}
2018-10-18 08:22:41 +08:00
}
render(<my-first-element my-obj={{ name: 'world' }}></my-first-element>, 'body')
```
`my-obj` 将映射到 myObj驼峰的方式。
### Event
```js
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
onClick = (evt) => {
alert('Hello Omi!')
}
render() {
return (
2018-10-30 07:18:59 +08:00
<h1 onClick={this.onClick}>Hello, world!</h1>
2018-10-22 03:50:09 +08:00
)
}
2018-10-30 07:18:59 +08:00
})
2018-10-18 08:22:41 +08:00
```
### Custom Event
```js
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
onClick = (evt) => {
this.fire('myevent', { name: 'abc' })
}
render(props) {
return (
<h1 onClick={this.onClick}>Hello, world!</h1>
)
}
2018-10-30 07:18:59 +08:00
})
2018-10-18 08:22:41 +08:00
render(<my-first-element onMyEvent={(evt) => { alert(evt.detail.name) }}></my-first-element>, 'body')
```
2018-10-18 10:22:50 +08:00
通过 `this.fire` 触发自定义事件fire 第一个参数是事件名称,第二个参数是传递的数据。通过 `evt.detail` 可以获取到传递的数据。
2018-10-18 08:22:41 +08:00
2018-10-23 09:18:59 +08:00
### CSS
```js
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-23 09:18:59 +08:00
css() {
return `h1 { color: red; }`
}
render(props) {
return (
<h1>Hello, world!</h1>
)
}
}
render(<my-first-element onMyEvent={(evt) => { alert(evt.detail.name) }}></my-first-element>, 'body')
```
你也可以在 JS 里动态拼接 CSS:
```js
css() {
return `h1 { color: ${Math.random() > 0.5 ? "red" : "blue"}; }`
}
```
你也可以另起一个文件用来写 CSS但是需要配置一下 webpack [to-string-loader](https://www.npmjs.com/package/to-string-loader)
```js
{
test: /[\\|\/]_[\S]*\.scss$/,
use: [
'to-string-loader',
'css-loader',
'sass-loader'
]
}
```
然后:
```js
2018-10-30 07:18:59 +08:00
import { define, WeElement } from 'omi'
2018-10-23 09:18:59 +08:00
import style from '../style/_button.scss'
2018-10-30 07:18:59 +08:00
define('el-button', class extends WeElement {
static pure = true
2018-10-23 09:18:59 +08:00
css() {
return style
}
...
...
```
2018-10-18 08:22:41 +08:00
### Ref
```js
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
onClick = (evt) => {
console.log(this.h1)
}
render(props) {
return (
<div>
<h1 ref={e => { this.h1 = e }} onClick={this.onClick}>Hello, world!</h1>
</div>
)
}
2018-10-30 07:18:59 +08:00
})
2018-10-18 08:22:41 +08:00
render(<my-first-element></my-first-element>, 'body')
```
2018-10-18 11:19:30 +08:00
在元素上添加 `ref={e => { this.anyNameYouWant = e }}` ,然后你就可以 JS 代码里使用 `this.anyNameYouWant` 访问该元素。
### Store
```js
2018-10-30 07:18:59 +08:00
define('my-first-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
//You must declare data here for view updating
static get data() {
return { name: null }
}
onClick = () => {
//auto update the view
this.store.data.name = 'abc'
}
render(props, data) {
2018-10-30 07:18:59 +08:00
//data === this.store.data when using store system
2018-10-22 03:50:09 +08:00
return (
<h1 onClick={this.onClick}>Hello, {data.name}!</h1>
)
}
2018-10-30 07:18:59 +08:00
})
2018-10-18 11:19:30 +08:00
const store = {
2018-10-22 03:50:09 +08:00
data: { name: 'Omi' }
2018-10-18 11:19:30 +08:00
}
render(<my-first-element name="world"></my-first-element>, 'body', store)
```
2018-10-19 14:19:44 +08:00
当非纯 Element 使用 store 体系时,`static get data` 就仅仅被用来声明依赖,举个例子:
2018-10-18 11:19:30 +08:00
```js
static get data() {
2018-10-22 03:50:09 +08:00
return {
a: null,
b: null,
c: { d: [] },
e: []
}
2018-10-18 11:19:30 +08:00
}
```
会被转换成:
```js
{
a: true,
b: true,
'c.d':true,
e: true
}
```
举例说明 Path 命中规则:
2018-10-22 03:50:09 +08:00
| Proxy Path | updatePath | 是否更新 |
| ---------- | ---------- | -------- |
| abc | abc | 更新 |
| abc[1] | abc | 更新 |
| abc.a | abc | 更新 |
| abc | abc.a | 不更新 |
| abc | abc[1] | 不更新 |
| abc | abc[1].c | 不更新 |
| abc.b | abc.b | 更新 |
2018-10-18 11:19:30 +08:00
以上只要命中一个条件就可以进行更新!
总结就是只要等于 updatePath 或者在 updatePath 子节点下都进行更新!
看可以看到 store 体系是中心化的体系?那么怎么做到部分组件去中心化?使用 tag 的第二个参数:
```js
@tag('my-first-element', true)
```
2018-10-18 15:53:33 +08:00
纯元素!不会注入 store!
2018-10-19 15:47:18 +08:00
2018-10-19 19:24:08 +08:00
### Slot
2018-10-19 19:27:41 +08:00
HTML`<slot>`元素Web组件技术套件的一部分是Web组件内部的占位符您可以用自己的标记填充该占位符该标记允许您创建单独的DOM树并将它们一起呈现。
2018-10-19 19:24:08 +08:00
2018-10-19 19:26:27 +08:00
```jsx
2018-10-30 07:18:59 +08:00
define('hello-element', class extends WeElement {
2018-10-22 03:50:09 +08:00
render() {
return (
<div onClick={this.onClick}>
<p><slot name="my-text">My default text</slot></p>
</div>
)
}
2018-10-30 07:18:59 +08:00
})
2018-10-19 19:24:08 +08:00
2018-10-30 07:18:59 +08:00
define('my-app', class extends WeElement {
2018-10-22 03:50:09 +08:00
render() {
return (
<div >
<hello-element>
<span slot="my-text">Let's have some different text!</span>
</hello-element>
</div>
)
}
2018-10-19 19:24:08 +08:00
}
render(<my-app></my-app>, 'body')
```
[→ Slot MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots#Adding_flexibility_with_slots)
2018-10-28 18:35:11 +08:00
### Observe
#### Omi Observe
你可以为那些不需要 store 的自定义元素使用 observe 创建响应式视图,比如:
2018-10-26 16:00:52 +08:00
```js
2018-10-30 07:18:59 +08:00
define("my-app", class extends WeElement {
static observe = true
2018-10-28 18:35:11 +08:00
install() {
this.data.name = "omi"
}
onClick = () => {
this.data.name = "Omi V4.0"
}
render(props, data) {
return (
<div onClick={this.onClick}>
<h1>Welcome to {data.name}</h1>
</div>
)
}
}
2018-10-26 16:00:52 +08:00
```
2018-10-28 18:35:11 +08:00
如果你想要兼容 IE11,请使用 `omi-mobx` 代替 omi 自带的 obersve往下看..
#### Omi Mobx
2018-10-26 16:00:52 +08:00
```js
2018-10-28 18:35:11 +08:00
import { tag, WeElement } from "omi"
import { observe } from "omi-mobx"
@observe
@tag("my-app")
class MyApp extends WeElement {
install() {
this.data.name = "omi"
}
onClick = () => {
this.data.name = "Omi V4.0"
}
2018-10-26 16:00:52 +08:00
2018-10-28 18:35:11 +08:00
render(props, data) {
return (
<div onClick={this.onClick}>
<h1>Welcome to {data.name}</h1>
</div>
)
}
}
```
2018-10-26 16:00:52 +08:00
2018-10-19 15:47:18 +08:00
### SSR
推荐尝试的框架:
* https://github.com/skatejs/skatejs/tree/master/packages/ssr
2018-10-23 22:11:03 +08:00
* https://www.youtube.com/watch?v=yT-EsESAmgA