Created
May 31, 2015 21:31
-
-
Save cdaringe/928eccc55121ded4c4d5 to your computer and use it in GitHub Desktop.
rendered implementation discussion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Solutions to manage the rendered state *better* | |
1. make `rendered` a bool member of `props`. manage rendered bit on your own | |
- weaknesses | |
- it's a pain for the user to have to explicty set `this.rendered` on every render and remove call, despite being a single bit | |
- it get's tricky if you extend muliple view definitions. If you manually set the rendered bit in each child's render function, you get duplicate 'change:rendered' events | |
2. make `rendered` a bool member of `props`. wrap user defined render()s to contain their render() fn AND logic to update `rendered` | |
- weaknesses | |
- again, each version of render() in the proto chain execs the fn and duplicate change events on the `rendered` prop occur | |
3. make `rendered` a bool member of `derived`. introduce {session: _rendered: [...]}, which the module uses internally for setting `rendered` state indirectly. this implementation also wraps the user provided render/remove functions and sets the _rendered bit, similair to the solution above. the `rendered` prop is dependent on and listening to the `_rendered` prop. Due to the caching nature of derived properties, a `changed:rendered` event only gets fired once, regardless of how many times parent View methods update `this._rendered = true` on a render() call. example: | |
```js | |
// &-view | |
_setRender: function(obj) { | |
Object.defineProperty(obj, 'render', { | |
get: function() { | |
return this._render; | |
}, | |
set: function(fn) { | |
this._render = function() { | |
fn.apply(this, arguments); | |
this._rendered = true; | |
return this; | |
}; | |
} | |
}); | |
}, | |
... | |
// ex | |
// recall that in this implementation, every call to a render function, regardless | |
// of whether View was extended or not, is going to set `view._rendered = true;` | |
var ChildView = AmpersandView.extend({ | |
render: function() { | |
AmpersandView.prototype.render.call(this); // third render call | |
t.ok(true, 'child view render called'); | |
} | |
}); | |
var GrandChildView = AmpersandView.extend({ | |
render: function() { | |
ChildView.prototype.render.call(this); // second render call | |
t.ok(true, 'grand child view render called'); | |
} | |
}); | |
var view = new GrandChildView({ | |
template: '<span></span>', | |
el: document.createElement('div') | |
}); | |
view.on('render', function(view, value) { | |
++renderCount; //=> 1, not 3. phew. | |
t.ok(true, 'view `render` event happened on `render()`'); | |
}); | |
view.render(); // first render call | |
}); | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment