or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

application-lifecycle.mdbuild-configuration.mdcomponent-system.mdevent-channels.mdindex.mdunified-api.mdutilities.md
tile.json

component-system.mddocs/

Component System

Functions for creating QQ mini-program pages and components from Vue.js options with full lifecycle support, data binding, and event handling.

Capabilities

Create Page

Converts Vue.js page options to QQ mini-program page with proper lifecycle mapping and navigation support.

/**
 * Creates a QQ mini-program page from Vue.js page options
 * @param options - Vue page configuration with QQ mini-program lifecycle hooks
 */
function createPage(options: PageOptions): void;

interface PageOptions {
  /** Reactive data factory function */
  data?: () => Record<string, any>;
  /** Called when page loads with query parameters */
  onLoad?: (query: Record<string, string>) => void;
  /** Called when page becomes visible */
  onShow?: () => void;
  /** Called when page initial render is complete */
  onReady?: () => void;
  /** Called when page becomes hidden */
  onHide?: () => void;
  /** Called when page is unloaded */
  onUnload?: () => void;
  /** Called when user pulls down to refresh */
  onPullDownRefresh?: () => void;
  /** Called when user scrolls to bottom */
  onReachBottom?: () => void;
  /** Called when page is scrolled */
  onPageScroll?: (options: PageScrollOptions) => void;
  /** Called when window is resized */
  onResize?: (options: ResizeOptions) => void;
  /** Called when tab is tapped */
  onTabItemTap?: (options: TabItemTapOptions) => void;
  /** Called when page is added to favorites */
  onAddToFavorites?: (options: AddToFavoritesOptions) => any;
  /** Called when sharing to timeline */
  onShareTimeline?: () => ShareTimelineResult;
  /** Called when sharing to chat */
  onShareAppMessage?: (options: ShareAppMessageOptions) => ShareAppMessageResult;
  /** Page methods */
  methods?: Record<string, Function>;
  /** Computed properties */
  computed?: Record<string, Function>;
  /** Watchers */
  watch?: Record<string, Function | WatchOptions>;
  /** Custom properties */
  [key: string]: any;
}

Usage Example:

import { createPage } from "@dcloudio/uni-mp-qq";

createPage({
  data() {
    return {
      title: 'Welcome to QQ Mini-Program',
      userList: [],
      loading: false,
      currentPage: 1
    };
  },
  
  onLoad(query) {
    console.log('Page loaded with query:', query);
    this.loadInitialData();
  },
  
  onShow() {
    console.log('Page visible');
    // Refresh data if needed
  },
  
  onReady() {
    console.log('Page render complete');
    // Setup UI components that need DOM
  },
  
  onPullDownRefresh() {
    this.refreshData();
  },
  
  onReachBottom() {
    this.loadMoreData();
  },
  
  onShareAppMessage(options) {
    return {
      title: this.title,
      path: '/pages/home/home',
      imageUrl: '/static/share-image.png'
    };
  },
  
  methods: {
    async loadInitialData() {
      this.loading = true;
      try {
        const result = await uni.request({
          url: 'https://api.example.com/users',
          method: 'GET'
        });
        this.userList = result.data;
      } catch (error) {
        console.error('Load data error:', error);
      } finally {
        this.loading = false;
      }
    },
    
    async refreshData() {
      this.currentPage = 1;
      await this.loadInitialData();
      uni.stopPullDownRefresh();
    },
    
    async loadMoreData() {
      this.currentPage++;
      // Load more logic
    },
    
    handleUserTap(userId) {
      uni.navigateTo({
        url: `/pages/user/user?id=${userId}`
      });
    }
  },
  
  computed: {
    hasUsers() {
      return this.userList.length > 0;
    }
  },
  
  watch: {
    userList: {
      handler(newVal, oldVal) {
        console.log('User list changed:', newVal.length);
      },
      deep: true
    }
  }
});

Create Component

Converts Vue.js component options to QQ mini-program component with props, events, and lifecycle support.

/**
 * Creates a QQ mini-program component from Vue.js component options
 * @param options - Vue component configuration
 */
function createComponent(options: ComponentOptions): void;

interface ComponentOptions {
  /** Component props definition */
  props?: Record<string, PropDefinition> | string[];
  /** Reactive data factory function */
  data?: () => Record<string, any>;
  /** Component methods */
  methods?: Record<string, Function>;
  /** Computed properties */
  computed?: Record<string, Function>;
  /** Watchers */
  watch?: Record<string, Function | WatchOptions>;
  /** Called when component is created */
  created?: () => void;
  /** Called when component is mounted */
  mounted?: () => void;
  /** Called when component is updated */
  updated?: () => void;
  /** Called when component is destroyed */
  destroyed?: () => void;
  /** Component behaviors (QQ mini-program specific) */
  behaviors?: string[];
  /** External classes (QQ mini-program specific) */
  externalClasses?: string[];
  /** Component options (QQ mini-program specific) */
  options?: {
    multipleSlots?: boolean;
    addGlobalClass?: boolean;
    [key: string]: any;
  };
  /** Custom properties */
  [key: string]: any;
}

interface PropDefinition {
  type: any;
  default?: any;
  required?: boolean;
  validator?: (value: any) => boolean;
}

interface WatchOptions {
  handler: Function;
  deep?: boolean;
  immediate?: boolean;
}

Usage Example:

import { createComponent } from "@dcloudio/uni-mp-qq";

createComponent({
  props: {
    title: {
      type: String,
      required: true
    },
    type: {
      type: String,
      default: 'default',
      validator: (value) => ['default', 'primary', 'success', 'warning', 'danger'].includes(value)
    },
    disabled: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: 'medium'
    }
  },
  
  data() {
    return {
      clicking: false,
      internalState: null
    };
  },
  
  created() {
    console.log('Component created with props:', this.$props);
  },
  
  mounted() {
    console.log('Component mounted');
    this.initializeComponent();
  },
  
  methods: {
    initializeComponent() {
      // Component initialization logic
      this.internalState = this.computeInitialState();
    },
    
    computeInitialState() {
      return {
        timestamp: Date.now(),
        id: Math.random().toString(36).substr(2, 9)
      };
    },
    
    handleClick(event) {
      if (this.disabled) return;
      
      this.clicking = true;
      setTimeout(() => {
        this.clicking = false;
      }, 150);
      
      // Emit custom event to parent
      this.$emit('click', {
        type: this.type,
        timestamp: Date.now(),
        originalEvent: event
      });
    },
    
    handleLongPress(event) {
      if (this.disabled) return;
      
      this.$emit('longpress', {
        type: this.type,
        duration: event.detail.duration || 0
      });
    }
  },
  
  computed: {
    buttonClass() {
      return [
        'custom-button',
        `button-${this.type}`,
        `button-${this.size}`,
        {
          'button-disabled': this.disabled,
          'button-clicking': this.clicking
        }
      ];
    },
    
    buttonStyle() {
      const styles = {};
      if (this.disabled) {
        styles.opacity = 0.6;
      }
      return styles;
    }
  },
  
  watch: {
    type: {
      handler(newType, oldType) {
        console.log(`Button type changed from ${oldType} to ${newType}`);
        this.updateTypeSpecificLogic();
      },
      immediate: true
    },
    
    disabled(newVal) {
      if (newVal) {
        this.clicking = false;
      }
    }
  },
  
  // QQ mini-program specific options
  options: {
    multipleSlots: true,
    addGlobalClass: true
  },
  
  // External classes for styling
  externalClasses: ['custom-class', 'button-class']
});

Component Communication

Parent-Child Communication

// Parent component passing data and listening for events
createComponent({
  data() {
    return {
      buttonText: 'Click Me',
      buttonType: 'primary'
    };
  },
  
  methods: {
    handleButtonClick(eventData) {
      console.log('Button clicked:', eventData);
      uni.showToast({
        title: 'Button clicked!',
        icon: 'success'
      });
    },
    
    handleButtonLongPress(eventData) {
      console.log('Button long pressed:', eventData);
    }
  }
});

// Child component emitting events
createComponent({
  methods: {
    onClick() {
      this.$emit('click', { timestamp: Date.now() });
    },
    
    onLongPress() {
      this.$emit('longpress', { duration: 1000 });
    }
  }
});

Component Lifecycle Details

interface PageScrollOptions {
  /** Scroll top position */
  scrollTop: number;
}

interface ResizeOptions {
  /** Window size information */
  size: {
    windowWidth: number;
    windowHeight: number;
  };
}

interface TabItemTapOptions {
  /** Tab index */
  index: number;
  /** Page path */
  pagePath: string;
  /** Tab text */
  text: string;
}

interface AddToFavoritesOptions {
  /** Web page URL for H5 */
  webviewUrl?: string;
}

interface ShareAppMessageOptions {
  /** Share source: button, menu */
  from: 'button' | 'menu';
  /** Target information if from button */
  target?: any;
  /** Web page URL for H5 */
  webviewUrl?: string;
}

interface ShareAppMessageResult {
  title: string;
  path: string;
  imageUrl?: string;
}

interface ShareTimelineResult {
  title: string;
  query?: string;
  imageUrl?: string;
}

Advanced Component Features

Component Slots

// Component with multiple slots
createComponent({
  options: {
    multipleSlots: true
  },
  
  // Template would use <slot name="header"></slot>, <slot></slot>, <slot name="footer"></slot>
});

Component Behaviors

// Using QQ mini-program behaviors
createComponent({
  behaviors: ['wx://form-field'],
  
  props: {
    name: String,
    value: {
      type: String,
      default: ''
    }
  }
});

External Styling

// Component with external classes
createComponent({
  externalClasses: ['my-class', 'custom-button-class'],
  
  // Parent can pass: <my-component my-class="parent-style" />
});

Component System Architecture

  • Pages are top-level route components with navigation lifecycle
  • Components are reusable UI elements with props and events
  • Both support full Vue.js patterns (data, computed, watch, methods)
  • QQ mini-program specific features (behaviors, external classes) are supported
  • Lifecycle hooks map between Vue.js and QQ mini-program conventions
  • Event system uses Vue's $emit pattern adapted for mini-program event handling