@fluixi/dom (英语)
DOM运行时间编译器目标:外科精细刷新,水合和SSR.
运行时间 @fluixi/compiler 发出呼叫 它提供低级DOM操作:
元素创建、活性属性和属性、插入、控制流、水分:
它可以做出改变 准确更新约束 取决于它。 虽然大部分可以直接使用
通过编译的JSX或 html 模板.
特征
- 🎯 精细反应: 只更新需要更改的精确 DOM 节点
- 🔄 信号存储集成( S): 具有任何反应系统(信号、储存、可观察)的工作
- 🔁 水分: 采用服务器发送的节点, 而不是在它们旁边重建
- 🚀 最佳业绩: Template 缓存、事件授权和最小重接
- 🧩 控制流程组件: 内置显示器, for, switch, Portal等
- 📦 无依赖: 核心运行时间对反应系统没有外部依赖性
- 🔧 灵活融合: 单独使用或与您的反应库集成
安装
npm install @fluixi/dom
# or
pnpm add @fluixi/dom
# or
yarn add @fluixi/dom
快速启动
基本用途
import { insert, createElement, setProperty } from '@fluixi/dom';
// Create an element
const div = createElement('div');
// Set properties
setProperty(div, 'className', 'container');
setProperty(div, 'textContent', 'Hello World');
// Insert into DOM
document.body.appendChild(div);
有信号
import { insert, createElement } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [count, setCount] = createSignal(0);
const div = createElement('div');
// Insert reactive text
insert(div, () => `Count: ${count()}`);
document.body.appendChild(div);
// Updates automatically!
setCount(1); // DOM updates to "Count: 1"
构成部分
装订一旦导入就会工作: 上面的例子不需要设置 。 渲染 组件 需要填入一个接合器,所以组件调用是自有和可支配的:
import '@fluixi/core'; // wires it for you at import time
使用 @fluixi/dom 无 @fluixi/core填充自己: 看
一体化。 。 。 .
核心 API
DOM 操纵
insert(parent, accessor, marker?, init?)
插入带有自动反应跟踪的动态内容 .
import { insert } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [text, setText] = createSignal('Hello');
const div = document.createElement('div');
// Insert reactive content
insert(div, () => text());
// Or insert static content
insert(div, 'Static text');
// With a marker for positioning
const marker = document.createTextNode('');
div.appendChild(marker);
insert(div, () => text(), marker);
spread(options)
将道具分散到有精细更新的元素上.
import { spread, createElement } from '@fluixi/dom';
const element = createElement('div');
const props = {
className: 'container',
style: { color: 'red' },
onClick: () => console.log('clicked'),
};
spread({ element, props });
属性( P)
import { setAttribute, setProperty, setClassName, setStyle } from '@fluixi/dom';
const div = createElement('div');
// Set attribute
setAttribute(div, 'data-id', '123');
// Set property
setProperty(div, 'value', 'text');
// Set className (handles strings, arrays, objects)
setClassName(div, 'btn btn-primary');
setClassName(div, ['btn', 'btn-primary']);
setClassName(div, { btn: true, 'btn-primary': true });
// Set style (handles strings or objects)
setStyle(div, 'color: red; font-size: 16px');
setStyle(div, { color: 'red', fontSize: '16px' });
动态属性( P)
import { setDynamicAttribute, setDynamicProperty } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [color, setColor] = createSignal('red');
const div = createElement('div');
// Reactive attribute
setDynamicAttribute(div, 'data-color', color);
// Reactive property
setDynamicProperty(div, 'className', () => `text-${color()}`);
代表团
import { delegateEvents, addDelegatedEventListener } from '@fluixi/dom';
// Setup delegation for common events
delegateEvents(['click', 'input', 'change']);
// Add delegated listener
const button = createElement('button');
addDelegatedEventListener(button, 'click', (e) => {
console.log('Button clicked!');
});
控制流程组件
显示
附带可选倒计时的有条件渲染.
import { Show } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [user, setUser] = createSignal(null);
// Basic usage
Show({
when: user,
children: (u) => `Hello, ${u.name}!`,
fallback: 'Loading...',
});
// With reactive condition
Show({
when: () => user() !== null,
children: (u) => `Hello, ${u.name}!`,
});
对于
带有最佳更新的按键列表渲染 .
import { For } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [items, setItems] = createSignal([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
]);
For({
each: items,
children: (item, index) => {
const div = createElement('div');
insert(div, () => `${index()}: ${item.name}`);
return div;
},
fallback: 'No items',
});
指数
基于索引的列表渲染(当项目改变但位置不变时使用).
import { Index } from '@fluixi/dom';
Index({
each: () => [1, 2, 3, 4, 5],
children: (item, index) => {
const div = createElement('div');
insert(div, () => `Item ${index}: ${item()}`);
return div;
},
});
切换/匹配
多向有条件渲染.
import { Switch, Match } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [state, setState] = createSignal('loading');
Switch({
fallback: 'Unknown state',
children: [
Match({
when: () => state() === 'loading',
children: 'Loading...',
}),
Match({
when: () => state() === 'success',
children: 'Success!',
}),
Match({
when: () => state() === 'error',
children: 'Error occurred',
}),
],
});
门户
不同 DOM 位置的 Render 内容 .
import { Portal } from '@fluixi/dom';
Portal({
mount: document.body,
children: createElement('div', { textContent: 'Portal content' }),
});
动态
根据运行时间条件动态渲染组件 .
import { Dynamic } from '@fluixi/dom';
import { createSignal } from '@fluixi/reactive/signal';
const [component, setComponent] = createSignal('div');
Dynamic({
component: component,
className: 'dynamic-element',
children: 'Dynamic content',
});
边界错误
获取和处理组件树中的出错 .
import { ErrorBoundary } from '@fluixi/dom';
ErrorBoundary({
fallback: (error, reset) => {
const div = createElement('div');
insert(div, `Error: ${error.message}`);
const button = createElement('button');
button.textContent = 'Retry';
button.onclick = reset;
div.appendChild(button);
return div;
},
children: /* your components */,
});
一体化
这个软件包不具有反应系统 一个接合连接了两者: 组件调用被包裹,它是一个单一函数:
import { registerCreateComponent } from '@fluixi/dom';
registerCreateComponent((Comp, props) => myOwnedCall(Comp, props));
你几乎从来没有叫这个. 导入 @fluixi/core 电线 @fluixi/reactive 输入
您在导入时间,所以应用程序只是导入和制作。 如果你用的话,这很重要 @fluixi/dom
或者用不同的反应库驱动它.
import { isIntegrationInitialized, resetIntegration } from '@fluixi/dom';
isIntegrationInitialized(); // has something claimed the seam?
resetIntegration(); // drop it again — tests
initializeIntegration({ signalSystem }) 是较老的切入点,仍然有效;它选择
createComponent 放弃你通过的东西 忽略其他的.
模板
html 编辑模板,不解释: @fluixi/compiler 把他们变成
相同的调用此软件包曝光, 因此运行时不需要花费任何成本, 不需要模板
图书馆.
import { html } from '@fluixi/core';
function Counter() {
const n = $signal(0);
return html`<button @click=${() => n.set(n() + 1)}>${n()}</button>`;
}
高级使用
内存管理
捆绑着活活生生的 与主人同生共活 所以拆了一块地盘 以它去除听众和效果 :
import { createRoot, onCleanup } from '@fluixi/reactive';
import { insert } from '@fluixi/dom';
createRoot((dispose) => {
insert(container, () => text());
onCleanup(() => console.log('bindings gone'));
dispose(); // runs the cleanups, drops the bindings
});
性能提示
- 使用
For列表编号:For组件使用按键调节以优化更新 - 代表活动: 使用
delegateEvents与许多活动听众一起提高性能 - 批量更新: 环绕多个更新
batch()尽量减少重交 - 纪念昂贵的计算: 使用
createMemo从您的信号系统 - 需要时取消跟踪: 使用
untrack()读取被动值而不创建依赖性 - 同步静态内容: 将静态元素移出被动上下文
import { batch, createMemo, untrack } from '@fluixi/dom';
// Batch multiple updates
batch(() => {
setSignal1(value1);
setSignal2(value2);
setSignal3(value3);
});
// Memoize expensive computations
const computed = createMemo(() => {
return expensiveOperation(signal1(), signal2());
});
// Read without tracking
const value = untrack(() => signal());
类型脚本支持
全面类型定义的全类型脚本支持.
import type {
Children,
InsertOptions,
SpreadOptions,
SignalSystem,
StoreSystem,
ShowProps,
ForProps,
} from '@fluixi/dom';
// Use types in your code
const mySignalSystem: SignalSystem = {
createEffect: (fn) => {
// Implementation
return () => {};
},
batch: (fn) => {
// Implementation
},
};
浏览器支持
- 现代浏览器(Chrome,Firefox,Safari,边缘)
- ES2020+ 所需数量
- 支持的浏览器不需要多填充
调试
import { isIntegrationInitialized } from '@fluixi/dom';
// A component rendering as a bare function usually means nothing claimed the seam
isIntegrationInitialized();
与其他图书馆的比较
vs 固态JS
这个软件包深受SolidJS的多姆表达的启发,但:
- 作为一个独立的图书馆工作
- 可以通过另一种反应系统驱动
registerCreateComponent - 服务于JSX和
html" 模板, 汇编到相同的呼叫中
vs 反应
- 细纹反应( 无虚拟 DOM)
- 不需要对账
- 直接 DOM 操作
- 运行时间较小
- 提高许多使用案例的绩效
捐款
欢迎捐款! 请参看准则的主要存放处.
许可证
麻省理工学院
相关软件包
@fluixi/jsx- JSX使用DOM软件包运行时间@fluixi/reactive- 信号和存储执行@fluixi/compiler- 汇编JSX和html进入这些电话
资源
- SolidJS 文档: dom- 表达式是前作中最接近的艺术
- 数字表达式
- Fluixi 文档