-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Separate attributes into hook #3846
Conversation
What's the use case? |
I had a list collection view that allowed you to select multiple items. The selected state was toggled by a css class on the item view's class ItemView {
className() {
return this.model.get('active') ? 'active' : '';
}
} I specifically want the |
But this changes the way the view attribute methods are called, from being only invoked once at instantiate-time to now potentially being invoked many times throughout the view lifecycle with different state. In my experience with Backbone you almost never want I like it in theory, but I wonder if it opens the door to too big of a breaking change in the way View works. |
I'm actually trying to move into the opposite direction. I see all of the event listeners with element specific update logic as duplication that should be in the template. I'm hoping with iDOM to never have to write another one. 😄 The only parts I can't put into the template are the root |
Sure, but if you're getting rid of the jQuery parts of View in favor of iDOM, you don't need In my experience with virtual DOMs you usually compute the dynamic attributes in your render method at runtime. You can move that logic to your own methods if you want, but there shouldn't be a need to put this on View. Closing, in lieu of a better example. |
They're still needed as the root element is managed by Backbone. Rendering with iDOM isn't any different than the way we render with jQuery, it's just much faster.
That's for template based vDOMs, where the root element is defined in the render function. Can't do that with Backbone, unless I want a bunch of wrapper DIVs (ick).
#3255, and (if you ignore the discussion about Views without root elements) marionettejs/backbone.marionette#2357 (comment). |
I don't understand why this would be. You're only managing a small part of your app with a virtual dom? Why?? This is backwards from most vdom solutions I've seen. Mostly it's VDOM top of tree, then mutable leaves when you need Google Maps or a jQuery plugin or something.
vdom isn't magic. It's faster for certain types of changes (particularly ones that cause reflows), but slower for others (ones where you know what you're going to change ahead of time). Throwing a subtree of your app in a vdom isn't going to magically speed it up. The biggest gains tend to come from change-heavy apps that modify many parts of the tree at once.
I think we might be using different terminologies here. I'm talking about something like this: export default App = React.createClass({
render() {
const {isActive} = props;
return <div className={cx({active: isActive})} />
}
});
Agreed. That's what I'm arguing against.
#3255 isn't super compelling, the comments are pretty spot on. I see Backbone Views as orthogonal to VDOM. Backbone Views have a two-stage creation process: instantiation ( |
I really don't see the issue with this PR. It does nothing to enforce a new rendering strategy, nor is it breaking.. Not adding this however does very little in preventing people from poor rendering strategies. A quick search on stack overflow and it's easy to find people reproducing the attributes code inside their renders to do just that anyways. |
I think we're getting off topic here. I'd be happy to discuss how I'm trying to integrate iDOM on gitter.
@jashkenas comment on #3255 is pushing towards a wrapper DIV. This PR gives the dev a way to get the attributes as they should be now. And this isn't necessarily tied to a re-render. class View {
initialize() {
this.listenTo(this.model, 'change', this.updateAttributes);
}
className() {
return this.model.get('active') ? 'active' : '';
}
attributes() {
return {
data-image: this.model.get('image')
};
}
updateAttributes() {
this.$el.attr(this._attributes());
}
} Answering:
Because it's a Backbone app. I'm using iDOM as a templating language, nothing more. All of the core philosophies of Backbone still apply, including
Exactly. The
A lot of people use
I'm definitely not trying to make Backbone more like React as in marionettejs/backbone.marionette#2357. But one of the solutions to it is to make the root |
But it implies a use case that is different. Is this something we want to support? If it's towards a better vdom solution, let's figure out the answer holistically.
But it's certainly not faster (or magic ✨) compared to just adding a class directly. |
This is wholly separate from vDOM. Backbone currently treats the root element as static, with attributes only being set at instantiation time. This pushes us to using wrapper DIVs, per #3255 (comment). I really dislike that. This isn't trying to tackle mutating the
Ignoring the magic discussion, this means we already support mutating the root element's attributes – just indirectly. This PR gives a generalized method to grab all of the attributes with our custom precedence rules ( |
The attributes are still only set by the library once, so I don't see how this could break an app.
@akre54, the Backbone wrapping element defined outside of the template presents its own set of challenges (for good reasons); why hold back a backwards-compatible improvement that could make dealing with that fundamental tenet of Backbone a little more elegant? |
A small change to allow subclasses access to the attributes that should be on the view. This is particularly handy when there are dynamic attributes...
Something like:
Notice the attributes update code is just copied pasted from the Backbone source.