Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify mounting to just be sugar over m.render #2280

Closed
dead-claudia opened this issue Nov 4, 2018 · 2 comments
Closed

Simplify mounting to just be sugar over m.render #2280

dead-claudia opened this issue Nov 4, 2018 · 2 comments
Labels
Type: Breaking Change For any feature request or suggestion that could reasonably break existing code Type: Enhancement For any feature request or suggestion that isn't a bug fix

Comments

@dead-claudia
Copy link
Member

dead-claudia commented Nov 4, 2018

Updates

This is part 3 of a broader proposal: #2278.

This is the second major step of how Mithril would become a lot more component-driven and less component-oriented. My goal here would be to further encourage component use over definition, by changing m.mount/m.redraw to accept a view function to invoke on each redraw, rather than a component to render. This has a few benefits:

  • It simplifies the concept to just "render this view to this element on each redraw"
  • It decouples the vnode representation from the underlying algorithm, for easier mainenance.
  • This would make it much easier to teach, since it's now literally just a thin layer of sugar over m.render.

There are a few other things I'd do:

Here's what the mounting and redrawing would change to.

I'd consolidate m.redraw and m.mount into a single file as per below.

I do have a few notes:

  • This depends on Subtree rendering proposal #1907
  • This sets the stage for Feature request: Custom renderer support #2215, since render is passed via parameter instead of directly instantiated
    • Most UI frameworks, including the native ones in Windows, Android, and iOS, use arrays for children, not doubly linked lists. This has completely different performance implications, so I can't use the same renderer/reconciler for both.
  • This drops the dependency on Vnode, so it's a little more portable and better decoupled.
// In `index.js`
var createRedraw = require("./api/redraw")
var redrawService = createRedraw(
	typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout,
	renderService.render
)

m.mount = redrawService.mount
m.redraw = redrawService.redraw

// In `api/redraw.js`
"use strict"

module.exports = function(schedule, render) {
	var callbacks = []
	var rendering = false

	function sync() {
		if (rendering) throw new Error("Nested m.redraw.sync() call")
		rendering = true
		for (var i = 0; i < callbacks.length; i += 2) {
            try {
                render(callbacks[i], (0, callbacks[i + 1])(), redraw)
            } catch (e) {
                if (typeof console !== "undefined") console.error(e)
            }
        }
		rendering = false
	}

    //60fps translates to 16.6ms, round it down since setTimeout requires int
	var delay = 16
	var last = 0, pending

    function redraw() {
        pending = pending || schedule(function() {
            pending = null
            last = Date.now()
            sync()
        }, delay - last - Date.now())
	}

    redraw.sync = sync

	return {
		redraw: redraw,
		mount: function(root, view) {
            if (view != null && typeof view !== "function") {
                throw new Error("`view` must be a function")
            }
            var index = callbacks.indexOf(root)
    		if (index > -1) callbacks.splice(index, 2)
            if (view != null) { view = view(); callbacks.push(root, view) }
            render(root, view, redraw)
		}
	}
}
@dead-claudia dead-claudia added Type: Breaking Change For any feature request or suggestion that could reasonably break existing code Type: Enhancement For any feature request or suggestion that isn't a bug fix labels Nov 4, 2018
@dead-claudia dead-claudia added this to the post-v2 milestone Nov 4, 2018
@StephanHoyer
Copy link
Member

So it would be like?

m.mount(document.body, () => 'Hello World')

I had this once in mithril-query but dropped the support due to closure components.

So this would definitely a breaking change.

Other than that, I would support this change.

@dead-claudia dead-claudia changed the title Simplify mounting to just use m.render directly Simplify mounting to just be sugar over m.render Nov 5, 2018
@dead-claudia dead-claudia removed this from the post-v2 milestone Nov 13, 2018
@dead-claudia
Copy link
Member Author

See this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Breaking Change For any feature request or suggestion that could reasonably break existing code Type: Enhancement For any feature request or suggestion that isn't a bug fix
Projects
Status: Completed/Declined
Development

No branches or pull requests

2 participants