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

How to work with different DOM? #348

Open
user471 opened this issue Jan 4, 2016 · 9 comments
Open

How to work with different DOM? #348

user471 opened this issue Jan 4, 2016 · 9 comments

Comments

@user471
Copy link

user471 commented Jan 4, 2016

Deku has this Actions abstraction https://github.com/dekujs/deku/blob/master/src/diff/index.js#L11
Does it mean you can work with any dom and not just html?
For example, I want to use deku with pixi.js library which has its own DOM.
If it's possible, is there any example how can I do it?

@user471 user471 changed the title How to work with different DOM. How to work with different DOM? Jan 4, 2016
@anthonyshort
Copy link
Owner

Yeah the diff functions just return an array of those actions. You can see how it's used in dom/patch.js. I think we'll need to expose the diff function if we're not already. Then you just need to make your own patch function.

I don't know much about pixi so I won't be that much help with that exactly.

@user471
Copy link
Author

user471 commented Jan 4, 2016

Then you just need to make your own patch function

Why do I need my own patch? Can't I just refined only actions? Patch logic should be the same, go throw nodes and apply actions.

@anthonyshort
Copy link
Owner

Maybe I'm not following exactly what you meant. I thought you meant you wanted to create your own custom renderer. If you just want to apply it to some random piece of DOM, we could expose both the patch and diff functions and you can just use them on anything.

@user471
Copy link
Author

user471 commented Jan 4, 2016

I am thinking about this ideal scenario

Pixi has its own object model, something like this

var pixiNode = new Container();
pixiNode.addChild(new Text("123"));
pixiNode.addChild(new Sprite("img.png"));

I can create virtual dom.

var vNode = element('container' [
  element('text', {text:"123"}),
  element('sprite', {img:"img.png"})
])
var vNodeNew = element('container' [
  element('text', {text:"456"}),
  element('sprite', {img:"img.png"})
])

then I would do something like this

var diffs = diff(vNode, vNodeNew);
patch(pixiNode, diffs); //it would change text "123" to "456" in pixiNode

Ideally, I would need to implement only two parts
vNode to pixiNode converter

pixiNode = createElement(vNode);

and patch Actions, something like this

Actions = {
    setAttribute = function(pixiNode, name, value){
         ...
    }
    ....
}

All other logic should be the same as for html, so it could be reused.

Is deku support something like this?

@anthonyshort
Copy link
Owner

Yeah you should be able to do that. I'll reply with a bit more detail later today. You would still just need a custom patch function that takes the array of Actions and makes the appropriate changes to the pixiNode. That's essentially creating a Pixi renderer for Deku :)

@andrewn
Copy link

andrewn commented Jan 5, 2016

I also want to do this, either with Pixi.js or some other scenegraph-based library like Two.js or Fabric.js. So more detail on the approach would be great!

@anthonyshort
Copy link
Owner

This should be fairly straightforward, you'll just need to do something similar to the DOM renderer. You might have an API like this.

// This will function roughly the same as the DOM root element
let pixiNode = new Container()

// Create a function to render the lastest vnode
let render = createPixiRenderer(container)

You can follow the DOM renderer pretty closely, you'll need:

  • A way to create new pixi nodes from a vnode. Similar to createElement
  • A way to update an existing pixiNode using actions from the diffNode function
  • A way to create a render function that takes a vnode

The update function would work something like this:

import {diff} from 'deku'
const {Actions, diffNode} = diff // This is the API we'd need to expose

export default function patch (pixiNode, action) {
    Actions.case({
      setAttribute: (name, value, previousValue) => {

      },
      removeAttribute: (name, previousValue) => {

      },
      insertBefore: (index) => {

      },
      sameNode: () => {

      },
      updateChildren: (changes) => {
        changes.forEach(change => {
          Actions.case({
            insertChild: (vnode, index, path) => {
              pixiNode.addChild(new Text(vnode.nodeValue))
            },
            removeChild: (index) => {

            },
            updateChild: (index, actions) => {

            }
          }, change)
        })
      },
      updateThunk: (prev, next, path) => {
        // If you want lazy-rendered vnodes
      },
      replaceNode: (prev, next, path) => {

      },
      removeNode: (prev) => {

      }
    }, action)
}

It shouldn't be too hard to put together. I'll make sure you can access the diff in the next release.

@anthonyshort
Copy link
Owner

Making a render for Two or Fabric would be similar. I might try getting something like Two working as it should be fairly simple.

@user471
Copy link
Author

user471 commented Jan 9, 2016

Thanks.

I'll make sure you can access the diff in the next release.

When would it be?
Also, according to http://vdom-benchmark.github.io/vdom-benchmark/ previous version of Deku was slower than other libraries.
Were there any perfomance improvements in 2.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants