Giter Club home page Giter Club logo

maquette's Introduction

NpmLicense npmBundleSize build

Maquette

Maquette is a Javascript utility which makes it easy to synchronize the DOM tree in the browser with your data. It uses a technique called 'Virtual DOM'. Compared to other virtual DOM implementations, maquette has the following advantages:

  • It is very lightweight (3.7Kb gzipped)
  • It allows changes to be animated
  • It makes your frontend easy to unit-test

Visit the website for more information.

maquette's People

Contributors

amarcruz avatar buckle2000 avatar doublerebel avatar dylans avatar gmschouten avatar gregorysmithhtx avatar hellozeronet avatar jcfranco avatar johan-gorter avatar jvanoostveen avatar kitsonk avatar levlaz avatar matt-gadd avatar maxpatiiuk avatar molsp avatar paldepind avatar pdfernhout avatar rickhoving avatar subtilior avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

maquette's Issues

Event handler parameter passing

What's the best way to pass an extra argument to the event handler?

Maquette does not allow anon functions. In an another framework (snabdom) I have seen something similar to this:

function handleClick(message) {
  alert(message)
}

function render() {
  return h("div", [
    h("a", {"onclick": [handleClick, "Hello from Item 1!"]}, "Item 1"),
    h("a", {"onclick": [handleClick, "Hello from Item 2!"]}, "Item 2")
  ])

Ps: Thanks for the library, we are big fan on Maquete. Just finished the second site, everything worked well (the only thing missed is dom-reordering support): Distributed messaging site, Homepage and newsfeed of the network

Firefox vs Chrome speed

Hello, I'm looking for a good and fast solution to display large amount of dom elements.

I have created a simple test that similar what I going to do: http://jsfiddle.net/13j1Lfc7/5/

It looks fine in Chrome:

jQuery x 3000 = 657ms
Mithril x 3000 = 935ms
Maquette x 3000 = 226ms

But not that good in Firefox:

jQuery x 3000 = 675ms
Mithril x 3000 = 1098ms
Maquette x 3000 = 1192ms

Is there any way to make it faster?

Thanks!

Routing [enhancement]

Nearly all SPAs today require front end routing.
Mithril does a good job at implementing it while still keeping the library small.
Perhaps there should be a version of Maquette with routing, or, an example of how to use it with a routing library.

Mapping object does not properly handle moving data

The Maquette Mapping#map method does not call updateResult() for a data item that moves from the beginning of the data array to the end.

I created a test case in this fiddle: https://jsfiddle.net/edhager/k675wd9u/. Do the following:

  1. Click the "Modify 1st item" button so the first list item looks like this: "1 (edit 1)".
  2. Click the "Move 1st item to end" button. Notice item "1" moves to the end but loses the "(edit 1)" modification. updateResult() was not called for item "1". Instead, createResult() was called for item "1".
  3. Click the "Modify 1st item" button. Now the first item in the list is "2 (edit 1)" and the last item in the list has returned to "1 (edit 1)". updateResult() was called for item 1 this time.

The problem is this for-loop: https://github.com/AFASSoftware/maquette/blob/master/src/maquette.ts#L1113. It does not loop over the entire length of the keys array which is needed for my test case.

`class` attribute does not work for SVG nodes

Hi,

I've been playing around rendering SVG with maquette (awesome that it handles namespacing automatically btw!) and have discovered that setting the class attribute on an SVG node doesn't work, but setting classes in the vnodeSelector or using the classes attribute does.

For example:

h("g", { class: "test" }) // => <g></g>
h("g.test", "") // => <g class="test"></g>
h("g", { classes: { test: true } }) // => <g class="test"></g>

It looks like this is because SVG nodes support updating the classList attribute (set from the vnodeSelector and classes) but not the className attribute (set from the class attribute). Is there a reason that className is used here? - could it be changed to classList or have an exception added for SVG nodes?

Thanks!

How can i dynamically add remove event handlers

This was the fastest in the virtual dom benchmarks, cheers for that! I was wondering if i could dynamically add and remove event handlers. In the examples i saw you can write inline handlers, but there should be a way to remove them or it would start introducing memory leaks, right?

Create a performance regression benchmark

We do not want to inadvertently cause the performance to drop when making modifications to maquette. Therefore we need a representative benchmark that we can run to see the performance impact of each change.

Support for IE9

I can't seem to find where you explicitly indicate browser support, but I have noticed that you cannot currently support IE9 due to the scheduleRender() utilising requestAnimationFrame for providing rendering.

Have you considered supporting some of the older browsers (specifically IE9)?

Event Delegation

Context: We have been prototype using Maquette with dgrid considering using it for the next major version. We have found a few things that we see as challenges for us in adopting it. @kfranqueiro, @maier49, and @edhager have been working on the prototyping.

Problem Description

First, apologies, that this might be more of a support item than an issue with Maquette, but since this was part of the challenges with our prototype, I figured I would bring it up here.

There appears to be no easy way of utilising event delegation with Maquette. For example, if I have a <div> that contains 10 <button> elements, I might want to put a listener on the <div> and allow event bubbling to occur when the <button> is clicked to actually handle the event. In a situation where the application directly manipulates the DOM, it would be able to determine what action to take because it placed each of the DOM nodes and knows what part of the DOM relates to the application logic.

In a VDOM situation, not knowing about the DOM is most compelling advantage.

Impact

The specific impact to dgrid is that, with thousands of rows, it is often easier to put a listener higher up the DOM and allow event bubbling to occur, meaning one listeners needs to be attached and can manage thousands of different scenarios. In order to go to a 1:1 mapping of VNode to listener would be a significant amount of refactoring.

Outside of that, we see that the general use case of being able to harness the power of event delegation and bubbling in a way the integrates well with Maquette as a compelling feature.

Discussion

We might be missing something around the intent of Maquette and are "doing something wrong" and there is already a reasonable solution.

Outside of that, we think there might be two approaches to solving this use case:

  • Listeners could hold references to VDom generated and then walk the VDom looking for matching DOM nodes that have been added to the VDom. This seems like a lot of work and likely would not be efficient.
  • Maquette could potentially intercept DOM events and decorate them in some fashion (e.g. either decorate the DOM event with a reference to the VDom node or only decorate the event if the key property was supplied in the original VNode)

Polyfill change in 2.3

The polyfill behaviour has changed in version 2.3.

Previously, the polyfill would modify the global scope, now the polyfill modifies window for requestAnimationFrame. The problem comes in that maquette.ts refers to it in the default scope (instead of window.requestAnimationFrame). This is fine in environments where global === window, but fails in other environments (e.g. NodeJS with jsdom where global !== window).

My suggestion is that maquette.ts and maquette-polyfills.ts are consistent in the way they work in these unexpected situations.

Certain Array Mutations Inefficient

Context: We have been prototype using Maquette with dgrid considering using it for the next major version. We have found a few things that we see as challenges for us in adopting it. @kfranqueiro, @maier49, and @edhager have been working on the prototyping.

Problem Description

Certain VDOM array mutations appear to be inefficient. Specifically given an array of VNodes: [ A, B, C, D, E ] and moving E to before, example B causes B, C and D to be touched.

@kfranqueiro wrote a CodePen that demonstrates the issue. It highlights any nodes that are "touched" during the DOM modifications. If you move an item up the array order (e.g. from index 9 to 1) or if you click the Move last item to top button.

Impact

Why we are concerned about this is that dgrid is often used in situations where thousands of rows might be rendered on screen of a virtual data set of millions of records. We virtually page rows in and out of memory and also render them at different points. Mutations to the order of the rows can occur via many different mechanisms, including user input, server side updates sent to the client, or application logic. We therefore care greatly about any inefficiency in the mutations of lists.

Discussion

There maybe an obvious improvement to the mutation detection algorithm.

An the other hand, as we discussed with our wider team, we acknowledged that any change detection algorithm is likely to have some sort of inefficiency. One thought we had, is that if in the properties of the VNode which has an array of children, to provide an optional hint around the type of mutation performed. Maquette could then use that information to more efficiently detect any mutations. We haven't thought through the details of what this hinting might look like, but it seems like it could be an effective way of making Maquette even more efficient.

[Question] Is it possible to create a virtual dom based on an existing dom element

I was wondering if there is a way to create a virtual hyperscript node from an existing element. For example:

h(document.getElementById('exists'), {properties}, [childrens])

I found that I could init a node without using h() by returning the expected result, for example:

    {
      vnodeSelector: 'input',
      properties: {
        type: 'text',
      },
      text: undefined,
      domNode: document.getElementById('exists')
    },

I thought that by specifying the domNode it won't be appended, but it's anyway.

This would be helpfull if you want to add features to an existing dom element, but maybe it's out of scope. Thanks.

Maybe related to #53

npm install warnings

Here are some warnings from doing an install today. Should any of these npm packages that Maquette depends on be updated?

maquette$ npm install
npm WARN deprecated [email protected]: TSD is deprecated in favor of Typings (https://github.com/typings/typings) - see DefinitelyTyped/tsd#269 for more information
npm WARN deprecated [email protected]: Consider jsdom-global instead. https://www.npmjs.com/package/jsdom-global
npm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.
npm WARN deprecated [email protected]: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^4.0.0.
npm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.
WARN engine [email protected]: wanted: {"node":">= 0.10.0 <= 0.11.0"} (current: {"node":"4.3.0","npm":"2.14.12"})
npm WARN deprecated [email protected]: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^4.0.0.
npm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.

First-class support for progressive enhancement?

I have been using virtual-dom for several months, before discovering maquette. As mentioned in your blog post, this module appears to use similar hypersrcipt implementation, while giving first-class support for PE?

But looking at the introduction:
http://maquettejs.org/2015/02/28/Progressive-enhancement.html

and source code at:
http://maquettejs.org/tutorial/01-intro.html

I still haven't fully understand what happens when you do a mergeDom.

To put it in simpler context, let's say, we have this render template:

h('body', [
  h('h1', 'welcome')
]);

which server-rendered and output as:

<body>
  <h1>welcome</h1>
<body>

What does it take to swap it with a maquette-rendered dom using the same template? What happen when you trying to replace them, do nothing happen, or do everything get replaced like replaceChild.


As a side-note: just how similar are maquette and virtual-dom in terms of their hypersrcipt implementation?

https://github.com/Matt-Esch/virtual-dom/tree/master/virtual-hyperscript

I am wondering if I had to rewrite https://github.com/nthtran/vdom-to-html to support maquette.

Optionally allow function updates

Before all, I'm not aware of all performance issues, so take the associated PR as an example of what can be done, not the way to do it. Also, it needs an option in the maquette.createProjection factory to be effective.

So I've made it possible to change the event handlers. It seems that this modification does not have a lot of consequences on performances, it adds a property on the DOM Node to store the original handler, so eventHandlerInterceptor is called only once.

In case of the PR associated with this issue is accepted, I'll sign the CLA.

Support HTML string

Is it possible to pass HTML string to maquette for rendering instead of hyperscript?

Maquette Tutorial error

The Maquette tutorial in your website is not working. There are errors in the gutter of HTML frame, in http://maquettejs.org/tutorial/01-intro.html:

 Expected an identifier and instead saw '<'.
 ...

This is a fragment of error in Chrome console:

  MutationObserver fired          workbench.js:120
  http://maquettejs.org/tutorial/bower_components/ace-builds/src-noconflict/mode-html.js  Failed to load resource: the server responded with a status of 404 (Not Found)

thanks.

Returning a VNode without classes and then classes causes an exception

Given the following:

const projector = createProjector({});
let count = 0;
function render() {
    count++;
    if (count === 1) {
        return h('div');
    }
    return h('div', { classes: { foo: true, bar: true } });
}

projector.append(document.body, render);
projector.scheduleRender();

I get the following error:

TypeError: Cannot read property 'classes' of undefined
  at updateProperties  <node_modules/maquette/dist/src/maquette.ts:472:43>
  at updateDom  <node_modules/maquette/dist/src/maquette.ts:761:14>
  at Object.update  <node_modules/maquette/dist/src/maquette.ts:779:6>
  at doRender  <node_modules/maquette/dist/src/maquette.ts:1106:21>

It generally appears to be related to assuming previousValue will actually be available. It seems that several other properties can run into this as well.

Exit / Enter anim triggered on reordering

I want to create real-time update list of threads, the enter/exitAnimation works well when new comes in or old removed, but if one of the threads position changed then it fades off/fades in every other element in the list:

http://codepen.io/anon/pen/GpbYzz?editors=001 (by clicking on an element its moves to top in the list)

I don't expect animated position change (but would be nice), fade out from old position and fade in to new position could do.

Is there any easy way to solve this?

Allowing DOM Elements as part of VDOM

Sorry to be overly verbose today, but another part of team (@pottedmeat) and I were discussing another use case we will likely encounter.

As we transition to a virtual DOM, it maybe challenging to have all components move to a virtual DOM. While a Projector can manage just a portion of the DOM, allowing other code to perform as normal, if we wanted to contain a "legacy" component in the VDom, we don't see a way we could do that at the moment.

One solution we thought of, would be to allow a VNode children to contain a Element in the array and Maquette place that Element appropriately in the DOM with no further styling. We would create Elements for our legacy components and instantiate them, passing them back as part of the render response. Again, we may simply be missing a solution.

Preventing rerendering sometimes in event handlers?

Sometimes you know that a rerender is not needed after an event handler runs. A common use case involves keyboard events like onkeydown in a widget where you can ignore them unless a specific key is pressed (like the Enter key). Another use case is for mouse events like onmouseenter where only occasionally you might to change the GUI like with a popup for a specific element in big grid (perhaps only after the user has dwelled over a location for some time like if they are quickly moving the mouse across a grid). Potentially, moving the mouse quickly across a grid could otherwise generate dozens of spurious rerenders per second. So, what is the recommended way to prevent rerendering by Maquette once an event handler has been called?

It seems to me one possible option with Maquette currently would be to create a new eventHandlerInterceptor function for a projector that perhaps checks a global flag set before the event handler us called. Would that be the recommended approach? It seems a little ad-hoc to me though for what may be a common use case. Still, that might be the best for perfomance if most users don't need this. If so, it might be worth providing an example of doing that in the cookbook section of the documentation.

Right now, by default, it seems like Maquette commits to a rerender before the event handler code is called -- perhaps to avoid the overhead of a try/finally? And projectors can have rendering stopped and resumed, but as I read the code, have no function to unschedule a render (not saying they necessarily should). So, it does not seem to me this can be done without setting a new eventHandlerInterceptor for a projector.

Here is how Mithril does that, also involving a global variable, but there might be better ways (perhaps even involving using the event itself somehow) -- and Mithril's approach runs the risk of breaking the rerendering process by a missing endComputation call like in an exception handler:
https://lhorie.github.io/mithril/mithril.redraw.html

In any case, thanks for the great library. I'm having fun playing with it. :-)

The distinguishable rule seems limiting

Due to the distinguishable rule I can't do stuff like this:

h('div', [
  h('span', ['Hello world']),
  h('span', ['Oh no!'])
]);

That seems very limiting and other virtual DOM libraries does not have the same restriction.

The tutorial was quite fun :)

Changelog

Is there list of changes between versions?

Examples/gallery

Show transitions by using a digit flipping alarm clock example

Updating properties.classes not being reflected in the DOM

Given the following:

import { createProjector, h, VNode } from 'maquette/maquette';

const node = h('dojo-panel-tabbed', {
    id: 'tabbed-panel'
}, [
    h('ul', {}, [
        h('li', { classes: { active: false }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ]),
        h('li', { classes: { active: true }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ]),
        h('li', { classes: { active: false }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ]),
        h('li', { classes: { active: false }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ])
    ])
]);

function render(): VNode {
    return node;
}

const projector = createProjector({});

projector.append(document.body, render);

const next = document.getElementById('next');

next.addEventListener('click', (event) => {
    console.log('before', node.children[0].children[1].properties.classes, node.children[0].children[2].properties.classes);
    node.children[0].children[1].properties.classes['active'] = false;
    node.children[0].children[2].properties.classes['active'] = true;
    console.log('after', node.children[0].children[1].properties.classes, node.children[0].children[2].properties.classes);
    projector.scheduleRender();
});

Maquette does not appear to notice changes to changes to already rendered VNodes. The classes do not change if a VNode is updated. I maybe missing something, but is it not possible to reuse VNodes?

To explain a bit, where I ran into an issue trying to create a tabbed component, where the VNodes for the tab bar were always regenerated, but the tab's contents would only be calculated for the tab coming into view, but then updating the classes of any tab contents already rendered. That way, if the tab were to come back into view, but its content had not changed, it would be as simple as adding a class back.

I have noticed though if I dropped a VNode out of one render and then return it later, the VNode will be full parsed.

I even tried to "reuse" just VNodeProperties, but that also appeared to exhibit the same behaviour, that if it was present from one render to the next, changes to its properties were not deeply noticed.

I can get it to work, only if I do something like this:

import { createProjector, h, VNode } from 'maquette/maquette';

let clicked = false;

function render(): VNode {
    return h('dojo-panel-tabbed', {
        id: 'tabbed-panel'
    }, [
        h('ul', {}, [
            h('li', { classes: { active: false }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ]),
            h('li', { classes: { active: !clicked }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ]),
            h('li', { classes: { active: clicked }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ]),
            h('li', { classes: { active: false }, key: {} }, [ h('div.tab-label', [ 'tab 1' ]), h('div.tab-close', [ 'X' ]) ])
        ])
    ]);
}

const projector = createProjector({});

projector.append(document.body, render);

const next = document.getElementById('next');

next.addEventListener('click', (event) => {
    clicked = true;
    projector.scheduleRender();
});

In my opinion, this is rather surprising behaviour and means that it is difficult to not fully recalculate the whole of the virtual DOM on every render, which doesn't properly represent the application state, as from render to render, only small changes are made to the VDOM.

Ability to manage Events and Schedule Rendering

Context: We have been prototype using Maquette with dgrid considering using it for the next major version. We have found a few things that we see as challenges for us in adopting it. @kfranqueiro, @maier49, and @edhager have been working on the prototyping.

Problem Description

In certain cases, the application is aware that certain DOM Events of which it has listeners for do not equate to any mutations of the DOM, but currently Maquette will always schedule a render on any listener provided via the VDOM.

Also, we are unsure if the intent of Maquette to potentially manage these events. While the code documents the projector option of eventHandlerInterceptor the actual code will always overwrites this option with one that always schedules a render. (We suspect this is a defect)

@pdfernhout brought this up in #31, but we have had some further experience with this.

Impact

We noticed in our prototypes a significant amount of "jank" when the list was scrolled. Part of that "jank" we us actually some coding issues in our implementation and we were able to get the performance to improve to a great degree, but we highly suspect that in certain situations under certain environments, a schedule render for every scroll event would make the performance unacceptable.

Discussion

We suspect the eventHandlerInterceptor is potentially a defect.

On the wider topic though which was discussed in #31. The application "knows" that only an aggregate scroll movement of X actual would cause the DOM to need to be updated and that often takes 10x the DOM events to equal something the application actually cares about, so for 9 of those events, we have recalculated the whole of the VDOM which results in a noop for actual DOM mutations. The feeling I get from the discussion in #31 was "let's discuss real problems, versus potential ones" which, to me, makes a lot of sense. I think we have come up with a use case though that can cause real problems. Implementing a custom eventHandlerInterceptor could resolve this issue (or as suggested in the other ticket, a custom Projector). In both those cases though, it would mean we would have to become the "experts" at VDOM versus and something we are reticent to do.

We hope given a compelling use case, we can find a way to improve Maquette to be able to manage DOM events bubbled up to the application more efficiently.

Feature Request - Subsuming DOM

@pottedmeat and myself were having a discussion last night and we have identified a use case that we were wondering what the Maquette team's opinion was.

As we are all aware, quick application startup, especially on mobile, is important. So lets say we were able to calculate the state of the DOM of a complex web app server side (e.g. using Maquette with JSDom) and then were to send that to the client as our initial page. We would then load maquette and replicate the Projector and then load the rest of our components, set their state and we would then be ready to render client side.

We could of course do that now, but my understanding is that the Projector would only be able to detach the existing node and replace it with one it calculated and then from that point you would get the efficiency of DOM diffing on subsequent applications.

When in reality, the pre calculated initial state of the DOM I sent from the server would actually be the initial calculated structure (minus maybe some event handlers).

I was wondering what the thoughts are about enabling a feature (maybe even as a seperate module) that creates a Projector that can subsume a set of DOM, essentially matching the VNodes up with existing DOM and then projecting from there.

Using TypeScript instance methods as event handlers?

What is the best way to use methods of TypeScript class instances as Maquette event handlers?

=== More details

Maquette requires event handlers to always be the same exact function for performance reasons, prohibiting code in a render method in a TypeScript object like:

h("input", { value: this.myData, onchange: this.setMyData.bind(this) ] }) // won't work

Trying to do that will produce this warning:

Error: Functions may not be updated on subsequent renders (property: onclick). Hint: declare event handler functions outside the render() function.

The Maquette todoComponent example shows a certain style of defining objects where the object itself has methods are specialized for the specific object and its fields as a closure held onto by the object.

That approach works, but it requires every component to have a closure for each of the callback functions, which clashes with a more object-oriented style of programming using classes with methods. It is also potentially inefficient, because if you had a thousand editable items to display, they each would need a closure for each of their event handling methods (rather than sharing methods on a common prototype).

If the Maquette ToDo example was rewritten using TypeScript classes, a challenge would become obvious. How do you easily connect methods of a typical TypeScript object to event handlers when "this" in an event handler is defined by default as the DOM node receiving the event?

That is a very common case which in Mithril is typically handled just by using bind as in the first non-working example (admittedly, at a performance penalty).

Working within the current restriction on event handlers, it could make application development easier if Maquette supported specifying what "this" should be in an event handler, as "this" is otherwise apparently the DOM node getting the event. I don't know the best way to do that, but here are some possibilities.

One way is perhaps passing an array (or other object) as an event handler that could be used internally in Maquette with apply for event handlers, like so:

h("input", { value: this.myData, onchange: [ this, this.setMyData, "Extra1", "Extra2" ] })

But that would be creating a new array on every render.

Another approach could be to pass a value in for "this" as a field for the properties which Maquette could use in apply like so:

h("input", { value: this.myData, onchange: this.setMyData, _this: this })

That way might be the most efficient. It is a bit limiting, but in practice I doubt that limit would be a big issue. A generalization of that approach could be to pass in an array of arguments to be applied to any event handler. Because event handling is unlikely to be performance critical, doing a check to see if there was data to apply on a function would probably not slow things down -- although it would add a small bit of library code complexity at a huge savings for application code complexity.

There are other approaches I can think of, like functions that lazily cache bound references to methods in the object somehow in a _cachedMethods field, or perhaps managing a global WeakMap of bound functions associated with instances and their methods. Those have their own drawbacks. And they have overhead at rendering to do lookups. Still, it is common to refer to "event.target.value" in handlers (or similar for "checked" and other attributes), and it could be useful to have a wrapper function for that such as Mithril's "withAttr" function. So, I could imagine creating a global event handler tracker that also resolved events to their values which might be worth using especially for that side benefit.

Perhaps there is some other clever way to handle setting up Maquette event handlers with TypeScript class instances?

Converting the TODO example to idiomatic TypeScript using a class for todoComponent would be a way for Maquette designers to wrestle with this design issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.