Component API Reference
- Home
- Documentation
- API Reference
- Component API Reference
Overview
The Component API in Now.js provides a comprehensive system for creating and managing UI components. Components are managed through the ComponentManager and follow a lifecycle pattern similar to other modern frameworks.
Component Definition
Components are defined using the define
method
Now.getManager('component').define('my-component', {
// Component template
template: `
<div class="my-component">
<h2>{{title}}</h2>
<p>{{content}}</p>
</div>
`,
// Component state
state: {
title: 'Default Title',
content: 'Default Content'
},
// Methods
methods: {
updateContent(newContent) {
this.state.content = newContent;
}
},
// Computed properties
computed: {
titleLength() {
return this.state.title.length;
}
},
// Lifecycle hooks
created() {
console.log('Component created');
},
mounted() {
console.log('Component mounted');
}
});
Component Properties
Required Properties
Property | Type | Description |
---|---|---|
template |
String | HTML template for the component |
state |
Object | Component's internal state |
Optional Properties
methods |
Object | Component methods |
computed |
Object | Computed properties |
watch |
Object | State watchers |
props |
Object | Component properties validation |
Lifecycle Hooks
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed
Hook | Description | Use Case |
---|---|---|
beforeCreate |
Called before component initialization | Setup initial configuration |
created |
Called after component is initialized | Initialize state, fetch data |
beforeMount |
Called before component is mounted to DOM | Prepare DOM operations |
mounted |
Called after component is mounted | DOM manipulations, add event listeners |
beforeUpdate |
Called before state update | Prepare for state changes |
updated |
Called after state update | React to state changes |
beforeDestroy |
Called before component removal | Cleanup resources |
destroyed |
Called after component is removed | Final cleanup |
State Management
Direct State Access
// In component methods
this.state.count = 5;
// Access in template
{{count}}
Computed Properties
computed: {
doubleCount() {
return this.state.count * 2;
},
fullName() {
return `${this.state.firstName} ${this.state.lastName}`;
}
}
Watchers
watch: {
'count': {
handler(newValue, oldValue) {
console.log(`Count changed from ${oldValue} to ${newValue}`);
},
immediate: true
}
}
Methods
Component Methods
methods: {
increment() {
this.state.count++;
},
async fetchData() {
const response = await fetch('/api/data');
this.state.data = await response.json();
}
}
Event Handlers
methods: {
handleClick(event) {
event.preventDefault();
this.state.clicked = true;
}
}
Component Communication
Props
// Component definition
{
props: {
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
}
}
}
// Usage in HTML
<my-component
data-prop-title="Hello"
data-prop-count="5">
</my-component>
Events
// Emit event
methods: {
submitForm() {
const event = Now.getManager('event');
event.emit('form:submit', {
data: this.state.formData
});
}
}
// Listen for event
mounted() {
const event = Now.getManager('event');
event.on('form:submit', this.handleSubmit);
}
Error Handling
Error Boundaries
{
errorBoundary: true,
errorCaptured(error, info) {
console.error('Component error:', error);
this.state.error = error;
return false; // Prevent error propagation
}
}
Performance Optimization
Render Strategies
{
// Choose render strategy
renderStrategy: 'auto', // 'auto', 'static', or 'always'
// Custom shouldUpdate implementation
shouldUpdate(newState, oldState) {
return newState.count !== oldState.count;
}
}
Best Practices
- Keep components focused and single-responsibility
- Use computed properties for derived state
- Implement proper cleanup in beforeDestroy
- Validate props to catch errors early
- Use error boundaries for robust error handling
- Optimize rendering performance with appropriate strategies
Complete Example
Now.getManager('component').define('user-profile', {
template: `
<div class="user-profile">
<h2>{{fullName}}</h2>
<p class="email">{{user.email}}</p>
<div class="stats">
Posts: {{stats.posts}}
Followers: {{stats.followers}}
</div>
<button onclick="{{methods.follow}}">
{{isFollowing ? 'Unfollow' : 'Follow'}}
</button>
</div>
`,
props: {
user: {
type: Object,
required: true
}
},
state: {
stats: {
posts: 0,
followers: 0
},
isFollowing: false
},
computed: {
fullName() {
return `${this.props.user.firstName} ${this.props.user.lastName}`;
}
},
methods: {
async follow() {
try {
await this.toggleFollow();
this.state.isFollowing = !this.state.isFollowing;
this.updateStats();
} catch (error) {
console.error('Follow action failed:', error);
}
},
async fetchStats() {
const response = await fetch(`/api/users/${this.props.user.id}/stats`);
this.state.stats = await response.json();
}
},
watch: {
'user.id': {
handler() {
this.fetchStats();
},
immediate: true
}
},
mounted() {
this.fetchStats();
},
beforeDestroy() {
// Cleanup
},
errorCaptured(error) {
console.error('Component error:', error);
return false;
}
});