ChatGPT解决这个技术问题 Extra ChatGPT

Backbone.View "el" confusion

How should a view's el be handled? It has to be set, otherwise events don't fire (see here).

But should it be an element that is already on the page? In my app, I render a (jQuery Templates) template into a Fancybox. What should the el be in that case?

I thought - I am the only one fiddling with the el thing.
el is like gf . nobody can understand them fully .

D
Darryl Hein

A views el is where all the event binding takes place. You don't have to use it but if you want backbone to fire events you need to do your rendering work on the el. A views el is a DOM element but it does not have to be a pre-existing element. It will be created if you do not pull one from your current page, but you will have to insert it into the page if you ever want to see it do anything.

An example: I have a view that creates individual items

window.ItemView = Backbone.View.extend({
    tagName: "li", //this defaults to div if you don't declare it.
    template: _.template("<p><%= someModelKey %></p>"),
    events: {
         //this event will be attached to the model elements in
         //the el of every view inserted by AppView below
        "click": "someFunctionThatDoesSomething"
    },
    initialize: function () { 
        _.bindAll(this, "render");
        this.render();
    },
    render: function () {
        this.el.innerHTML = this.template(this.model.toJSON());
        return this;
    }
});
window.AppView = Backbone.View.extend({
    el: $("#someElementID"), //Here we actually grab a pre-existing element
    initialize: function () { 
        _.bindAll(this, "render");
        this.render(new myModel());
    },
    render: function (item) { 
        var view = new ItemView({ model: item });
        this.el.append(view.render().el);
    }
});

The first view just creates the list items and the second view actually places them on the page. I think this is pretty similar to what happens in the ToDo example on the backbone.js site. I think convention is to render you content into the el. So the el serves as a landing place or a container for placing your templated content. Backbone then binds its events to the model data inside of it.

When you create a view you can manipulate the el in four ways using el:, tagName:, className:, and id:. If none of these are declared el defaults to a div without id or class. It is also not associated with the page at this point. You can change the tag to something else by using using tagName (e.g. tagName: "li", will give you an el of <li></li>). You can set the id and class of el likewise. Still el is not a part of your page. The el property allows you to do very fine grain manipulation of the el object. Most of the time I use an el: $("someElementInThePage") which actually binds all the manipulation you do to el in your view to the current page. Otherwise if you want to see all the hard work you have done in your view show up on the page you will need to insert/append it to the page somewhere else in your view (probably in render). I like to think of el as the container that all your view manipulates.


Thanks for the clarification and the example! I think it is not always clear what the el should be in certain situations and the developer has to get a "feel" for it. Your explanations certainly helped! One question, though: you don't define an el in your ItemView, but you access it in the render function. Will this work? Is there some kind of default el if you don't explicitly define it?
By default el is a "div" tag with no id or class. It is a DOM object not bound to your page DOM. Usually I insert/append it to the page in the render function or the render function of a parent view.
Updated my answer with some description of the properties that define the el.
I guess my only issue with grabbing a pre-existing element with el: $("#someElementID") is your view probably knows more than it should, making it difficult to reuse it. see "Decouple view from DOM..." coenraets.org/blog/2012/01/…
@scoarescoare since you are adding the el property on instantiation the view itself does not actually know more than it should, it remains modular and able to accept any $(el) you want to hand it. So this makes it quite reusable, really.
s
sth

Bit old now, but I was confused as well, and so for other people that get here, this fiddle might help - http://jsfiddle.net/hRndn/2/

var MyView = Backbone.View.extend({

    events: {
        "click .btn" : "sayHello",
    },

    sayHello : function() {
        alert("Hello");
    },


    render : function() {
        this.$el.html("<input type='button' class='btn' value='Say Hello'></input>");

    }
});

$(function() {
    myView = new MyView({el:"#parent_id"});
    myView.render();
});

I've followed this model and wish I had not. To destroy a view and remove the bindings, backbone's convention is view.remove(). That destroys $el and removes it from the DOM, so when you need to show the view again, $el does not exist.
@Mark what If i'm using composite architecture like marionette.... do i still need to have view's el?
your fiddle code doesn't work, as link should be jsfiddle.net/hRndn
@Mahi Yes you are right. I probably pasted wrong link, sorry. This one works: jsfiddle.net/hRndn/127
j
joshvermaire

You want your 'el' to reference an element that contains a child element that has any event that triggers a change in your view. Could be as wide as a "body" tag.


Hmm, that doesn't really clear it up either. Most of the times the elements that could trigger a change in my view are inside the template the view renders, so before it is rendered these elements don't exist yet.