首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >主干:使用_.template内部的视图

主干:使用_.template内部的视图
EN

Stack Overflow用户
提问于 2013-01-16 02:51:54
回答 1查看 993关注 0票数 1

我试图创建一个动态的Widget系统来在我的页面中创建面板。让我们举一个例子:

代码语言:javascript
复制
                Widgets.create({
                    name : 'menu-site',
                    title: 'Menu', 
                    content: 'This is my menu!'
                });  

它将使之成为:

代码语言:javascript
复制
<section class="widget menu-site">
    <h1>Menu</h1>
    <article>This is my menu!</article>
</section>

没事的对吧?我已经做了上千次了。但是,当我试图在内部使用视图时,问题就开始了:

代码语言:javascript
复制
                var view = new MyCustomView;                  
                Widgets.create({
                    name : 'custom-panel',
                    title: 'Custom Panel', 
                    content: view.render().el
                });                    

我可以通过在outerHTML中调用WidgetView来呈现内容,但是,当我这样做时,在MyCustomView中声明的事件不能工作!

有人面临过这个问题吗?

对于那些需要更多细节的人,这是我的WidgetView代码:

代码语言:javascript
复制
        var Widget = Backbone.Model.extend({
            defaults : function() {
                return {
                    title : '',
                    content : '',
                    closeable : true
                }
            }
        });
        var WidgetList = Backbone.Collection.extend({
            url : '/widgets',
            model : Widget
        });
        Widgets = new WidgetList;


        var WidgetView = Backbone.View.extend({
            tagName : 'section',
            className : function() {
                return ['widget',' ', this.model.get('name')].join('');
            },
    template: _.template($('#widget-template').html()),

            events : {
                "click .close" : "removeWidget"
            },

            initialize : function() {
                this.listenTo(this.model, 'destroy', this.remove);
            },


            removeWidget  : function() {
                this.model.destroy();
            },

            render: function() {
              this.$el.append(this.template(this.model.toJSON()));   
              return this;
            },
        });

        var AppViewport = Backbone.View.extend({
            el : $("#widgets"),

            events : {
            },

            initialize : function() {
                this.listenTo(Widgets, 'add', this.addNewWidgetView);
            },

            addNewWidgetView : function(widget) {
              var view = new WidgetView({model: widget});
              this.$el.append(view.render().el);
            }
        });

        new AppViewport;

或者,也许,我在考虑另一个解决办法。但是我浪费了太多的时间去理解这个问题,以至于我看不到光明!

更新

我做了一些测试,并修改了代码:我没有使用下划线模板,而是创建了一个WidgetViewLayout,并手动完成了所有模板的工作:

代码语言:javascript
复制
            var WidgetView = Backbone.View.extend({
                tagName : 'section',
                className : function() {
                    return ['widget',' ', this.model.get('name')].join('');
                },

                events : {
                    "click .close" : "removeWidget"
                },

                initialize : function() {
                    this.listenTo(this.model, 'destroy', this.remove);
                },


                removeWidget  : function() {
                    this.model.destroy();
                    MenuRouterInstance.navigate('');
                },

                render: function() {
                    var layout_view = new WidgetViewLayout({model: this.model.toJSON()});
                    this.$el.append(layout_view.render().el);   
                    return this;
                }
            });

            var WidgetViewLayout = Backbone.View.extend({
                tagName : 'div',

                render : function() {
                    var title = this.model.title,
                        content = this.model.content,
                        closeable = this.model.closeable || false;

                    var anchor = this.setupAnchor(closeable),
                        h1 = this.setupH1(title, anchor),
                        article = this.setupArticle(content);

                    this.$el.append(h1);
                    this.$el.append(article);

                    return this;
                },

                setupH1 : function(title, target) {
                    var element = $('<h1 />');
                    element.text(title);
                    element.append(target);   

                    return element;
                },

                setupAnchor : function(closeable) {
                    var element = '';
                    if(closeable == true) {
                        element = $('<a />'); 
                        element.addClass('close');
                        element.text('(fechar)');
                    }

                    return element;
                },

                setupArticle : function(content) {
                    var element = $('<article />');
                    element.append(content);

                    return element;
                }
            })

它现在似乎有效了,但是我在Widget中创建的视图仍然存在一些问题,比如:

代码语言:javascript
复制
                    var view = new MyView;                  
                    Widgets.create({
                        name : 'menu',
                        title: 'My menu', 
                        content: view.render().el
                    }); 

当MyView在自身内创建多个SubViews时,我调用model.destroy来删除Subview的一个模型,侦听方法"this.remove“最终会删除所有SubViews,而不是只删除一个SubViews。最后,我被迫这样做:

代码语言:javascript
复制
                removeit : function(removed_item) {
                    if(removed_item.get('name') == this.model.get('name')) {
                        this.remove();                            
                    }
                },

我不知道这是不是一个坏的模式,但它已经成功了!如果有人有更好的主意我很感激!

[`,s

EN

回答 1

Stack Overflow用户

发布于 2013-01-16 03:15:49

我认为您的问题是,您试图将DOM元素对象(el)视为字符串。当你这样做时:

代码语言:javascript
复制
content: view.render().el

content中将有一个活动的DOM节点,视图的事件将绑定到该DOM节点。您可以使用其中一个HTML方法(在您的示例中是outerHTML )通过模板获取节点的HTML,但是处理事件的delegate绑定到DOM节点,而不是绑定到最终使用的HTML字符串。

您可以修改一下您的render以处理原始DOM节点,在必要时可以这样做。

代码语言:javascript
复制
render: function() {
    var json = this.model.toJSON();
    if(_(json.content).isString()) {
        this.$el.append(this.template(json));
    }
    else {
        var content = json.content;
        delete json.content;
        this.$el.append(this.template(json));
        this.$('article').append(content);
    }
}

基本上,如果您的content不是字符串,那么就手动将其放入$el中,而不是遍历模板。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14350651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档