gpt4 book ai didi

javascript - 再次在 Backbone 僵尸 View

转载 作者:行者123 更新时间:2023-12-03 11:25:39 27 4
gpt4 key购买 nike

我正在尝试了解主干,并且目前正在努力尝试僵尸 View 。我已经阅读了很多有关此问题的堆栈溢出信息,但仍然无法解决。

为了简单起见,我设置了两个需要切换的 View (无数据)。
到目前为止,我所做的是:

  • 创建对象

  • //定义应用程序对象
    var app = {
    通风口:{},
    模板:{},
    观看次数:{},
    路由器:{},
    };

    //实例化事件聚合器并将其附加到应用程序
    app.vent = _.extend({},Backbone.Events);

  • 定义了两个非常简单的模板(存储在app.templates中):第一个模板包含一些伪文本和一个按钮(其id为'test-begin'),第二个模板只是伪文本
  • 定义两个 View

  • app.views.instructions = Backbone.View.extend({

    //加载下划线模板
    模板:_。template(app.templates.instructions),

    //实例化时自动调用
    初始化:功能(选项){

    //将相关功能绑定(bind)到 View
    _.bindAll(this,'render','testBegin','stillAlive','beforeClose');

    //收听app.vent事件
    this.listenTo(app.vent,'still:alive',this.stillAlive);

    },

    //将事件绑定(bind)到DOM元素
    事件:{
    'click#test-begin':'testBegin',
    },

    //渲染 View
    渲染:function(){
    this。$ el.html(this.template());
    返回这个
    },

    //开始测试
    testBegin:function(){
    Backbone.history.navigate('begin',{trigger:true});
    },

    //还活着
    stillAlive:function(){
    console.log('我还活着');
    },

    //关闭之前
    beforeClose:function(){
    //停止收听app.vent
    this.stopListening(app.vent);
    },

    });

    //测试 View
    app.views.test = Backbone.View.extend({

    //加载下划线模板
    模板:_。template(app.templates.test),

    //实例化时自动调用
    初始化:功能(选项){

    // trigger still:alive,看看移除的 View 是否响应它
    app.vent.trigger('still:alive');

    //将相关功能绑定(bind)到 View
    _.bindAll(this,'render');

    },

    //渲染 View
    渲染:function(){
    this。$ el.html(this.template());
    返回这个
    },
    });

  • 定义路由器

  • //基本路由器
    app.routers.baseRouter = Backbone.Router.extend({

    //路线
    路线:{
    ”:“说明”,
    'begin':“beginTest”
    },

    //函数(属于对象 Controller )
    指令:function(){baseController.instructions()},
    beginTest:function(){baseController.beginTest()},
    });

    // baseRouter Controller
    var baseController = {

    说明:function(){
    mainApp.viewsManager.rederView(new app.views.instructions());

    },

    beginTest:函数(选项){
    mainApp.viewsManager.rederView(new app.views.test());
    },
    };

  • 定义mainApp(带有 View 切换器)

  • //定义mainApplication对象
    mainApp = {};

    //管理 View 切换
    mainApp.viewsManager = {

    // rootEl
    rootEl:'#test-container',

    //关闭当前 View 并显示下一个 View
    rederView:function(view,rootEl){

    //如果未传递DOM el,请将其设置为默认RootEl
    rootEl = rootEl || this.rootEl;

    //关闭当前 View
    如果(this.currentView)this.currentView.close();

    //存储对下一个 View 的引用
    this.currentView = View ;

    //呈现下一个 View
    $(rootEl).html(this.currentView.render()。el);
    },
    };

    //呈现应用程序的第一个 View
    mainApp.viewsManager.rederView(new app.views.instructions());

    //启动路由器并将其附加到应用程序
    mainApp.baseRouter =新的app.routers.baseRouter();

    //开始 Backbone 历史
    Backbone.history.start({silent:true

    });
  • 添加一个关闭功能以通过Backbone原型(prototype)
  • 查看


    //向Backbone View 原型(prototype)添加功能(在所有 View 中可用)
    Backbone.View.prototype.close = function(){

    //如果在 View 中定义 View ,则在其 View 之前调用 View
    如果(this.beforeClose)this.beforeClose();

    //从DOM中删除this.el并清除DOM元素的事件
    this.remove();

    //取消绑定(bind) View 绑定(bind)的任何模型和集合事件
    this.stopListening();

    //检查 View 是否有 subview
    如果(this.hasOwnProperty('_ subViews')){

    //循环thorugh当前 View 的 subview
    _(this._subViews).each(function(child){

    //调用 subview 的close方法
    child.close();
    });
    }
    };

    因此,为了检查僵尸 View ,第二个 View 会触发和事件(仍然: Activity ),第一个 View 会通过发送到console.log的消息来侦听和响应它(尽管实际上不是这样)。
    第一个 View 的确会听到这样的消息(在控制台日志中,我读到“我还活着”),即使它已被第二个 View 替换。

    你能帮助我吗?非常感谢

    最佳答案

    长帖子,如果您有任何疑问,请询问

    僵尸 View 只是不在DOM中的 View ,而是侦听事件并对事件使用react-有时这种行为是预期的,但通常不是这样。

    如果未正确删除该 View 的DOM事件处理程序,则该 View 及其内存HTML片段将不会被垃圾收集。如果Backbone.Event处理程序未正确解除绑定(bind),则可能会有各种各样的不良行为……例如,一堆“Zombie” View 触发了模型上的AJAX请求。这个问题在stopListeninglistenTo之前的Backbone的较旧版本中非常普遍,尤其是如果您在 View 之间共享模型时。

    在您的代码中,您没有Zombie View,因为您正在正确关闭 View 。

    您可以看到console.log,因为您正在关闭第二个 View (并触发事件still:alive),然后再关闭第一个 View 。

    要切换 View ,请致电:

    mainApp.viewsManager.rederView(new app.views.test());

    调用 new app.views.test()会初始化第二个 View ,从而触发第一个 View 监听的事件。

    如果您将代码更新为以下代码,将不再看到 console.log
    //baseRouter controller
    var baseController = {

    instructions: function() {
    mainApp.viewsManager.rederView(app.views.instructions);

    },

    beginTest: function(options) {
    mainApp.viewsManager.rederView(app.views.test);
    },
    };

    并更新rederView
    rederView : function(ViewClass, rootEl) {   
    //if DOM el isn't passed, set it to the default RootEl
    rootEl = rootEl || this.rootEl;

    //close current view
    if (this.currentView) this.currentView.close();

    //store reference to next view
    this.currentView = new ViewClass();

    //render next view
    $(rootEl).html(this.currentView.render().el);
    },

    如果从close方法中删除此行,则将具有僵尸 View ,并应看到 console.log
    //unbind any model and collection events that the view is bound to
    this.stopListening();

    僵尸查看示例

    在以下代码中,我将创建100个 View ,但在DOM中仅显示1个 View 。每个 View 都包含相同的模型,并监听其 change事件。单击 View 的 <button>元素时,它将更新模型,该模型将导致执行每个 View 的模型更改处理程序,调用fetch 100次... 100个AJAX请求!

    View 的更改处理程序被调用100次,因为 View 关闭方法未调用 this.stopListening(),因此即使将 View 从页面中删除,它们都仍会监听模型的事件。单击按钮后,模型将更改,并且所有僵尸 View 都会响应,即使它们不在页面上也是如此。

    var TestView = Backbone.View.extend({
    tagName: 'h1',
    initialize: function(options) {
    this.i = options.i;
    this.listenTo(options.model, 'change', function(model) {
    model.fetch();
    });
    },
    events: {
    'click button': function() {
    this.model.set("show_zombies", Date.now());
    }
    },
    render: function() {
    this.$el.append("<button>Click To Test for Zombies!</button>");
    return this;
    },
    close: function() {
    this.$el.empty(); // empty view html
    // this.$el.off(); // // Whoops! Forgot to unbind Event listeners! (this view won't get garbage collected)
    // this.stopListening() // Whoops! Forgot to unbind Backbone.Event listeners.
    }
    });

    var model = new (Backbone.Model.extend({
    fetch: function() {
    document.body.innerHTML += "MODEL.FETCH CALLED<br />"
    }
    }));

    var v;
    for (var i = 1; i < 101; i++) {
    if (v) v.close();
    v = new TestView({
    'i': i,
    'model': model
    }).render();

    $('body').html(v.el);
    }
    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone.js"></script>

    关于javascript - 再次在 Backbone 僵尸 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26369604/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com