Backbone.js的后未触发事件重新呈现 [英] backbone.js events not firing after re-render

查看:93
本文介绍了Backbone.js的后未触发事件重新呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个观点,即渲染时有附加的click事件上登录按钮。首先呈现所有作品:点击按钮,并在成功的Ajax调用的登录提示消失和欢迎视图显示(LoggedInView)。但是,如果我导航回到这个视图以后(#foo)的UI渲染,但事件关联不消失调用delegateEents()手动强制的问题。

发生了什么事,我的事件并没有自己重新关联?

  LoginView = Backbone.View.extend({
    模板:_.template($(#loginTemplate)HTML()。)
    初始化:功能(东东,路由器){
        _.bindAll(在此,呈现,RC,gotProfile');
        this.model.bind(RC,this.rc)
        this.router =路由器;
    },
    事件:{
        点击.loginButton':'登录'
    },
    渲染:功能(){
        $(this.el)的.html(this.template(this.model.toJSON()));
        $(this.el).find(actionButton。)按钮(); //按钮
// this.delegateEvents(this.events); //需要!重线有关事件的重新渲染
        返回此;
    },
    RC:函数(code){
        开关(code){
            犯错的情况下codes.USER_NOT_FOUND:this.notFound();打破;
            犯错的情况下codes.OK:this.loginOk();打破;
            默认:this.otherErr();打破;
        }
    },
    登录:函数(){
        clearErrors($('[相对=REQ]'));
        VAR okReq =的validate($('#登录[相对=REQ]'),validateReq);
        VAR okEmail =验证([$('#UID')],validateEmail);
        如果(okReq&安培;&安培; okEmail){
            this.model.set({'UID':$('#UID)VAL()修剪(),'PWD':。$('#PWD')VAL()修剪()});
            this.model.fetch();
        }
    },
    NOTFOUND:功能(){
        验证([$('#UID'),$('#PWD'),函数(){返回[假的,无效的用户名/密码]});
    },
    otherErr:功能(){
        验证([$('#UID'),$('#PWD'),函数(){返回[假的,请在帮助日志支持。]});
    },
    loginOk:功能(){
        this.profile =新的配置文件({UID:this.model.get('UID'),令牌:this.model.get('键')});
        this.profile.bind(RC,this.gotProfile)
        this.profile.fetch();
    },
    gotProfile:功能(){
        this.router.navigate('/',TRUE);
    }
});LoggedInView = Backbone.View.extend({
    模板:_.template($(#显示LoggedInTemplate)HTML()。)
    uList:新ProfileList文件()
    初始化:功能(){
        _.bindAll(在此,呈现,renderUserList','renderUser');
        this.model.bind('秀',this.render);
        this.uList.bind(RC,this.render);
    },
    事件:{
        点击#ufa':'getUsersForHouse
    },
    渲染:功能(){
        $(this.el)的.html(this.template(this.model.toJSON()));
        this.renderUserList();
// this.delegateEvents(this.events); //需要!重线有关事件的重新渲染
        返回此;
    },
    renderUserList:功能(){
        $(this.el).find(UL),空();
        this.uList.each(this.renderUser);
    },
    renderUser:功能(aUser){
        $(this.el).find('#用户列表)追加。(<立GT;+ aUser.get(人)的firstName +< /李>中。);
    },
    getUsersForHouse:功能(){
        this.uList.fetch(this.model.get('令牌'),房子);
    }
});主要= Backbone.Router.extend({
    路线:{
        '富':'富',
        *所有:家
    },
    初始化:功能(){
        this.token =新令牌();
        this.loginView =新LoginView({模式:this.token},这一点);
    },
    富:功能(){//这里naving失去点击登录按钮事件
        $('#登录')空();
        $(#登陆)追加(this.loginView.render()EL)。
    },
    家庭:功能(){
        $('#登录')空();
        如果(this.loginView.profile == NULL)
            $(#登陆)追加(this.loginView.render()EL)。
        其他{
            this.loggedInView =新LoggedInView({模式:this.loginView.profile});
            $(#登陆)追加(this.loggedInView.render()EL)。
        }
    }
});


解决方案

您清空了#login股利。由于jQuery的医生说:


  

要避免内存泄漏,jQuery的删除其他结构,如数据
  从子元素和事件处理程序移除前
  元素本身。


所以,你有效地从你的观点删除事件。我preFER,因为它使事件使用分离。 http://api.jquery.com/detach/

您可以在您的视图的显示/隐藏,将处理这个。

[EDIT: I solved earlier problem by calling delegateEvents(), but shouldn't have to. Re-posting w/more info.]

I have a View that when rendered has a login button on it with a click event attached. First render all works: click on button and upon successful ajax call the login prompts disappear and welcome view (LoggedInView) is displayed. But, if I navigate back to this View later (#foo) the UI renders but the event association is gone without manually forcing the issue by calling delegateEents().

What happened that my events didn't re-associate themselves?

LoginView = Backbone.View.extend({
    template: _.template($("#loginTemplate").html()),
    initialize: function(stuff,router) {
        _.bindAll(this,'render','rc','gotProfile');
        this.model.bind("rc",this.rc)
        this.router = router;
    },
    events: {
        'click .loginButton': 'login'
    },  
    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
        $(this.el).find(".actionButton").button();  // Button
//      this.delegateEvents(this.events);  // NEEDED!  Re-wire events on re-render
        return this;
    },
    rc: function(code) {
        switch(code) {
            case errCodes.USER_NOT_FOUND:   this.notFound(); break;
            case errCodes.OK:               this.loginOk(); break;
            default:                            this.otherErr(); break;
        }
    },
    login: function() {
        clearErrors( $('[rel="req"]') );
        var okReq = validate( $('#login [rel="req"]'), validateReq );
        var okEmail = validate( [$('#uid')], validateEmail );
        if( okReq && okEmail ) {
            this.model.set({'uid':$('#uid').val().trim(),     'pwd':$('#pwd').val().trim()});
            this.model.fetch();
        }
    },
    notFound: function() {
        validate( [$('#uid'),$('#pwd')], function(){return[false,"Invalid user / password"]} );
    },
    otherErr: function() {
        validate( [$('#uid'),$('#pwd')], function(){return[false,"Please contact support for help logging in."]} );
    },
    loginOk: function() {
        this.profile = new Profile({uid:this.model.get('uid'),token:this.model.get('key')});
        this.profile.bind("rc",this.gotProfile)
        this.profile.fetch();
    },
    gotProfile: function() {
        this.router.navigate('/',true);
    }
});

LoggedInView = Backbone.View.extend({
    template: _.template($("#loggedInTemplate").html()),
    uList: new ProfileList(),
    initialize: function() {
        _.bindAll(this,'render','renderUserList','renderUser');
        this.model.bind('show', this.render);
        this.uList.bind('rc', this.render);
    },
    events: {
        'click #ufa': 'getUsersForHouse'
    },
    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
        this.renderUserList();
//      this.delegateEvents(this.events); // NEEDED!  Re-wire events on re-render
        return this;
    },
    renderUserList: function() {
        $(this.el).find('ul').empty();
        this.uList.each(this.renderUser);
    },
    renderUser: function(aUser) {
        $(this.el).find('#userList').append("<li>"+aUser.get('person').firstName+"</li>");
    },
    getUsersForHouse: function() {
        this.uList.fetch(this.model.get('token'),"house");
    }
});

Main = Backbone.Router.extend({
    routes: {
        'foo': 'foo',
        '*all': 'home'
    },
    initialize: function() {
        this.token = new Token();
        this.loginView = new LoginView({model:this.token},this);
    },
    foo: function(){  // naving here looses click event on login button
        $('#login').empty();
        $("#login").append(this.loginView.render().el);
    },
    home: function() {
        $('#login').empty();
        if( this.loginView.profile == null ) 
            $("#login").append(this.loginView.render().el);
        else {
            this.loggedInView = new LoggedInView({model:this.loginView.profile});
            $("#login").append(this.loggedInView.render().el);
        }
    }
});

解决方案

You empty the the #login div. As the jQuery doc says:

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.

So you are effectively removing events from your views. I prefer to use detach because it keeps events. http://api.jquery.com/detach/

You can implement a show/hide in your views that will deal with this.

这篇关于Backbone.js的后未触发事件重新呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆