Now.js

  • Home
  • Documentation
  • Components
  • Examples

Component API Reference

  1. Home
  2. Documentation
  3. API Reference
  4. 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;
  }
});

Now.js

Modern Frontend Framework

Documentation

  • Getting Started
  • Components
  • API Reference

Community

  • GitHub
  • Examples
  • Showcase

© 2024 Now.js. MIT License.