Skip to content
hhh edited this page Jan 31, 2019 · 7 revisions

API Reference

Here is the API reference for @hyper-ui/core.

HUI

function HUI(type: any, properties?: object, ...children: any[]): HNode;

This is the default export of this package, or the only global exported if you include the UMD module in your HTML file. You can call this to create virtual nodes(called HNodes in this lib). This function can also be used as the JSX factory.

type

The first argument should be either a string or a symbol telling the type of the virtual node (quite like element tags in HTML). If the type has been defined as a custom component, then what the render method of its description returns will be rendered. Otherwise, it is used to specify the tag of the element which will be rendered.

properties

The second argument is an optional object representing the properties of the node (like element attributes). If the node is a custom component, then it will receive the props. Or, the props will be treated as the attributes of the element. For the latter, each prop will be set as is unless a corresponding handler is set in propHandlers or its name starts with on:

Any prop whose name starts with on will be considered as an event listener. A valid event listener prop name is: on+event(+option), where option can be one or some of Captrue, Nonpassive and Once which stand for the listening options. For instance, onclick means a simple click event listener, and ontouchstartOnceNonpassive means a one-off and nonpassive touchstart event listener.

children

Other arguments will be rendered as the children of the element or passed to the component as props.children.

HUI.render

function render(src: any, options?: RenderOptions): void;

This method renders src into real DOM node(s).

src

This argument tells what to be rendered. (See rendering rules for more information.)

RenderOptions.parent

This option indicates the parent node and is optional. (Default: document.body)

RenderOptions.clear

This is an optional boolean telling whether to clear the parent node before rendering. (Default: false)

RenderOptions.sync

This optional boolean tells whether to do rendering synchronously. (Default: false)

RenderOptions.owner

This optional option tells the owner virtual node. You may need this to link virtual nodes correctly.

RenderOptions.context

This is an optional option which can be a store object representing the initial context. (You may not need this parameter in most cases because you can use defaultContext to set initial context value pairs.)

RenderOptions.defaultContext

This is an optional object that represents default context value pairs.

RenderOptions.contextHandlers

This optional object tells the handlers which should be added to the context.

Rendering rules

Here are the rendering rules:

  • HNodes will be rendered according to what their render methods return;
  • Strings and numbers will be rendered as text nodes;
  • Arrays will be rendered according to their elements;
  • Other things will be rendered as empty text nodes.

HUI.define

function define(name: any, desc: object): symbol;

This method lets you define custom components. It returns a unique symbol standing for the components. You should pass the returned symbol to HUI calls as the first argument to create such components.

name

This should be a readable name used to identify the component.

desc

This is an object which stands for the description of the component. It can have following properties:

desc.defaultProps

This is an optional object telling the default props which will be merged with received props.

desc.defaultStore

This is an optional object which represents default store value pairs.

desc.storeHandlers

This optional object tells the handlers which should be added to the store.

desc.state

This is an array which contains some keys of the store of the component. When any stored value matching one of the given keys changes, the component will be updated.

desc.context

This is an array which contains some keys of the context. When any context value matching one of the given keys changes, the component will be updated.

desc.effects

function effectCallback(this: HNode, props: object, store: Store, context: Store): (() => void) | void;

This is an optional array which contains the effect callbacks that will be invoked after initialization. Each effect callback can do something like init and it can returns a callback that will be invoked before clear. Usually, you can do something with side-effects in an effect callback and clear them in the returned one. For example,

const Timer = HUI.define('Timer', {

    state: ['time'],

    defaultStore: { time: 0 },

    effects: [
        function timeEffectCallback(props, store) {
            // Create a timer here,
            const timerId = setInterval(store.inc, 1000, 'time');
            // and clear it in the returned callback
            return () => {
                clearInterval(timerId);
            }
        }
    ],

    render(props, store) {
        return store.get('time');
    }

});

Moreover, you can get more reusable effects by defining effect factories:

// Define a time initializing effect factory
function timeInitEffect(props, store) {
    store.set('time', props.start || 0);
}
// Define a timer effect factory
const timerEffect = (key, interval) => (props, store) => {
    const timerId = setInterval(store.inc, interval, key);
    return () => {
        clearInterval(timerId);
    };
};
// Use them in components
const Timer = HUI.define('Timer', {
    // ...
    effects: [
        timeInitEffect,
        timerEffect('time', 1000)
    ],
    // ...
});

desc.init

function init(this: HNode, props: object, store: Store, context: Store): void;

This property is an optional function. It will be invoked before the first render of the component to initialize the component. (e.g. store some initial values or fetch some data for the component.)

desc.render

function render(this: HNode, props: object, store: Store, context: Store): any;

This property is required and returns what to be rendered. Please remember that this method must be pure. That is, given the same arguments, it should return the same result. It mustn't do anything except giving out rendering results according to the given arguments.

desc.clear

function clear(this: HNode, props: object, store: Store, context: Store): void;

This property is an optional function. It will be invoked when the component will be destroyed to do some clearing things. (e.g. clear the timers set in init or cancel unfinished data fetching started in init.)

desc.catch

function catch(this: HNode, err: any, props: object, store: Store, context: Store): any;

This property is an optional function. It will be invoked when something goes wrong with the component. The first argument will be the error. In addition, what it returns will be rendered so that you can show some error messages. (Errors in clear will be printed in console instead of being passed to this method.)

Arguments explanation

this

The this pointers will be bound to virtual node instances. You may not need this in most cases.

props

This stands for received props. (There will always be a prop called children which is any array representing received children.)

store

This is a store object and each component instance will have one. You can use it to save some value pairs(e.g. states). If a value changes and its key is in the state array, then the component will be updated.

context

This is also a store object but each component instance under the same HUI.render call will have the same one. That is, this is like a global store which can be used to store some global value pairs.

HUI.propHandlers

This is a map which stores custom prop handlers for elements. There are some built-in handlers as well:

propHandlers-children

This handler compares and updates child nodes of elements.

propHandlers-style

The style handler handles style for you so that you can use either strings or objects to describe styles. Please note that if you pass an object to describe styles, you should write style names in camel case. (e.g. textAlign instead of text-align)

propHandlers-class

This handler deals with class names and enables you to pass either a simple string or an array as the class name list.

propHandlers-attr

With this handler, you can specify some attributes that will be set by calling the setAttribute method on the node.

propHandlers-prop

This handler lets you directly assign some properties of the node.

propHandlers-ref

This is a very special prop which you can use to get the real DOM node. You need to pass a callback to receive the reference. For example:

HUI('input', {
    ref: (inputElement) => {
        console.log(inputElement);
    }
});

Please note that the callback will receive undefined when the element is destroyed, so be careful if your callback uses the reference directly.

HUI.noCmpProps

This is an array of strings telling the prop names that don't need comparing. (That is, any prop whose key is in this array will be always considered changed in comparing process.)

HUI.createStore

This method creates a new store and returns it. You don't need to know this method in most cases, but you should know the store objects it returns.

Store Object

Each store object stores some value pairs. The store argument and the context argument you receive in description methods are all store objects. A store object has the following methods for you to manage the values stored in it:

store.get

function get(key: any): any;

This method lets you get the value matching the given key.

store.set

function set(key: any, value: any, force?: boolean): this;

This method lets you set the value matching the given key. You can also pass a boolean as the third argument to tell the method that this is a new value anyway.

store.setter

function setter(key: any, force?: boolean): (value: any) => void;

This method returns a setter for the given key. You can pass a force update flag to it as well, which will later be passed to the set method. One use case is passing a store setter as a ref prop.

store.setSome

function setSome (pairs: object, force?: boolean): this;

This method enables you to set multiple value pairs together. It invokes store.set internally with the given force flag.

store.toggle

function toggle (key: any): this;

This method toggles the value matching the given key.

store.inc

function inc (key: any, addition?: any): this;

This method adds the given addition to the matching value. (Default addition: 1)

store.push

function push (key: any, ...items: any[]): this;

This method adds the given items to the end of the matching array.

store.unshift

function unshift (key: any, ...items: any[]): this;

This method adds the given items to the start of the matching array.

store.slice

function slice (key: any, start: number, end: number): this;

This method slices the matching array from start to end.

store.splice

function splice (key: any, start: number, deleteCount?: number): this;
function splice (key: any, start: number, deleteCount: number, ...items: any[]): this;

This method deletes some elements of the matching array and if necessary, adds some new items to it. (If there are only two arguments provided, then all the elements since start will be deleted.)

store.handle

function handle(name: any, handler?: null | (this: Store, ...args: any[]) => any): this;

This method sets the handler of name if handler is not falsy, or otherwise deletes it. The handler should receive arguments appended to store.trigger and handle the action. (The this pointer of handler will be bound to the store so that you can interact with it by calling methods like this.set.)

store.getHandler

function getHandler (name: any): undefined | (this: Store, ...args: any[]) => any;

This methods returns the handler of name.

store.trigger

function trigger (name: any, ...args: any[]): any;

This method invokes the handler of name with appended arguments and returns what it returns. (undefined will be returned if there is no such a handler.)

HUI.defer

function defer(callback: (...args: any[]) => void, ...args: any[]): void;

This method accepts a callback and some optional arguments for it. The callback function will be invoked with those arguments later. More specifically speaking, the callbacks will be invoked after all the components are updated.

One use case is doing DOM manipulations after the DOM objects are completely ready:

// Define a component which renders an auto-focused input
const AutofocusedInput = HUI.define('AutofocusedInput', {
    render(props, store) {
        // Defer the DOM manipulation
        HUI.defer(function () {
            // The input element is in the document now
            store.get('input').focus();
        });
        // Render an input and stores its reference
        return HUI('input', { ref: store.setter('input') });
    }
});

HUI.Fragment

This is a symbol standing for fragments which make it easier for you to render several things without adding an extra wrapper. They are usually useful in JSX usage:

render(props) {
    return (
        <HUI.Fragment>
            <h1>{props.title}</h1>
            <p>{props.content}</p>
        </HUI.Fragment>
    );
}

In non-JSX usage, you may use just arrays instead of fragments to do such things. So, the example above is equal to this in non-JSX usage:

render(props) {
    return [
        HUI('h1', null, props.title),
        HUI('p', null, props.content)
    ];
}

HUI.Portal

This is a symbol standing for portals which let you render something elsewhere. For example:

// Define a dialog window component
HUI.define('DialogWindow', {
    // Declare `on` as a state
    state: ['on'],
    // Handlers
    storeHandlers: {
        toggle() {
            this.toggle('on');
        }
    },
    // Default store value
    defaultStore: {
        on: false
    },
    // Renderer
    render(props, store) {
        return [
            // A toggle button
            HUI('button', { onclick: store.getHandler('toggle') }),
            // A paragraph somewhere else if state `on` is true
            store.get('on') && HUI('p', null, 'Dialog window')
        ];
    }
});

PortalProps.parent

By default, the children of the portal will be appended to document.body, but you can also specify a custom container node.

HUI.tick

function tick(callback: () => void): void;

This is the ticking method which is used internally. It accepts a callback and let it be invoked later. The built-in one uses requestAnimationFrame to do this. You can use your own ticking method to override this to meet your needs.

HUI.frameLimit

This is a number representing the frame time limit in milliseconds. Updates will be sliced according to this. You can set your own value to modify this behaviour. (Default: 15)

HUI.cmp

function cmp (a: unknown, b: unknown): boolean;

This is a comparing method used internally to compare stored values or some other things. A default one is provided which compares the two value deeply and you can override it with yours.