| [omi-docs](https://github.com/Tencent/omi/blob/master/docs/main-concepts.md)| Omi official documents |
| [omip![](https://raw.githubusercontent.com/dntzhang/cax/master/asset/hot.png) ](https://github.com/Tencent/omi/tree/master/packages/omip)| 直接使用 Omi 开发小程序!!!|
| [omio![](https://raw.githubusercontent.com/dntzhang/cax/master/asset/hot.png) ](https://github.com/Tencent/omi/tree/master/packages/omio)| Omi for old browsers(IE8+ and mobile browsers).|
| [omiu![](https://raw.githubusercontent.com/dntzhang/cax/master/asset/hot.png)](https://tencent.github.io/omi/packages/omiu/examples/build/index.html)| Omi official UI|
| [omix![](https://raw.githubusercontent.com/dntzhang/cax/master/asset/hot.png) ](https://github.com/Tencent/omi/tree/master/packages/omix)| Tiny size mini programe framework.|
| [omi-chart](https://github.com/Tencent/omi/tree/master/packages/omi-chart)| Simple HTML5 Charts using chart-x tag.|
| [md2site](https://tencent.github.io/omi/assets/md2site/)| Static Site Generator with markdown powered by Omio.|
| [omi-mvvm](https://github.com/Tencent/omi/blob/master/tutorial/omi-mvvm.md)| MVVM comes back bravely with [mappingjs](https://github.com/Tencent/omi/tree/master/packages/mappingjs) strong support.|
| [omi-html](https://github.com/Tencent/omi/tree/master/packages/omi-html)| Using [htm](https://github.com/developit/htm) in omi.|
| [omi-30-seconds](https://github.com/Tencent/omi/tree/master/packages/omi-30-seconds)| Useful Omi snippets that you can understand in 30 seconds.|
| [omi-canvas](https://github.com/Tencent/omi/tree/master/packages/omi-canvas)| Perfect fusion of web components, jsx and canvas.|
| [omi-mp](https://github.com/Tencent/omi/tree/master/packages/omi-mp)| Develop and generate Web HTML5 Single-Page Applications by wechat mini program. The output source is base on omi + [omi-router](https://github.com/Tencent/omi/tree/master/packages/omi-router)|
| [omi-router](https://github.com/Tencent/omi/tree/master/packages/omi-router) |Omi official router in 1KB js. [→ DEMO](https://tencent.github.io/omi/packages/omi-router/examples/spa/build/) |
| [omi-transform](https://github.com/Tencent/omi/tree/master/packages/omi-transform)|Omi / [css3transform](https://tencent.github.io/omi/packages/omi-transform/css3transform/) integration. Made css3 transform super easy in your Omi project.|
| [omi-tap](https://github.com/Tencent/omi/releases/tag/v4.0.24)| Native tap event support(omi v4.0.24+)|
| [omi-finger](https://github.com/Tencent/omi/tree/master/packages/omi-finger)|Support touch and gesture events in your Omi project.|
| [omi-touch](https://github.com/Tencent/omi/tree/master/packages/omi-touch)|Smooth scrolling, rotation, pull to refresh and any motion for the web.|
| [omi-use](https://github.com/Tencent/omi/blob/master/docs/main-concepts.md#use)|React hooks like API|
| [omi-native](https://github.com/Tencent/omi/tree/master/packages/omi-native)|Render web components to native|
|[omi-i18n](https://github.com/i18next/omi-i18n)| Internationalization solution for omi.js using i18next ecosystem |
| [omi-page](https://github.com/Tencent/omi/tree/master/packages/omi-page) |Tiny client-side router by [page](https://github.com/visionmedia/page.js)|
## Why Omi?
- Tiny size
- Supports TypeScript
- Reactive data-binding
- Having official UI components - [omiu](https://tencent.github.io/omi/packages/omiu/examples/build/index.html)
- Excellent compatibility(IE8+) with [omio](https://github.com/Tencent/omi/tree/master/packages/omio)
- Real [MVVM](https://github.com/Tencent/omi/blob/master/tutorial/omi-mvvm.md) with [mappingjs](https://github.com/Tencent/omi/tree/master/packages/mappingjs) strong support
- Enhanced CSS, [rpx unit support](https://github.com/Tencent/omi/releases/tag/v4.0.26) base on **750** screen width
- Compliance with browser trend and API design
- Merge [**Web Components**](https://developers.google.com/web/fundamentals/web-components/) and [**JSX**](https://reactjs.org/docs/introducing-jsx.html) into one framework
- Web Components can also be a data-driven view, **`UI = fn(data)`**.
- JSX is the best development experience (code intelligent completion and tip) UI Expression with least [grammatical noise](https://github.com/facebook/jsx#why-not-template-literals) and it's turing complete(template engine is not, es template string is but grammatical noise is too loud)
- Look at [Facebook React vs Web Components](https://softwareengineering.stackexchange.com/questions/225400/pros-and-cons-of-facebooks-react-vs-web-components-polymer),Omi **combines their advantages** and gives developers the **freedom to choose the way they like**
- **Shadow DOM merges with Virtual DOM**, Omi uses both virtual DOM and real Shadow DOM to make view updates more accurate and faster
- **Scoped CSS**'s best solution is [**Shadow DOM**](https://developers.google.com/web/fundamentals/web-components/shadowdom), the community churning out frameworks and libraries for Scoped CSS (using JS or JSON writing styles such as Radium, jsxstyle, react-style; binding to webpack using generated unique `className``filename-classname-hash`, such as CSS Modules, Vue), are hack technologies; _and Shadow DOM Style is the perfect solution_.
<!-- - The original**Path Updating** system. Proxy-based automatic**accurate** update,**low power consumption**, high degree of freedom, excellent performance, easy integration of `requestIdleCallback`, say goodbye to `this.update` method when using**store system**! It will automatically update UI partially when data is changed -->
Compare TodoApp by Omi and React, Omi and React rendering DOM structure:
|[Styling We Components Using A Shared Style Sheet](https://www.smashingmagazine.com/2016/12/styling-web-components-using-a-shared-style-sheet/)|
|[Developer Tools support for Web Components in Firefox 63](https://blog.nightly.mozilla.org/2018/09/06/developer-tools-support-for-web-components-in-firefox-63/)||
|[Develop W3C Web Components with WebAssembly](https://medium.com/coinmonks/develop-w3c-web-components-with-webassembly-d65938284255)||
| [60FPS Animation In Omi](https://github.com/Tencent/omi/blob/master/tutorial/omi-transform.md)| [简体中文](https://github.com/Tencent/omi/blob/master/tutorial/omi-transform.cn.md) [한국어](https://github.com/Tencent/omi/blob/master/tutorial/omi-transform.kr.md)|
| [Render Web Components To Native](https://github.com/Tencent/omi/blob/master/tutorial/render-web-components-to-native.md)|[简体中文](https://github.com/Tencent/omi/blob/master/tutorial/render-web-components-to-native.cn.md) [한국어](https://github.com/Tencent/omi/blob/master/tutorial/render-web-components-to-native.kr.md)|
| [Shadow Dom In Depth](https://github.com/praveenpuglia/shadow-dom-in-depth)| [简体中文](https://github.com/Tencent/omi/blob/master/tutorial/shadow-dom-in-depth.cn.md)|
| [The Power Of Web Components](https://hacks.mozilla.org/2018/11/the-power-of-web-components/)|[简体中文](https://github.com/Tencent/omi/blob/master/tutorial/the-power-of-web-components.cn.md)|
CLI's auto-created project scaffolding is based on a single-page create-react-app to be converted into a multi-page one, with configuration issues to see [create-react-app user guide](https://facebook.github.io/create-react-app/docs/getting-started)
### Hello Element
Define a custom element by extending **`WeElement`** base class:
```js
import { define, WeElement } from 'omi'
define('hello-element', class extends WeElement {
onClick = evt => {
// trigger CustomEvent
this.fire('abc', { name: 'dntzhang', age: 12 })
evt.stopPropagation()
}
css = `
div {
color: red;
cursor: pointer;
}`
}
render(props) {
return (
<divonClick={this.onClick}>
Hello {props.msg} {props.propFromParent}
<div>Click Me!</div>
</div>
)
}
})
```
Using `hello-element`:
```js
import { define, render, WeElement } from 'omi'
import './hello-element'
define('my-app', class extends WeElement {
data = { abc: 'abc', passToChild: 123 }
// define CustomEvent Handler
onAbc = evt => {
// get evt data by evt.detail
this.data.abc = ' by ' + evt.detail.name
this.data.passToChild = 1234
this.update()
}
css = `
div{
color: green;
}`
}
render(props, data) {
return (
<div>
Hello {props.name} {data.abc}
<hello-element
onAbc={this.onAbc}
propFromParent={data.passToChild}
msg="WeElement"
/>
</div>
)
}
})
render(<my-appname="Omi v4.0"/>, 'body')
```
Tell Babel to transform JSX into `Omi.h()` call:
```json
{
"presets": ["env", "omi"]
}
```
The following two NPM packages need to be installed to support the above configuration:
```bash
"babel-preset-env": "^1.6.0",
"babel-preset-omi": "^0.1.1",
```
If you use babel7, you can also use the following packages and configuration:
```bash
npm install --save-dev @babel/preset-env
npm install --save-dev @babel/preset-react
```
```js
{
"presets": [
"@babel/preset-env",
[
"@babel/preset-react",
{
"pragma": "Omi.h"
}
]
]
}
```
If you don't want to write CSS in JS, you can use [to-string-loader](https://www.npmjs.com/package/to-string-loader) of webpack,
For example, the following configuration:
```js
{
test: /[\\|\/]_[\S]*\.css$/,
use: [
'to-string-loader',
'css-loader'
]
}
```
If your CSS file starts with "`_`", CSS will use `to-string-loader`., such as:
``` js
import { tag, WeElement render } from 'omi'
define('my-app', class extends WeElement {
css = require('./_index.css')
...
...
...
```
You can also forget the tedious configuration and use omi-cli directly, no need to configure anything.
Omi Store provides a way to pass data through the component tree without having to pass props down manually at every level, injected from the root component and shared across all subcomponents. It's very simple to use:
```js
import { define, render, WeElement } from 'omi'
define('my-hello', class extends WeElement {
render() {
//use this.store in any method of any children components
return <div>{this.store.name}</div>
}
})
define('my-app', class extends WeElement {
handleClick = () => {
//use this.store in any method of any children components
Unlike global variables, when there are multiple root nodes, multiple stores can be injected, while there is only one global variable.
<!-- It will automatically update the UI partially when store.data is changed. The powerful**Store architecture** is high-performanced since all the data is mounted on the store.
```js
export default {
data: {
items: [],
text: "",
firstName: "dnt",
lastName: "zhang",
fullName: function() {
return this.firstName + this.lastName;
},
globalPropTest: "abc", // Change it will refresh all elements without changing the components and page declaring data dependency.
ccc: { ddd: 1 } // Change it will refresh all elements without changing the components and page declaring data dependency.
},
globalData: ["globalPropTest", "ccc.ddd"],
add: function() {
if (!this.data.text.trim().length) {
return;
}
this.data.items.push({
text: this.data.text,
id: Date.now()
});
this.data.text = "";
}
// Default value is false, set to true will update all instances when data changing.
// updateAll: true
};
```
Custom Element requires declaring dependent data so that Omi stores compute the dependency path based on the data declared on the custom component and update it locally as needed. Such as:
```js
define('todo-app', class extends WeElement {
// If you use store, the data is only used to declare dependencies.
static get data() {
return { items: [], text: "" };
}
// ...
handleChange = e => {
this.store.data.text = e.target.value;
};
handleSubmit = e => {
e.preventDefault();
this.store.add();
};
})
```
- The logic of data is **encapsulated in the store definition method** (such as `store.add`).
- Views are only **responsible for passing data to store**, such as calling `store.add` or setting `store.data.text` on top.
You need to inject `store` from the root node at render time to use this store:
```js
render(<todo-app/>, "body", store);
```
[→ Store Source Code](https://github.com/Tencent/omi/blob/master/packages/omi/examples/store/main.js) -->
## Mitt
If you don't want to use store's data system, you can also use publish subscribe mode. For example, using [mitt](https://github.com/developit/mitt) across component communication in Omi:
| `install` | before the component gets mounted to the DOM |
| `installed` | after the component gets mounted to the DOM |
| `uninstall` | prior to removal from the DOM |
| `beforeUpdate` | before update |
| `updated` | after update |
| `beforeRender` | before `render()` |
| `receiveProps` | parent element re-render will trigger it |
## Debugging
Easy to debug via [Omi DevTools Extension](https://github.com/f/omi-devtools) [[Install from Chrome WebStore](https://chrome.google.com/webstore/detail/omijs-devtools/pjgglfliglbhpcpalbpeloghnbceocmd)], using Omi DevTools you can simply debug and manage your UI **without any configuration**. Just install and debug.
Since Omi uses Web Components and Shadow-DOM, it doesn't need to have another elements panel such as React has. It just adds a panel to the **Elements' sidebar** and it's powerful as much as React DevTools.