Skip to content
This repository has been archived by the owner on Jun 16, 2020. It is now read-only.

Latest commit

 

History

History
89 lines (70 loc) · 3 KB

introduction.md

File metadata and controls

89 lines (70 loc) · 3 KB

What is mercury.

Below is a comment stolen from a mercury vs cycle ( cyclejs/cyclejs#49 (comment) ) comparison.

Mercury is very component oriented at the root of it. Generally you write applications as a series of components that return a state (the component data at any given point) and provides a render function. The render function knows how the component should be rendered including the dom structure, attributes/values and events/event handlers (known as channels in Mercury).

The following is a quick example that makes a div that can be clicked which will create a new one exactly the same except it has a different data-foo-id attribute value. It is created in the image of a Cycle.js example you can see here ( https://github.com/staltz/cycle/blob/master/examples/simple/simple.js ).

var hg = require('mercury');
var h = require('mercury').h;

function Foo(initialState) {
    return hg.state({
        bars: hg.array(initialState.bars, createBar),
        channels: {
            addBar: Foo.addBar
        }
    });

    function createBar(x) {
        return hg.struct({
            id: hg.value(x.id),
            bar: hg.value(x.bar)
        })
    }
}

Foo.addBar = function addBar(state) {
    state.bars.push({
        id: 2,
        bar: Math.round(Math.random() * 1000)
    });
};

Foo.render = function render(state) {
    return h('div', state.bars.map(renderBar))

    function renderBar(bar) {
        return h('div', {
            'attributes': {
                'data-foo-id': bar.id
            },
            'style': {
                'margin': '10px',
                'background': '#ececec',
                'padding': '5px',
                'cursor': 'pointer',
                'display': 'inline-block'
            },
            'ev-click': hg.send(state.channels.addBar)
        });
    }
};

function main() {
    hg.app(document.body, Foo({
        bars: [{ id: 2, bar: 135 }]
    }), Foo.render);
}

main();

Some of the core ideas are:

  • your entire view is a single complex vtree
  • your entire view state is a single complex immutable object.
  • your rendering function is pure, it takes just the view state (disclaimer: hooks & widgets are not pure).
  • you declare all user input as channels up front in your view state.
  • the view state supports cursors, you can nest components in components.

Mercury is unidirectional because:

  • A DOM event triggers a value to be send to a channel
  • The listener for the channel updates the view state
  • An update to the view state triggers a re-render
  • A new vtree is created
  • diff() and patch() update the DOM.

See more about life cycles here ( https://github.com/Raynos/mercury/blob/master/docs/life-cycles.md ).

Mercury is also a hybrid of functional and imperative, the rendering logic is functional but the updating logic has an imperative updating interface (backed by a stream of immutable objects under the hood).

This gives you an FRP style application written in a way that still feels like its javascript