A comprehensive implementation of Vue.js core features from scratch, demonstrating how Vue's reactivity system, template parsing, directives, and component system work under the hood.
This is an educational implementation that recreates Vue.js's core functionality to understand how modern reactive frameworks work. It includes:
- Template Parser: HTML template parsing with directive support
- Reactivity System: Data observation and change detection
- Directives: v-bind, v-if, v-for, v-on, and mustache interpolation
- Component System: Component creation, lifecycle, and communication
- Event System: Component event broadcasting and dispatching
- Batch Updates: Performance optimization through batched DOM updates
- Slot System: Content projection between components
src/
βββ template-parser.js # HTML template parsing and AST generation
βββ directives.js # Directive implementations (v-bind, v-if, v-for, etc.)
βββ observe.js # Reactive data system with watchers
βββ batch-update.js # Batched DOM updates for performance
βββ components.js # Component creation and management
βββ events.js # Component event system ($emit, $on, $broadcast)
βββ hooks.js # Component hooks (useData, useMethods, etc.)
βββ lifecycle.js # Component lifecycle management
βββ render.js # Main rendering orchestration
βββ slot.js # Slot content projection
βββ queue.js # Queue data structure
βββ stack.js # Stack data structure
βββ linked-list.js # Linked list for component tree
βββ errors.js # Error handling utilities
- Uses
Object.definePropertyto create getters/setters - Watchers are triggered when data changes
- Supports nested objects and arrays
- Automatic dependency tracking
- Parses HTML templates into AST (Abstract Syntax Tree)
- Handles directives, components, and text interpolation
- Supports nested templates for v-if and v-for
- Mustache
{{}}: Text interpolation - v-bind: Dynamic attribute binding
- v-if: Conditional rendering
- v-for: List rendering with track-by optimization
- v-on: Event handling
- Component tree creation and management
- Props passing and validation
- Lifecycle hooks (mounted, unmounted)
- Component communication via events
$emit: Emit events to parent components$on: Listen to events$broadcast: Broadcast events to all descendants$dispatch: Dispatch events up the component tree
- Queues DOM updates to prevent excessive re-renders
- Uses microtasks for optimal performance
- Deduplicates updates with the same watcher ID
- Node.js (version 14 or higher)
- Yarn package manager
# Clone the repository
git clone <repository-url>
cd how-vue-works
# Install dependencies
yarn install
# Run tests
yarn testimport render from './src/render';
import observe from './src/observe';
// Create reactive data
const data = observe({
message: 'Hello Vue!',
items: ['Apple', 'Banana', 'Orange'],
showList: true,
});
// Define a component
const MyComponent = () => `
<div>
<h1>{{ message }}</h1>
<ul v-if="showList">
<li v-for="item in items" track-by="item">{{ item }}</li>
</ul>
<button v-on:click="toggleList">Toggle List</button>
</div>
`;
// Render the component
const { componentNode } = render(MyComponent, {}, '#app');The template parser converts HTML strings into a structured format that can be processed by the directive system:
// Template
const template = '<div v-if="show">{{ message }}</div>';
// Parsed into AST-like structure with directives
// - Element: div
// - Directives: [v-if, mustache]
// - Attributes: { 'v-if': 'show' }Data becomes reactive through the observe function:
const data = observe({
count: 0,
user: { name: 'John' },
});
// Changes trigger watchers automatically
data.count = 1; // Triggers all watchers for 'count'
data.user.name = 'Jane'; // Triggers watchers for 'user.name'Each directive handles specific DOM manipulation:
- Mustache: Updates text content when data changes
- v-bind: Updates element attributes
- v-if: Conditionally renders/removes elements
- v-for: Renders lists with optimization
- v-on: Binds event listeners
Components communicate through events:
// Parent component
const Parent = () => `
<child-component v-on:message="handleMessage"></child-component>
`;
// Child component
const Child = () => `
<button v-on:click="sendMessage">Send Message</button>
`;
// Child emits event
componentNode.$emit('message', 'Hello from child!');DOM updates are batched for performance:
// Multiple rapid changes trigger only one update
data.count = 1;
data.count = 2;
data.count = 3;
// Only one DOM update occursThe project includes comprehensive tests for all features:
# Run all tests
yarn test
# Run specific test file
yarn test test/directives.spec.js
# Run tests in watch mode
yarn test --watchTest coverage includes:
- Template parsing
- Directive functionality
- Reactive data system
- Component lifecycle
- Event system
- Batch updates
- Slot system
how-vue-works/
βββ src/ # Source code
βββ test/ # Test files
βββ package.json # Dependencies and scripts
βββ babel.config.js # Babel configuration
βββ .eslintrc.json # ESLint configuration
βββ .prettierrc.json # Prettier configuration
- lodash: Utility functions
- jest: Testing framework
- babel: JavaScript transpilation
- eslint: Code linting
- prettier: Code formatting
- Make changes to source files in
src/ - Add corresponding tests in
test/ - Run tests to ensure functionality
- Code is automatically formatted and linted
This project demonstrates:
- Reactive Programming: How data changes trigger UI updates
- Template Compilation: Converting templates to executable code
- Virtual DOM Concepts: Efficient DOM manipulation
- Component Architecture: Building reusable UI components
- Event Systems: Component communication patterns
- Performance Optimization: Batching and deduplication strategies
This is an educational project. Feel free to:
- Report bugs or issues
- Suggest improvements
- Add new features
- Improve documentation
ISC License - see LICENSE file for details.
- Inspired by Vue.js architecture
- Built for educational purposes
- Thanks to the Vue.js team for the excellent framework
Note: This is an educational implementation and should not be used in production. It's designed to help understand how modern reactive frameworks work under the hood.