Need help with omi?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

Tencent
11.5K Stars 1.1K Forks Other 6.6K Commits 91 Opened issues

Description

Front End Cross-Frameworks Framework - 前端跨框架跨平台框架

Services available

!
?

Need anything else?

Contributors list

English | 简体中文

omi

omi

Omi - Front End Cross-Frameworks Framework

Merge Web Components, JSX, Virtual DOM, Functional style, observe or Proxy into one framework with tiny size and high performance. Write components once, using in everywhere, such as Omi, React, Preact, Vue or Angular.

Omiu

Cross-Frameworks and Cross-Themes UI Components powered by Omi

| Name | Status | Example | Docs | | -------------- | ----------|----------- | ----------------| | @omiu/button | omiu-button-status|CodePen | Button Docs| | @omiu/icon | omiu-icon-status|Icon Online | Icon Docs| | @omiu/tabs | omiu-tabs-status|CodePen | Tabs Docs| | @omiu/radio | omiu-radio-status|CodePen | Radio Docs| | @omiu/link | omiu-link-status|CodePen | Link Docs| | @omiu/checkbox | omiu-checkbox-status|CodePen | Checkbox Docs| | @omiu/hamburger-menu | omiu-hamburger-menu-status|CodePen | HamburgerMenu Docs| | @omiu/input | omiu-input-status|CodePen | Input Docs| | @omiu/tree | omiu-tree-status|CodePen | Tree Docs| | @omiu/pagination | omiu-pagination-status|CodePen | Pagination Docs| | @omiu/loading | omiu-loading-status|CodePen | Loading Docs| | @omiu/toast | omiu-toast-status|CodePen | Toast Docs| | @omiu/action-sheet | omiu-action-sheet-status|CodePen | ActionSheet Docs| | @omiu/switch | omiu-switch-status|CodePen | Switch Docs| | @omiu/color-picker | omiu-color-picker-status|CodePen | ColorPicker Docs| | @omiu/chart | omiu-chart-status|CodePen | Chart Docs| | @omiu/toggle-icon | omiu-toggle-icon-status|CodePen | ToggleIcon Docs| | @omiu/o-icon | omiu-o-icon-status|CodePen | OIcon Docs| | @omiu/badge | omiu-badge-status|CodePen | Badge Docs| | @omiu/avatar | omiu-avatar-status|CodePen | Avatar Docs| | @omiu/breadcrumb | omiu-breadcrumb-status|CodePen | Breadcrumb Docs| | @omiu/bottom-nav | omiu-bottom-nav-status|CodePen | BottomNav Docs| | @omiu/transition | omiu-transition-status|CodePen | Transition Docs| | @omiu/dialog | omiu-dialog-status|CodePen | Dialog Docs| | @omiu/dialog-extention | omiu-dialog-extention-status|CodePen | DialogExtention Docs| | Coming... | | | | | Coming... | | | |

Quick Preview

Pass data through the component tree without having to pass props down manually at every level by store, auto update the view on demand.

import { define, render } from 'omi'

class Store { data = { count: 1 } sub = () => { this.data.count-- } add = () => { this.data.count++ } }

define('my-counter', _ => (

- {_.store.data.count} +
), { use: ['count'], //or using useSelf, useSelf will update self only, exclude children components //useSelf: ['count'], css: span { color: red; }, installed() { console.log('installed') } })

render(, 'body', new Store)

  •  can be used in any framework or no framework, such as 
    document.createElement('my-counter')

You can also use

useSelf
,
useSelf
only updates itself. When using
useSelf
, the corresponding attributes are accessed through
usingSelf
in JSX.

You can also implement

computed
props through
compute
, such as:
define('my-counter', _ => (
  
- {_.store.data.count} +
Double: {_.computed.doubleCount}
), { use: ['count'], compute: { doubleCount() { return this.count * 2 } } })

Path is also supported:

class Store {
  data = {
    list: [
      { name: { first: 'dnt', last: 'zhang' } }
    ]
  }
}

... ...

define('my-counter', _ => ( ... ... ), { use: [ 'list[0].name', //Direct string path dep, accessible through this.using[0] ], compute: { fullName() { return this.list[0].name.first + this.list[0].name.last } } })

Multi-store injection

import { define, render } from 'omi'

define('my-app', _ => { const store = _.store.storeA const { data, add, sub } = store return (

Clicked: {data.count} times + -

  </p><div>
    {_.store.storeB.data.msg}
    <button onclick="{_.store.storeB.changeMsg}">
      change storeB's msg
    </button>
  </div>

) }, { useSelf: { storeA: ['count', 'adding'], storeB: ['msg'] } })

const storeA = new class Store { data = { count: 0, adding: false } sub = () => { this.data.count-- } add = () => { this.data.count++ } }

const storeB = new class Store { data = { msg: 'abc' } changeMsg = () => { this.data.msg = 'bcd' } }

render( , 'body', { storeA, storeB })

How to Multi-store injection with

compute
and
computed
? Very simple:
define('my-app', _ => {
  const store = _.store.storeA
  const { data, add, sub } = store
  return (
    

Clicked: {data.count} times + -

  </p><div>
    {_.store.storeB.data.msg}
    <button onclick="{_.store.storeB.changeMsg}">
      change storeB's msg
    </button>
  </div>

  <div>{_.computed.dobuleCount}</div>
  <div>{_.computed.reverseMsg}</div>

) }, { useSelf: { storeA: ['count', 'adding'], storeB: ['msg'] }, compute: { dobuleCount() { return this.storeA.data.count * 2 }, reverseMsg() { return this.storeB.data.msg.split('').reverse().join('') } } })

API and Hooks

define('my-component', _ => (
  ...
  ...
), {
    use: ['count', 'path.a', 'path[1].b'],
    useSelf: ['path.c', 'path[1].d'],
    compute: {
      doubleCount() {
        return this.count * 2
      }
    },
    css: 'h1 { color: red; }',
    propTypes: { },
    defaultProps: { },
    isLightDom: true, //default is false

//life cycle
install() { }, 
installed() { }, 
uninstall() { }, 
receiveProps() { },
beforeUpdate() { }, 
updated() { }, 
beforeRender() { }, 
rendered() { }, 

//custom methods
myMethodA() { },
myMethodB() { }

})

Inject use or useSelf through prop


Ecosystem of Omi

:100:Base

| Project | Description | | ------------------------------- | ----------------------------------- | | omi-docs and codepen and webcomponents.dev| Omi official documents | | omix| 小程序全局状态管理框架,数据触手可及,状态无处遁形 | | omim| Cross frameworks and themes components.(DOCS & REPL && JOIN US!)| | omi-kbone | 使用 omi + kbone 多端开发(小程序和Web)的贪吃蛇游戏。 | | omio| Omi for old browsers with same api(IE8+)| | omiv | 1kb store system for Vue apps. SSR Now | | omis | Omis + React| | omi-ssr| Server-side rendering(support omio only)| | omi-router |Omi official router in 1KB js| | omi-cli| Project scaffolding. → Base Templates and → Other Templates | | omi-devtools| Browser DevTools extension | | omiu| Simple Omi UI | | omil|Webpack loader for Omi.js components.(DOCS)| | omi-snippets |A beautify VSCode extension for .omi or .eno file, Install now!| | obaa or JSONPatcherProxy | Observe or Proxy any object's any change |

:snake:Snake MVP

| Project | Description | | ------------------------------- | ----------------------------------- | | omi-snake & → Touch the demo| The Snake-Eating Game Based on MVP Architecture Written by Omi | | omi-kbone-snake | omi-kbone 写的 MVP 架构的跨端贪吃蛇游戏,支持小程序和 H5 | | Preact-snake & → Touch the demo| The Snake-Eating Game Based on MVP Architecture Written by Preact + Preact-CSS + Omis | | [P]react-snake & → Touch the demo| The Snake-Eating Game Based on MVP Architecture Written by React/Preact | | vue-snake | The Snake-Eating Game Based on MVP Architecture Written by Vue + Omiv | | omix-snake | The Snake-Eating Game Based on MVP Architecture Written by Omix |

:+1:Mini Program(小程序)

| Project | Description | | ------------------------------- | ----------------------------------- | | omix| 小程序全局状态管理框架,数据触手可及,状态无处遁形 | | react-kbone | 直接使用 React 开发小程序或 Web,基于 kbone | | preact-kbone | 直接使用 Preact 开发小程序或 Web,基于 kbone | | omi-cloud| 小程序•云开发| | omip| 直接使用 Omi 开发小程序或 H5 SPA| | mps| 原生小程序增强框架(JSX + Less 输出 WXML + WXSS),也支持 QQ 轻应用 | | cax| 小程序 Canvas 和 SVG 渲染引擎 | | omi-mp| 通过微信小程序开发和生成 Web 单页应用(H5 SPA)| | westore| 小程序状态管理 | | comi| 小程序代码高亮和 markdown 渲染组件 | | wx-touch-event| 基于 AlloyFinger 改造的小程序手势解决方案 |

:books:Other

| Project | Description | | ------------------------------- | ----------------------------------- | | omi-piano |Build piano with Omi and Omi Snippets, Enjoy now!| | omi-chart| Simple HTML5 Charts using chart-x tag.| | md2site| Static Site Generator with markdown powered by Omio.| | omi-30-seconds| Useful Omi snippets that you can understand in 30 seconds.| | omi-canvas| Perfect fusion of web components, jsx and canvas.| | omi-swiper| Omi + Swiper | | omi-vscode| VSCode extension for omi, Install now! | | omi-ex| Omi.js extension(TypeScript) | | omi-transform|Omi / css3transform integration. Made css3 transform super easy in your Omi project.| | omi-finger|Support touch and gesture events in your Omi project.| | omi-touch|Smooth scrolling, rotation, pull to refresh and any motion for the web.| | omi-native|Render web components to native| | omi-i18n| Internationalization solution for omi.js using i18next ecosystem | | omi-page |Tiny client-side router by page| | omie |Build cross platform desktop apps with Omi.js and Electron.js| | omi-cv |Create a front-end engineer curriculum vitae, Get Started!| | Soo| Has same API as omi but is great alternative if you want to create custom elements without JSX, virtual DOM and store | |CEE| Fork from custom-elements-everywhere |

Why Omi?

  • Tiny size and High performance
  • Cross frameworks(react, preact, vue, angular), components of omi are pure custom elements
  • One framework. Mobile & desktop & mini program
  • Stateless View Architecture Design
  • Be friendly to custom elements, you can pass
    false
    attributes to elements through string
    '0'
    or string
    'false'
    , you can pass
    object
    attributes to elements through
    :
    prefix and
    Omi.$
  • Easy two way binding by extend api
  • Supports TypeScript
  • Reactive data-binding
  • Native tap event support
  • Having Cross-frameworks UI components - omim
  • Excellent compatibility(IE8+) with omio
  • Enhanced CSS, rpx unit support base on 750 screen width
  • Compliance with browser trend and API design
  • Merge Web Components, JSX 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 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,Omi combines their advantages and gives developers the freedom to choose the way they like
  • Shadow DOM or Light 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, 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 store system. Proxy-based automatic accurate update, low power consumption, high degree of freedom, excellent performance, easy integration of
    requestIdleCallback
    ,It will automatically update UI partially when data is changed

Compare TodoApp by Omi and React, Omi and React rendering DOM structure:

| Omi | React | Omio | | ------------------------------- | ----------------------------------- |----------------------------------- | | Omi | React | Omio |

Omi uses Shadow DOM or Light DOM based style isolation and semantic structure.

Useful Resources

| Title Name | Other language | Related| | ----------------------------------------- | ------------------ |-----------------| |Web Components bookmarks||| |Snake-Eating Game Making with Web Components of Omi and MVP Architecture||| |Constructable Stylesheets: seamless reusable styles||| |Web Components specifications||| |Web Components in a Nutshell||| |Using Web Components with React in 2019||| |Using Web Components in React||| |Styling We Components Using A Shared Style Sheet| |Developer Tools support for Web Components in Firefox 63|| |Develop W3C Web Components with WebAssembly|| | 60FPS Animation In Omi| 简体中文 한국어| | Render Web Components To Native|简体中文 한국어| | Shadow Dom In Depth| 简体中文| | Part Theme Explainer|求翻译| | Web Components MDN| 简体中文| | Web Components Google| | Web Components Org| | Web Components: the Right Way| | Proxy MDN|简体中文 한국어| | CSS Variables|简体中文 한국어| | CSS Shadow Parts| | Platform HTML5| | Using requestIdleCallback|简体中文| A polyfill| | The Power Of Web Components|简体中文| |ShadowRoot|简体中文||

Overview of the Readme

Add Omi in One Minute

This page demonstrates using Omi with no build tooling, directly run in the browser.

  Omi demo without transpiler



  
  



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:

You can also use

my-counter
tag directly in HTML:
  

Getting Started

Install

$ npm i omi-cli -g    # install cli
$ omi init my-app     # init project
$ cd my-app           
$ npm start           # develop
$ npm run build       # release

npx omi-cli init my-app
is also supported(npm v5.2.0+).

Directory description:

├─ config
├─ public
├─ scripts
├─ src
│  ├─ assets
│  ├─ elements    //Store all custom elements
│  ├─ store       //Store all this store of pages
│  ├─ admin.js    //Entry js of compiler,will build to admin.html
│  └─ index.js    //Entry js of compiler,will build to index.html

Scripts

"scripts": {
    "start": "node scripts/start.js",
    "build": "PUBLIC_URL=. node scripts/build.js",
    "build-windows": "set PUBLIC_URL=.&& node scripts/build.js",
    "fix": "eslint src --fix"
}

You can set up the PUBLIC_URL, such as:

...
"build": "PUBLIC_URL=https://fe.wxpay.oa.com/dv node scripts/build.js",
"build-windows": "set PUBLIC_URL=https://fe.wxpay.oa.com/dv && node scripts/build.js",
...

Switch omi, omio and reomi

Add or remove the alias config in package.json to switch omi and omio:

"alias": {
  "omi": "omio"
}

Project Template

| Template Type| Command| Describe| | ------------ | -----------| ----------------- | |Base Template(v3.3.0+)|

omi init my-app
| Basic omi or omio(IE8+) project template.| |Base Template with snapshoot|
omi init-snap my-app
| Basic omi or omio(IE8+) project template with snapshoot prerendering.| |TypeScript Template(omi-cli v3.3.0+)|
omi init-ts my-app
|Basic template with typescript.| |Mobile Template|
omi init-weui my-app
| Mobile web app template with weui and omi-router.| |Kbone Template|
omi init-kbone my-app
|Developing mini program or web using omi.|

Hello Element

Define a custom element by extending

WeElement
base class:

import { define, WeElement } from 'omi'

define('hello-element', class extends WeElement { onClick = evt => { // trigger CustomEvent this.fire('abc', { name: 'dntzhang', age: 12 }) evt.stopPropagation() }

//If you need to use directly in html, you must declare propTypes static propTypes = { msg: String }

static css = div { color: red; cursor: pointer; }

render(props) { return (

Hello {props.msg}
Click Me!
) } })

Using

hello-element
:
import { define, render, WeElement } from 'omi'
import './hello-element'

define('my-app', class extends WeElement { data = { abc: 'abc' }

// define CustomEvent Handler onAbc = evt => { // get evt data by evt.detail this.data.abc = ' by ' + evt.detail.name this.update() }

static css = div{ color: green; } }

render(props, data) { return (

Hello {data.abc}
) } })

render(, 'body')

Tell Babel to transform JSX into

Omi.h()
call:
{
  "presets": ["env", "omi"]
}

The following two NPM packages need to be installed to support the above configuration:

"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:

npm install --save-dev @babel/preset-env
npm install --save-dev @babel/preset-react
{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "pragma": "Omi.h",
        "pragmaFrag": "Omi.h.f"
      }
    ]
  ]
}

If you don't want to write CSS in JS, you can use to-string-loader of webpack. For example, the following configuration:

{
  test: /[\\|\/]_[\S]*\.css$/,
  use: [
    'to-string-loader',
    'css-loader'
  ]
}

If your CSS file starts with "

_
", CSS will use
to-string-loader
, such as:
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. <!--

TodoApp

Here is a relatively complete example of TodoApp:

import { define, render, WeElement } from 'omi'

define('todo-list', class extends WeElement { static propTypes = { items: Array }

render(props) { return (

    {props.items.map(item => (
  • {item.text}
  • ))}
) } })

define('todo-app', class extends WeElement { items = [] text = ''

render() { return (

TODO

Add #{this.items.length + 1}
) }

handleChange = e => { this.text = e.target.value }

handleSubmit = e => { e.preventDefault() if (!this.text.trim().length) { return } this.items.push({ text: this.text, id: Date.now() }) this.text = '' this.update() } })

render(, 'body')

``` -->

TypeScript Auto Complete

```jsx import { h, WeElement, tag, classNames } from 'omi'; import * as styles from './_index.less';

interface ButtonProps { href?: string, disabled?: boolean, type?: 'default' | 'primary' | 'danger', htmltype?: 'submit' | 'button' | 'reset', onClick?: (e: any) => void }

const TAG = 'o-button'

declare global { namespace JSX { interface IntrinsicElements { [TAG]: Omi.Props & ButtonProps } } }

@tag(TAG) export default class oButton extends WeElement { ... ... ...

omi

Lifecycle

| Lifecycle method | When it gets called | | ---------------- | -------------------------------------------- | |

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,
return false
will prevent update action|

Debugging

Easy to debug via Omi DevTools Extension [Install from Chrome WebStore], 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.

Omi DevTools

View registered elements

console.log(Omi.elements)

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.