@nullfiy/core
v0.0.1
Published
TanStack 风格的框架无关核心逻辑库,提供可组合的特性系统和细粒度的状态控制。
Downloads
113
Readme
@nullfiy/core
TanStack 风格的框架无关核心逻辑库,提供可组合的特性系统和细粒度的状态控制。
✨ 特性
- ✅ 框架无关 - 可用于 React、Solid、Vue 等任何框架
- ✅ 高度可扩展 - 通过 Features/Plugins 模式组合功能
- ✅ 细粒度控制 - 如
instance.click(),instance.focus()等直观 API - ✅ 优秀的类型推导 - 充分利用 TypeScript 类型系统
- ✅ 零依赖 - 核心包无外部依赖
- ✅ 性能追踪 - 内置性能监控和渲染次数统计
📦 安装
pnpm add @nullfiy/core🚀 快速开始
基础使用 - Button 实例
import { createButton } from '@nullfiy/core';
const button = createButton({
disabled: false,
onPress: () => console.log('Button pressed!'),
onFocusChange: (focused) => console.log('Focus:', focused),
});
// 细粒度控制
button.click(); // 完整的点击操作
button.press(); // 只按下
button.release(); // 只释放
button.focus(); // 聚焦
button.blur(); // 失焦
// 状态访问
console.log(button.state);
// { focused: false, pressed: false, focusVisible: false, focusWithin: false }
// 检查状态
button.isFocused(); // false
button.isPressed(); // false
button.isDisabled(); // false
// 更新配置
button.setDisabled(true);自定义状态扩展
interface CustomButtonState {
focused: boolean;
pressed: boolean;
focusVisible: boolean;
focusWithin: boolean;
// 自定义字段
clickCount: number;
lastClickTime: number;
}
const button = createButton<CustomButtonState>({
initialState: {
focused: false,
pressed: false,
focusVisible: false,
focusWithin: false,
clickCount: 0,
lastClickTime: 0,
},
onPress: () => {
button.setState((old) => ({
...old,
clickCount: old.clickCount + 1,
lastClickTime: Date.now(),
}));
},
});
button.click();
console.log(button.state.clickCount); // 1组合特性创建自定义实例
import { createCore, createFocusFeature, createPressFeature } from '@nullfiy/core';
// 方式 1: 链式调用(推荐)- initialState 在各自 feature 中定义
const instance = createCore()
.extend(createFocusFeature(), {
// ✓ 有完整的类型提示
initialState: {
focused: false,
focusVisible: false,
focusWithin: false,
},
onFocusChange: (focused) => console.log('Focus:', focused),
})
.extend(createPressFeature(), {
// ✓ 有完整的类型提示
initialState: {
pressed: false,
},
onPress: () => console.log('Pressed!'),
});
// 现在拥有所有功能
instance.focus();
instance.press();
console.log(instance.state); // { focused, pressed, focusVisible, ... }
// 方式 2: 使用泛型(全局定义 state 类型)
interface MyState {
focused: boolean;
pressed: boolean;
focusVisible: boolean;
focusWithin: boolean;
customField: string;
}
const instanceWithTypes = createCore<MyState>({
// ✓ 有完整的类型提示和检查
initialState: {
focused: false,
pressed: false,
focusVisible: false,
focusWithin: false,
customField: 'value',
},
})
.extend(createFocusFeature())
.extend(createPressFeature());📚 核心概念
1. Core Instance
核心实例提供基础的状态管理功能:
const core = createCore({
initialState: { count: 0 },
onStateChange: (state) => console.log(state),
debug: true, // 开启调试模式
});
core.setState({ count: 1 });
core.setState((old) => ({ count: old.count + 1 }));
core.reset(); // 重置到初始状态2. initialState 使用模式
模式 1: 在 extend 中定义(推荐)
每个 feature 管理自己的 initialState,有完整的类型提示:
const instance = createCore()
.extend(createFocusFeature(), {
initialState: { // ✓ 类型提示:Partial<FocusState>
focused: true,
focusVisible: false,
focusWithin: false,
},
})
.extend(createPressFeature(), {
initialState: { // ✓ 类型提示:Partial<PressState>
pressed: false,
},
});模式 2: 在 createCore 中定义(需要泛型)
适合提前知道完整 state 结构的场景:
interface AppState {
focused: boolean;
pressed: boolean;
focusVisible: boolean;
focusWithin: boolean;
}
const instance = createCore<AppState>({
initialState: { // ✓ 有类型提示和检查
focused: false,
pressed: false,
focusVisible: false,
focusWithin: false,
},
})
.extend(createFocusFeature())
.extend(createPressFeature());state vs initialState
initialState: 部分覆盖,与现有 state 合并state: 完整覆盖,替换整个 state
instance.extend(createFocusFeature(), {
initialState: {
focused: true, // 只设置 focused,其他字段保持默认
},
// vs
state: {
focused: true,
focusVisible: false, // 必须提供所有字段
focusWithin: false,
},
});3. Features (特性)
特性是可组合的功能模块,可以扩展核心实例:
Focus Feature
const instance = createCore()
.extend(createFocusFeature(), {
onFocusChange: (focused) => {},
onFocusVisibleChange: (visible) => {},
onFocusWithinChange: (within) => {},
autoBlur: false,
});
instance.focus();
instance.blur();
instance.toggleFocus();
instance.setFocusVisible(true);
instance.setFocusWithin(true);Press Feature
const instance = createCore()
.extend(createPressFeature(), {
onPress: () => {},
onPressChange: (pressed) => {},
onPressStart: () => {},
onPressEnd: () => {},
disabled: false,
minPressDuration: 0, // 最小按压时间(ms)
});
instance.press();
instance.release();
instance.togglePress();
instance.click(); // press + release
instance.setDisabled(true);4. 自定义 Feature
使用 defineFeature 创建自定义 feature:
import { defineFeature } from '@nullfiy/core';
interface CounterState {
count: number;
}
interface CounterOptions {
step?: number;
}
const counterFeature = defineFeature<
CounterState,
CounterOptions,
{ increment: () => void; decrement: () => void }
>("counter", (instance, options) => {
// options 自动包含 initialState 和 state
const initialCount = options?.initialState?.count ?? 0;
const step = options?.step ?? 1;
if (instance.state.count === undefined) {
instance.setState({ ...instance.state, count: initialCount });
}
return {
increment: () => {
instance.setState((old) => ({ ...old, count: old.count + step }));
},
decrement: () => {
instance.setState((old) => ({ ...old, count: old.count - step }));
},
};
});
// 使用
const counter = createCore()
.extend(counterFeature, {
initialState: { count: 10 }, // ✓ 有类型提示
step: 5, // ✓ 有类型提示
});
counter.increment(); // 155. Composites (组合)
预组合的实例,适合常见场景:
createButton()- Focus + Press 特性
6. 事件订阅
// 订阅所有状态变化
const unsubscribe = button.subscribe((state) => {
console.log('State changed:', state);
});
// 订阅特定事件
const unsubscribeFocus = button._on('focusChange', (focused) => {
console.log('Focus:', focused);
});
// 取消订阅
unsubscribe();
unsubscribeFocus();📊 性能追踪
内置性能监控工具,可以追踪状态更新次数、耗时等:
const button = createButton({ debug: true });
// 执行一些操作
button.click();
button.focus();
// 查看性能报告
button.getPerformanceReport();
// 📊 Performance Report: Instance
// ⏱️ Total Time: 1234ms
// 🔄 State Updates: 10
// 📢 Events Emitted: 15
// 👥 Subscriber Notifications: 20
// ⚡ Avg State Update Time: 0.123ms
// 📈 Updates Per Second: 8.10
// 💾 Total State Update Time: 1.234ms
// 查看最近的日志
button.getRecentLogs(5);React 渲染次数统计
import { createButton, createRenderCounter } from '@nullfiy/core';
function ButtonComponent() {
const button = useMemo(() => createButton({}), []);
const [state, setState] = useState(button.state);
// 创建渲染计数器
const renderCounter = useMemo(() => createRenderCounter('ButtonComponent'), []);
// 每次渲染时计数
renderCounter.count();
useEffect(() => {
const unsubscribe = button.subscribe(setState);
return unsubscribe;
}, []);
// 在卸载时打印报告
useEffect(() => {
return () => {
renderCounter.printReport();
};
}, []);
return <button onClick={() => button.click()}>Click me</button>;
}🎨 在不同框架中使用
React
import { useMemo, useState, useEffect } from 'react';
import { createButton } from '@nullfiy/core';
function Button() {
const button = useMemo(() => createButton({
onPress: () => console.log('pressed'),
}), []);
const [state, setState] = useState(button.state);
useEffect(() => {
return button.subscribe(setState);
}, []);
return (
<button
onMouseDown={() => button.press()}
onMouseUp={() => button.release()}
onFocus={() => button.focus()}
onBlur={() => button.blur()}
disabled={button.isDisabled()}
>
{state.pressed ? 'Pressed' : 'Normal'}
</button>
);
}Solid
import { createSignal, onMount } from 'solid-js';
import { createButton } from '@nullfiy/core';
function Button() {
const button = createButton({
onPress: () => console.log('pressed'),
});
const [state, setState] = createSignal(button.state);
onMount(() => {
button.subscribe(() => setState(button.state));
});
return (
<button
onMouseDown={() => button.press()}
onMouseUp={() => button.release()}
disabled={button.isDisabled()}
>
{state().pressed ? 'Pressed' : 'Normal'}
</button>
);
}Vue
import { ref, onMounted } from 'vue';
import { createButton } from '@nullfiy/core';
export default {
setup() {
const button = createButton({
onPress: () => console.log('pressed'),
});
const state = ref(button.state);
onMounted(() => {
button.subscribe((newState) => {
state.value = newState;
});
});
return {
button,
state,
};
},
};🏗️ 架构设计
@nullfiy/core/
├── core/ # 核心状态管理
│ ├── index.ts # createCore()
│ ├── types.ts # 类型定义
│ └── utils.ts # 工具函数
│
├── features/ # 可组合的特性
│ ├── focus/ # Focus 特性
│ └── press/ # Press 特性
│
├── composites/ # 预组合实例
│ └── button/ # Button 实例
│
└── utils/ # 工具
└── performance.ts # 性能追踪📝 示例
查看 src/examples/button-example.ts 获取完整的使用示例。
🔧 开发
# 安装依赖
pnpm install
# 运行 lint
pnpm lint
# 构建
pnpm build🚧 未来计划
- [ ] 添加更多特性(Hover, Drag, etc.)
- [ ] 添加单元测试
- [ ] 添加更多预组合实例(Toggle, Input, etc.)
- [ ] 性能优化(可选 WASM 加速)
- [ ] 完善文档和示例
📄 License
MIT
🤝 贡献
欢迎提交 Issue 和 PR!
