gea-framework

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Gea Framework

Gea框架

Gea is a lightweight, reactive JavaScript UI framework built on the principle that JS code should be simple and understandable. It compiles JSX into efficient DOM operations at build time via a Vite plugin, uses proxy-based stores for state management, and employs event delegation for all user interactions. There is no virtual DOM — the Vite plugin analyzes your JSX templates and generates surgical DOM patches that update only the elements that depend on changed state.
Gea introduces no new programming concepts. There are no signals, no hooks, no dependency arrays, and no framework-specific primitives. Stores are classes with state and methods. Components are classes with a
template()
method or plain functions. Computed values are getters. The compile-time Vite plugin is the only "magic" — it analyzes ordinary JavaScript and wires up reactivity invisibly, so you write regular OOP/functional code that is fully reactive under the hood.
Read
reference.md
in this skill directory for the full API surface and detailed examples.
Gea是一款轻量级响应式JavaScript UI框架,设计原则是JS代码应当简单易懂。它通过Vite插件在构建阶段将JSX编译为高效的DOM操作,使用基于Proxy的store做状态管理,所有用户交互都采用事件委托机制。框架没有虚拟DOM——Vite插件会分析你的JSX模板,生成精准的DOM补丁,仅更新依赖了变化状态的元素。
Gea没有引入新的编程概念,没有signal、没有hook、没有依赖数组,也没有框架专属的原语。Store是包含状态和方法的类,组件是带有
template()
方法的类或普通函数,计算值是getter。只有编译阶段的Vite插件是唯一的「魔法」——它会分析普通JavaScript代码,隐式地完成响应式绑定,因此你只需要编写常规的OOP/函数式代码,底层就会自动具备完整的响应式能力。
查看本skill目录下的
reference.md
可获取完整API说明和详细示例。

Core Concepts

核心概念

Stores

Stores

A Store holds shared application state. Extend the
Store
class, declare reactive properties as class fields, and add methods that mutate them. The store instance is wrapped in a deep
Proxy
that tracks every property change and batches notifications via
queueMicrotask
.
ts
import { Store } from '@geajs/core'

class CounterStore extends Store {
  count = 0

  increment() {
    this.count++
  }
  decrement() {
    this.count--
  }
}

export default new CounterStore()
Key rules:
  • Always export a singleton instance (
    export default new MyStore()
    ), not the class.
  • Mutate properties directly —
    this.count++
    triggers reactivity automatically.
  • Use getters for derived/computed values — they re-evaluate on each access.
  • Array mutations (
    push
    ,
    pop
    ,
    splice
    ,
    sort
    ,
    reverse
    ,
    shift
    ,
    unshift
    ) are intercepted and produce fine-grained change events.
  • Replacing an array with a superset (same prefix + new items) is detected as an efficient
    append
    operation.
Store 用于存储应用共享状态。你可以继承
Store
类,将响应式属性声明为类字段,再添加修改属性的方法即可。Store实例会被深度
Proxy
包裹,追踪每一个属性的变化,并通过
queueMicrotask
批量发送变更通知。
ts
import { Store } from '@geajs/core'

class CounterStore extends Store {
  count = 0

  increment() {
    this.count++
  }
  decrement() {
    this.count--
  }
}

export default new CounterStore()
核心规则:
  • 始终导出单例实例
    export default new MyStore()
    ),而非类本身。
  • 直接修改属性即可——
    this.count++
    会自动触发响应式更新。
  • 派生/计算值使用getter——每次访问时都会重新计算。
  • 数组方法(
    push
    pop
    splice
    sort
    reverse
    shift
    unshift
    )会被拦截,并生成细粒度的变更事件。
  • 如果将数组替换为包含原数组前缀+新元素的超集,会被识别为高效的
    append
    操作。

Components

组件

Gea has two component styles. Both compile to the same internal representation.
Gea支持两种组件写法,二者编译后内部表现完全一致。

Class Components

类组件

Extend
Component
and implement a
template(props)
method that returns JSX. Class components can hold their own reactive properties — use them when you need local, transient UI state.
jsx
import { Component } from '@geajs/core'

export default class Counter extends Component {
  count = 0

  increment() { this.count++ }
  decrement() { this.count-- }

  template() {
    return (
      <div class="counter">
        <span>{this.count}</span>
        <button click={this.increment}>+</button>
        <button click={this.decrement}>-</button>
      </div>
    )
  }
}
Event handlers accept both method references (
click={this.increment}
) and arrow functions (
click={() => this.increment()}
). Use method references for simple forwarding; use arrow functions when passing arguments or composing logic.
Use class components when you need local component state or lifecycle hooks.
继承
Component
并实现
template(props)
方法返回JSX即可。类组件可以持有自身的响应式属性,当你需要本地临时UI状态时可以使用这类组件。
jsx
import { Component } from '@geajs/core'

export default class Counter extends Component {
  count = 0

  increment() { this.count++ }
  decrement() { this.count-- }

  template() {
    return (
      <div class="counter">
        <span>{this.count}</span>
        <button click={this.increment}>+</button>
        <button click={this.decrement}>-</button>
      </div>
    )
  }
}
事件处理函数支持传入方法引用(
click={this.increment}
)和箭头函数(
click={() => this.increment()}
)。简单转发场景使用方法引用即可;需要传参或组合逻辑时使用箭头函数。
当你需要组件本地状态或生命周期钩子时,使用类组件。

Function Components

函数组件

Export a default function that receives props and returns JSX. The Vite plugin converts it to a class component internally.
jsx
export default function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>
}
Use function components for stateless, presentational UI.
导出一个接收props并返回JSX的默认函数即可。Vite插件会在内部将其转换为类组件。
jsx
export default function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>
}
当你需要无状态展示型UI时,使用函数组件。

Props and Data Flow

Props与数据流

Props follow JavaScript's native value semantics:
  • Objects and arrays passed as props are the parent's reactive proxy. The child can mutate them directly, and both parent and child DOM update — two-way binding with zero ceremony.
  • Primitives are copies. Reassigning a primitive prop in the child updates only the child's DOM — the parent is unaffected.
No
emit
, no
v-model
, no callback props needed for object/array mutations. Deep nesting works the same way — as long as the same reference is passed down, reactivity propagates across the entire tree.
Props遵循JavaScript原生的值语义:
  • 作为props传递的对象和数组是父组件的响应式Proxy,子组件可以直接修改它们,父子组件的DOM都会更新——无需额外配置即可实现双向绑定。
  • 原始类型值是拷贝,在子组件中重新赋值原始类型prop只会更新子组件的DOM,不会影响父组件。
修改对象/数组无需
emit
v-model
或回调props,深层嵌套场景规则一致——只要传递的是同一个引用,响应式更新会在整个组件树中传播。

Component State vs. Stores

组件状态 vs Stores

ConcernWhere it livesWhen to use
Shared app data (todos, user, cart)StoreData accessed by multiple components or persisted across navigation
Derived / computed valuesStore gettersValues calculated from store state
Local, transient UI state (editing mode, hover)Component propertiesEphemeral state that no other component needs
A class component can have both local state and read from external stores:
jsx
export default class TodoItem extends Component {
  editing = false
  editText = ''

  template({ todo, onToggle, onRemove }) {
    const { editing, editText } = this
    return (
      <li class={`todo-item ${editing ? 'editing' : ''}`}>
        <span dblclick={this.startEditing}>{todo.text}</span>
        {/* ... */}
      </li>
    )
  }
}
场景所属位置适用场景
应用共享数据(待办事项、用户信息、购物车)Store多个组件都需要访问、或导航跳转后需要保留的数据
派生/计算值Store getter基于Store状态计算得到的值
本地临时UI状态(编辑模式、 hover状态)组件属性其他组件不需要使用的临时状态
类组件可以同时拥有本地状态,也可以读取外部Store的数据:
jsx
export default class TodoItem extends Component {
  editing = false
  editText = ''

  template({ todo, onToggle, onRemove }) {
    const { editing, editText } = this
    return (
      <li class={`todo-item ${editing ? 'editing' : ''}`}>
        <span dblclick={this.startEditing}>{todo.text}</span>
        {/* ... */}
      </li>
    )
  }
}

Multiple Stores

多Store管理

Split state into domain-specific stores. Each store is an independent singleton.
flight-store.ts    → step, boardingPass
options-store.ts   → luggage, seat, meal
payment-store.ts   → passengerName, cardNumber, paymentComplete
Stores can import and call each other:
ts
class FlightStore extends Store {
  startOver(): void {
    this.step = 1
    optionsStore.reset()
    paymentStore.reset()
  }
}
A root component reads from all relevant stores and passes data down as props:
jsx
export default class App extends Component {
  template() {
    const { step } = flightStore
    const { luggage } = optionsStore
    return <div>{step === 1 && <OptionStep selectedId={luggage} onSelect={id => optionsStore.setLuggage(id)} />}</div>
  }
}
可以按业务领域拆分状态,每个Store都是独立的单例。
flight-store.ts    → 步骤、登机牌信息
options-store.ts   → 行李、座位、餐食选项
payment-store.ts   → 乘客姓名、卡号、支付完成状态
Store之间可以互相导入和调用:
ts
class FlightStore extends Store {
  startOver(): void {
    this.step = 1
    optionsStore.reset()
    paymentStore.reset()
  }
}
根组件从所有相关Store读取数据,再作为props向下传递:
jsx
export default class App extends Component {
  template() {
    const { step } = flightStore
    const { luggage } = optionsStore
    return <div>{step === 1 && <OptionStep selectedId={luggage} onSelect={id => optionsStore.setLuggage(id)} />}</div>
  }
}

Router

路由

Gea includes a built-in client-side router. The router is a
Store
that reactively tracks
path
,
params
,
query
, and
hash
. Define routes with
setRoutes
or
createRouter
.
Gea内置了客户端路由,路由本身也是一个
Store
,会响应式地跟踪
path
params
query
hash
。可以通过
setRoutes
createRouter
定义路由。

Setup

配置

Create a bare
Router
in
router.ts
. Keep this file free of view imports to avoid circular dependencies (views import
router
, so
router.ts
must not import views).
ts
// src/router.ts
import { Router } from '@geajs/core'
export const router = new Router()
Set routes in
App.tsx
where both the router and view components are available:
tsx
// src/App.tsx
import { Component, Outlet } from '@geajs/core'
import { router } from './router'
import AppShell from './views/AppShell'
import Home from './views/Home'
import About from './views/About'
import NotFound from './views/NotFound'

router.setRoutes({
  '/': {
    layout: AppShell,
    children: {
      '/': Home,
      '/about': About,
      '/users/:id': UserProfile,
    },
  },
  '*': NotFound,
})

export default class App extends Component {
  template() {
    return <Outlet />
  }
}
Layouts receive the resolved child as a
page
prop:
tsx
export default class AppShell extends Component {
  template({ page }: any) {
    return (
      <div class="app">
        <nav>
          <Link to="/" label="Home" />
          <Link to="/about" label="About" />
        </nav>
        <main>{page}</main>
      </div>
    )
  }
}
For simple apps without layouts/guards (no circular dependency risk), you can use
createRouter
directly in
router.ts
and render with
<RouterView router={router} />
:
ts
import { createRouter } from '@geajs/core'
import Home from './views/Home'
import About from './views/About'

export const router = createRouter({
  '/': Home,
  '/about': About,
} as const)
tsx
import { Component, RouterView } from '@geajs/core'
import { router } from './router'

export default class App extends Component {
  template() {
    return <RouterView router={router} />
  }
}
router.ts
中创建一个空的
Router
实例,请保持该文件不引入视图组件,避免循环依赖(视图会导入
router
,因此
router.ts
不能导入视图)。
ts
// src/router.ts
import { Router } from '@geajs/core'
export const router = new Router()
App.tsx
中配置路由,该文件可以同时访问路由和视图组件:
tsx
// src/App.tsx
import { Component, Outlet } from '@geajs/core'
import { router } from './router'
import AppShell from './views/AppShell'
import Home from './views/Home'
import About from './views/About'
import NotFound from './views/NotFound'

router.setRoutes({
  '/': {
    layout: AppShell,
    children: {
      '/': Home,
      '/about': About,
      '/users/:id': UserProfile,
    },
  },
  '*': NotFound,
})

export default class App extends Component {
  template() {
    return <Outlet />
  }
}
布局组件会接收到匹配的子组件作为
page
prop:
tsx
export default class AppShell extends Component {
  template({ page }: any) {
    return (
      <div class="app">
        <nav>
          <Link to="/" label="Home" />
          <Link to="/about" label="About" />
        </nav>
        <main>{page}</main>
      </div>
    )
  }
}
对于不需要布局/路由守卫、没有循环依赖风险的简单应用,你可以直接在
router.ts
中使用
createRouter
,再通过
<RouterView router={router} />
渲染:
ts
import { createRouter } from '@geajs/core'
import Home from './views/Home'
import About from './views/About'

export const router = createRouter({
  '/': Home,
  '/about': About,
} as const)
tsx
import { Component, RouterView } from '@geajs/core'
import { router } from './router'

export default class App extends Component {
  template() {
    return <RouterView router={router} />
  }
}

Guards

路由守卫

Guards are synchronous functions on route groups that control access. A guard returns:
  • true
    — proceed to the route
  • string
    — redirect to that path
  • Component
    — render it instead of the route
ts
import authStore from './stores/auth-store'

const AuthGuard = () => {
  if (authStore.isAuthenticated) return true
  return '/login'
}

router.setRoutes({
  '/login': Login,
  '/': {
    layout: AppShell,
    guard: AuthGuard,
    children: {
      '/dashboard': Dashboard,
      '/settings': Settings,
    },
  },
})
Guards on nested groups stack parent → child. Guards are intentionally synchronous — they check store state, not async APIs. For async checks, use
created()
in the component.
路由守卫是路由组上的同步函数,用于控制访问权限。守卫的返回值规则:
  • true
    — 允许进入路由
  • string
    — 重定向到该路径
  • Component
    — 渲染该组件替代目标路由
ts
import authStore from './stores/auth-store'

const AuthGuard = () => {
  if (authStore.isAuthenticated) return true
  return '/login'
}

router.setRoutes({
  '/login': Login,
  '/': {
    layout: AppShell,
    guard: AuthGuard,
    children: {
      '/dashboard': Dashboard,
      '/settings': Settings,
    },
  },
})
嵌套路由组的守卫会按父→子的顺序依次执行。守卫设计为同步函数,仅用于检查Store状态,不处理异步API请求。如果需要异步校验,请在组件的
created()
生命周期中处理。

Route Patterns

路由匹配规则

  • Static:
    /about
  • Named params:
    /users/:id
    — extracted as
    { id: '42' }
  • Wildcard:
    *
    — matches any unmatched path
  • Redirects:
    '/old': '/new'
    — string values trigger a redirect
  • 静态路由:
    /about
  • 命名参数:
    /users/:id
    — 匹配后会提取为
    { id: '42' }
  • 通配符:
    *
    — 匹配所有未匹配的路径
  • 重定向:
    '/old': '/new'
    — 字符串值会触发重定向

Link

Link组件

Renders an
<a>
tag that navigates with
history.pushState
. Modifier keys (Cmd/Ctrl+click) open in a new tab.
jsx
<Link to="/about" label="About" class="nav-link" />
渲染一个
<a>
标签,内部使用
history.pushState
实现路由跳转。按下修饰键(Cmd/Ctrl+点击)会在新标签页打开。
jsx
<Link to="/about" label="About" class="nav-link" />

Programmatic Navigation

编程式导航

ts
import { router } from './router'

router.push('/about')         // pushState
router.replace('/login')      // replaceState
router.back()
router.forward()
ts
import { router } from './router'

router.push('/about')         // pushState跳转
router.replace('/login')      // replaceState跳转
router.back()
router.forward()

Route Parameters

路由参数

Function components receive matched params as props:
jsx
export default function UserProfile({ id }) {
  return <h1>User {id}</h1>
}
Class components receive them via
created(props)
and
template(props)
. Route params are also available on
router.params
.
函数组件会将匹配到的参数作为props接收:
jsx
export default function UserProfile({ id }) {
  return <h1>User {id}</h1>
}
类组件可以通过
created(props)
template(props)
接收路由参数,也可以直接通过
router.params
获取。

Active State

激活状态判断

ts
router.isActive('/dashboard')  // true if path starts with /dashboard
router.isExact('/dashboard')   // true only for exact match
ts
router.isActive('/dashboard')  // 路径以/dashboard开头时返回true
router.isExact('/dashboard')   // 仅完全匹配/dashboard时返回true

matchRoute Utility

matchRoute工具函数

Use
matchRoute
for manual route matching:
ts
import { matchRoute } from '@geajs/core'

const result = matchRoute('/users/:id', '/users/42')
// { path: '/users/42', pattern: '/users/:id', params: { id: '42' } }
使用
matchRoute
可以手动做路由匹配:
ts
import { matchRoute } from '@geajs/core'

const result = matchRoute('/users/:id', '/users/42')
// { path: '/users/42', pattern: '/users/:id', params: { id: '42' } }

RouterView

RouterView

RouterView
renders the current route. Use it with a
router
prop for
createRouter
setups, or with an inline
routes
array for quick prototypes:
jsx
// With createRouter (recommended)
<RouterView router={router} />

// With inline routes (uses the singleton router)
<RouterView routes={[
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '/users/:id', component: UserProfile },
]} />
RouterView
用于渲染当前匹配的路由。使用
createRouter
配置时传入
router
prop即可,也可以传入内联
routes
数组快速搭建原型:
jsx
// 配合createRouter使用(推荐)
<RouterView router={router} />

// 内联路由配置(使用单例路由)
<RouterView routes={[
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '/users/:id', component: UserProfile },
]} />

JSX Rules

JSX规则

Gea JSX differs from React JSX in several ways:
FeatureGeaReact
CSS classes
class="foo"
className="foo"
Event handlers
click={fn}
or
onClick={fn}
onClick={fn}
,
onInput={fn}
,
onChange={fn}
Checked inputs
checked={bool}
+
change={fn}
checked={bool}
+
onChange={fn}
Conditional render
{cond && <Child />}
Same
Lists with keys
{arr.map(item => <Item key={item.id} />)}
Same
Dynamic classes
class={`btn ${active ? 'on' : ''}`}
Same (with
className
)
Both native-style (
click
,
change
) and React-style (
onClick
,
onChange
) event attribute names are supported. Native-style is preferred by convention.
Supported event attributes:
click
,
dblclick
,
input
,
change
,
keydown
,
keyup
,
blur
,
focus
,
mousedown
,
mouseup
,
submit
,
dragstart
,
dragend
,
dragover
,
dragleave
,
drop
.
With
@geajs/mobile
:
tap
,
longTap
,
swipeRight
,
swipeUp
,
swipeLeft
,
swipeDown
.
Gea的JSX和React JSX有几处差异:
特性GeaReact
CSS类名
class="foo"
className="foo"
事件处理
click={fn}
onClick={fn}
onClick={fn}
onInput={fn}
onChange={fn}
选中输入框
checked={bool}
+
change={fn}
checked={bool}
+
onChange={fn}
条件渲染
{cond && <Child />}
一致
带key的列表
{arr.map(item => <Item key={item.id} />)}
一致
动态类名
class={`btn ${active ? 'on' : ''}`}
一致(使用
className
同时支持原生风格(
click
change
)和React风格(
onClick
onChange
)的事件属性名,约定优先使用原生风格。
支持的事件属性:
click
dblclick
input
change
keydown
keyup
blur
focus
mousedown
mouseup
submit
dragstart
dragend
dragover
dragleave
drop
使用
@geajs/mobile
时还支持:
tap
longTap
swipeRight
swipeUp
swipeLeft
swipeDown

Style Objects

样式对象

Gea supports React-style inline style objects. The compiler converts static style objects to CSS strings at build time and generates runtime conversion for dynamic values:
jsx
// Static — compiled to a CSS string at build time (zero runtime cost)
<div style={{ backgroundColor: 'red', fontSize: '14px', fontWeight: 'bold' }}>
  Styled content
</div>

// Dynamic — converted to cssText at runtime
<div style={{ color: this.textColor, opacity: this.isVisible ? 1 : 0 }}>
  Dynamic styling
</div>

// String styles still work (passed through as-is)
<div style={`width:${this.width}px`}>Sized content</div>
CSS property names use camelCase (like React). The compiler converts them to kebab-case:
backgroundColor
background-color
,
fontSize
font-size
.
Gea支持React风格的内联样式对象。编译器会在构建阶段将静态样式对象转换为CSS字符串,动态样式则会在运行时转换:
jsx
// 静态样式 — 构建阶段编译为CSS字符串(零运行时开销)
<div style={{ backgroundColor: 'red', fontSize: '14px', fontWeight: 'bold' }}>
  带样式的内容
</div>

// 动态样式 — 运行时转换为cssText
<div style={{ color: this.textColor, opacity: this.isVisible ? 1 : 0 }}>
  动态样式内容
</div>

// 字符串样式也支持(直接透传)
<div style={`width:${this.width}px`}>指定宽度的内容</div>
CSS属性名使用驼峰命名(和React一致),编译器会自动转换为短横线命名:
backgroundColor
background-color
fontSize
font-size

ref
Attribute

ref
属性

Use
ref
to get a direct reference to a DOM element after render:
jsx
export default class Canvas extends Component {
  canvasEl = null

  template() {
    return (
      <div class="canvas-wrapper">
        <canvas ref={this.canvasEl} width="800" height="600"></canvas>
      </div>
    )
  }

  onAfterRender() {
    const ctx = this.canvasEl.getContext('2d')
    ctx.fillRect(0, 0, 100, 100)
  }
}
The compiler replaces
ref
with a
data-gea-ref
marker and generates a
__setupRefs()
method that assigns the DOM element to the specified component property after render. Multiple refs on different elements are supported.
使用
ref
可以在渲染后获取DOM元素的直接引用:
jsx
export default class Canvas extends Component {
  canvasEl = null

  template() {
    return (
      <div class="canvas-wrapper">
        <canvas ref={this.canvasEl} width="800" height="600"></canvas>
      </div>
    )
  }

  onAfterRender() {
    const ctx = this.canvasEl.getContext('2d')
    ctx.fillRect(0, 0, 100, 100)
  }
}
编译器会将
ref
替换为
data-gea-ref
标记,并生成
__setupRefs()
方法,在渲染完成后将DOM元素赋值给指定的组件属性。支持给不同元素设置多个ref。

Compiler Errors (Unsupported Patterns)

编译器错误(不支持的写法)

The Gea compiler throws clear errors for JSX patterns it cannot compile. These are caught at build time, not at runtime:
PatternErrorFix
<div {...props} />
Spread attributes not supportedDestructure and pass props individually
<{DynamicTag} />
Dynamic component tags not supportedUse conditional rendering (
{isA ? <A /> : <B />}
)
{() => <div />}
Function-as-child not supportedUse render props with named attributes instead
export function Foo() { return <div /> }
Named JSX component exports not supportedUse
export default function
<>{items.map(...)}</>
Fragments as
.map()
item roots not supported
Wrap each item in a single root element
Gea编译器会对无法编译的JSX模式抛出清晰的错误,这些错误会在构建阶段捕获,不会出现在运行时:
写法错误信息修复方案
<div {...props} />
不支持展开属性解构后逐个传递props
<{DynamicTag} />
不支持动态组件标签使用条件渲染(
{isA ? <A /> : <B />}
{() => <div />}
不支持函数作为子元素使用带命名属性的render props替代
export function Foo() { return <div /> }
不支持命名导出JSX组件使用
export default function
<>{items.map(...)}</>
不支持将Fragment作为
.map()
项的根元素
给每个项包裹单个根元素

Rendering

渲染

js
import MyApp from './my-app.jsx'

const app = new MyApp()
app.render(document.getElementById('app'))
Components are instantiated with
new
, then
.render(parentEl)
inserts them into the DOM.
js
import MyApp from './my-app.jsx'

const app = new MyApp()
app.render(document.getElementById('app'))
使用
new
实例化组件,再调用
.render(parentEl)
即可将组件插入DOM。

Gea Mobile

Gea Mobile

The
@geajs/mobile
package extends Gea with mobile-oriented UI primitives:
  • View — a full-screen
    Component
    that renders to
    document.body
    by default.
  • ViewManager — manages a navigation stack with iOS-style transitions, back gestures, and sidebar support.
  • Sidebar, TabView, NavBar — pre-built layout components.
  • PullToRefresh, InfiniteScroll — scroll-driven UI patterns.
  • GestureHandler — registers
    tap
    ,
    longTap
    ,
    swipeRight
    ,
    swipeLeft
    ,
    swipeUp
    ,
    swipeDown
    events.
js
import { View, ViewManager } from '@geajs/mobile'

class HomeView extends View {
  template() {
    return (
      <view>
        <h1>Home</h1>
      </view>
    )
  }
  onActivation() {
    /* called when view enters viewport */
  }
}

const vm = new ViewManager()
const home = new HomeView()
vm.setCurrentView(home)
@geajs/mobile
包为Gea扩展了面向移动端的UI原语:
  • View — 全屏
    Component
    ,默认渲染到
    document.body
  • ViewManager — 管理导航栈,支持iOS风格转场动画、返回手势和侧边栏。
  • SidebarTabViewNavBar — 预置布局组件。
  • PullToRefreshInfiniteScroll — 滚动驱动的UI模式。
  • GestureHandler — 注册
    tap
    longTap
    swipeRight
    swipeLeft
    swipeUp
    swipeDown
    事件。
js
import { View, ViewManager } from '@geajs/mobile'

class HomeView extends View {
  template() {
    return (
      <view>
        <h1>首页</h1>
      </view>
    )
  }
  onActivation() {
    /* 视图进入视口时调用 */
  }
}

const vm = new ViewManager()
const home = new HomeView()
vm.setCurrentView(home)

Project Setup

项目配置

Scaffolding a New Project

初始化新项目

bash
npm create gea@latest my-app
cd my-app
npm install
npm run dev
The
create-gea
package scaffolds a Vite project with TypeScript, a sample store, class and function components, and the Vite plugin pre-configured.
bash
npm create gea@latest my-app
cd my-app
npm install
npm run dev
create-gea
包会生成一个预置了TypeScript、示例Store、类组件和函数组件、以及预配置Vite插件的Vite项目。

Manual Setup

手动配置

js
// vite.config.js
import { defineConfig } from 'vite'
import { geaPlugin } from '@geajs/vite-plugin'

export default defineConfig({
  plugins: [geaPlugin()]
})
The
@geajs/vite-plugin
Vite plugin handles JSX transformation, reactivity wiring, event delegation generation, and HMR.
js
// vite.config.js
import { defineConfig } from 'vite'
import { geaPlugin } from '@geajs/vite-plugin'

export default defineConfig({
  plugins: [geaPlugin()]
})
@geajs/vite-plugin
Vite插件负责JSX转换、响应式绑定、事件委托生成和HMR。

@geajs/ui Component Library

@geajs/ui组件库

@geajs/ui
is a Tailwind-styled, Zag.js-powered component library for Gea. It provides ~35 ready-to-use components: simple styled primitives (Button, Card, Input) and behavior-rich interactive widgets (Select, Dialog, Tabs, Toast). For full usage instructions, component API, and examples, see the gea-ui-components skill in
skills/gea-ui-components/
.
@geajs/ui
是基于Tailwind样式、Zag.js驱动的Gea组件库,提供约35个开箱即用的组件:包括基础样式原语(Button、Card、Input)和复杂交互组件(Select、Dialog、Tabs、Toast)。完整使用说明、组件API和示例请查看
skills/gea-ui-components/
下的gea-ui-components skill。

npm Packages

npm包

PackagenpmDescription
@geajs/core
npmCore framework — stores, components, reactivity, DOM patching
@geajs/ui
npmTailwind + Zag.js component library — Button, Select, Dialog, Tabs, Toast, etc.
@geajs/mobile
npmMobile UI primitives — views, navigation, gestures, layout
@geajs/vite-plugin
npmVite plugin — JSX transform, reactivity wiring, HMR
create-gea
npmProject scaffolder (
npm create gea@latest
)
gea-tools
VS Code / Cursor extension for Gea JSX code intelligence
包名npm地址描述
@geajs/core
npm核心框架 — Store、组件、响应式、DOM补丁
@geajs/ui
npmTailwind + Zag.js组件库 — Button、Select、Dialog、Tabs、Toast等
@geajs/mobile
npm移动端UI原语 — 视图、导航、手势、布局
@geajs/vite-plugin
npmVite插件 — JSX转换、响应式绑定、HMR
create-gea
npm项目脚手架(
npm create gea@latest
gea-tools
用于Gea JSX代码智能提示的VS Code / Cursor扩展

VS Code / Cursor Extension

VS Code / Cursor扩展

The
gea-tools
extension (in
packages/gea-tools
) provides:
  • Component completion inside JSX tags
  • Prop completion based on component signatures
  • Event attribute completion (
    click
    ,
    input
    ,
    change
    , etc.)
  • Hover details for components and props
  • Unknown component warnings
gea-tools
扩展(位于
packages/gea-tools
)提供以下能力:
  • JSX标签内的组件补全
  • 基于组件签名的Prop补全
  • 事件属性补全(
    click
    input
    change
    等)
  • 组件和Prop的悬停详情
  • 未知组件警告

Documentation

文档

Full documentation is in the
docs/
directory of the repository, structured for GitBook:
  • Getting started, core concepts, Gea Mobile, tooling, and API reference
  • Comparison pages: React vs Gea, Vue vs Gea
完整文档位于仓库的
docs/
目录下,适配GitBook结构:
  • 快速入门、核心概念、Gea Mobile、工具链、API参考
  • 对比页面:React vs Gea、Vue vs Gea