onejs-v2
v2.0.0
Published
OneJS Framework V2 - Modern reactive JavaScript framework with automatic .one file compilation
Maintainers
Readme
OneJS V2 Core
Modern, reactive, type-safe JavaScript framework for building SPAs.
🎯 Features
✅ Implemented
- View System: Enhanced View class với lifecycle management
- Reactive System: Fine-grained reactivity với dependency tracking
- Props Validation: Type-safe props với runtime validation
- Lifecycle Hooks: init, mounted, updated, unmounted
- Style Management: Auto-injection với deduplication
- Error Handling: Graceful error display
- Memory Management: Proper cleanup và unmount
🚧 In Progress
- Compiler: ONE file → JS compilation
- Template Engine: Optimized rendering
- HMR: Hot Module Replacement
📦 Installation
npm install onelaraveljs🚀 Usage
V1 (Backward Compatible)
import { App, View } from 'onelaraveljs';
// V1 code continues to workV2 (Modern API)
import { V2 } from 'onelaraveljs';
// Create reactive state
const state = V2.reactive({
count: 0,
user: { name: 'John' }
});
// Create view
const view = V2.View.create({
name: 'counter',
template(ctx, state, helpers) {
return `
<div>
<h1>Count: ${state.count}</h1>
<button onclick="${helpers.event(() => state.count++)}">
Increment
</button>
</div>
`;
},
styles: `
.counter { padding: 20px; }
button { padding: 10px 20px; }
`,
mounted() {
console.log('View mounted!');
}
});
// Initialize and mount
view.initialize({ count: 0 }).mount('#app');🎨 Reactive System
Basic Reactivity
import { V2 } from 'onelaraveljs';
// Reactive object
const state = V2.reactive({
count: 0,
user: { name: 'John' }
});
// Auto-tracks dependencies
V2.effect(() => {
console.log('Count:', state.count);
});
state.count++; // Logs: Count: 1Computed Properties
const state = V2.reactive({ count: 0 });
const doubled = V2.computed(() => state.count * 2);
console.log(doubled.value); // 0
state.count = 5;
console.log(doubled.value); // 10 (cached)Refs
const count = V2.ref(0);
console.log(count.value); // 0
count.value = 10;
console.log(count.value); // 10Watch
const state = V2.reactive({ count: 0 });
V2.watch(
() => state.count,
(newVal, oldVal) => {
console.log(`Count changed: ${oldVal} → ${newVal}`);
}
);
state.count = 5; // Logs: Count changed: 0 → 5useState Hook
const [count, setCount] = V2.useState(0);
console.log(count()); // 0
setCount(5);
console.log(count()); // 5
// With updater function
setCount(prev => prev + 1);
console.log(count()); // 6🎭 View Lifecycle
V2.View.create({
name: 'my-component',
// 1. Called once on creation
init() {
console.log('1. Initializing...');
},
// 2. Setup function - runs before mount
setup() {
const message = 'Hello!';
return { message };
},
// 3. Called when mounted to DOM
mounted() {
console.log('3. Mounted to DOM');
// Access this.$el
},
// 4. Called after each re-render
updated() {
console.log('4. Updated');
},
// 5. Called on cleanup
unmounted() {
console.log('5. Unmounted');
// Cleanup logic
}
});🎨 Template Helpers
template(ctx, state, helpers) {
return `
<!-- Escape HTML -->
<div>${helpers.escape(userInput)}</div>
<!-- Register events -->
<button onclick="${helpers.event(() => handleClick())}">
Click
</button>
<!-- Count array -->
<p>Total: ${helpers.count(items)}</p>
<!-- Memoize computed value -->
<p>Sum: ${helpers.memo('sum', () => items.reduce((a, b) => a + b, 0), [items])}</p>
<!-- Cached event handler -->
<div onclick="${helpers.cachedHandler('click', handleClick)}">
Click
</div>
`;
}🔧 Props Validation
V2.View.create({
name: 'user-card',
props: {
user: {
type: Object,
required: true
},
count: {
type: Number,
default: 0
},
items: {
type: Array,
default: () => []
}
},
template(ctx) {
return `
<div>
<h1>${ctx.props.user.name}</h1>
<p>Count: ${ctx.props.count}</p>
</div>
`;
}
});💾 Memory Management
const view = V2.View.create({...});
// Initialize
view.initialize({ user: {...} });
// Mount
view.mount('#app');
// Update
view.update({ user: {...} });
// Unmount (cleanup)
view.unmount();📊 Performance
Memoization
template(ctx, state, helpers) {
// Expensive computation - cached
const result = helpers.memo(
'expensive',
() => computeExpensiveValue(state.data),
[state.data] // Dependencies
);
return `<div>${result}</div>`;
}Event Handler Caching
template(ctx, state, helpers) {
// Handler is cached - not re-created on each render
const handler = helpers.cachedHandler(
'myHandler',
() => console.log('Clicked!')
);
return `<button onclick="${handler}">Click</button>`;
}🔄 Batch Updates
const scheduler = V2.createBatchScheduler();
// Schedule multiple updates
scheduler.schedule(() => state.count++);
scheduler.schedule(() => state.name = 'John');
scheduler.schedule(() => state.age = 25);
// All updates batched and executed together
// (automatically in next microtask)
// Or flush immediately
scheduler.flush();🎯 TypeScript Support
V2 is fully typed with JSDoc. For TypeScript projects:
import { V2 } from 'onelaraveljs';
interface User {
name: string;
email: string;
}
const state = V2.reactive<{ user: User }>({
user: { name: 'John', email: '[email protected]' }
});
// Type-safe!
state.user.name; // ✅
state.user.age; // ❌ Error🆚 V1 vs V2
| Feature | V1 | V2 | |---------|----|----| | Reactivity | Manual | Automatic | | TypeScript | ❌ | ✅ | | Lifecycle | Basic | Advanced | | Props Validation | ❌ | ✅ | | Memory Management | Manual | Automatic | | Performance | Good | Better | | Bundle Size | ~50KB | ~30KB |
📚 More Examples
See /examples for more usage examples.
🐛 Debugging
// Check if value is reactive
V2.isReactive(state); // true
// Check if value is ref
V2.isRef(count); // true
// Check if value is computed
V2.isComputed(doubled); // true
// Convert to raw object
const raw = V2.toRaw(state);🚀 Next Steps
- [ ] Implement Template Engine with optimizations
- [ ] Build Compiler (ONE → JS)
- [ ] Add HMR support
- [ ] Add Router
- [ ] Add SSR support
Status: ✅ Core Implemented
Version: 2.0.0-alpha
Last Updated: 2026-01-31
