BackboneJS 重新排列集合中模型的最佳方法,同时维护每个模型的 0 索引序数属性

2024-01-10

我在这里遇到一个问题,我有一个 BackboneJS 模型的集合,每个模型都有一个“序数”属性来跟踪其在集合中的顺序。

这是我的播放数据

var ex_group_test_data = [{

            title: 'PRE EXERCISE',
            id:         0,
            ordinal:    1,

            group_items: [{
                id:         0,
                ordinal:    0,
                title: 'item 1'
            },{
                id:         1,
                ordinal:    1,
                title: 'item 2'
            }]

        },{

            title: 'MAIN PART',
            id:         1,
            ordinal:    0,

            group_items: [{
                id:             2,
                ordinal:        0,
                title:          'item 3',
                description:    'testing descrip'
            },{
                id:         3,
                ordinal:    1,
                title: 'item 4'
            }]

        },{

            title: 'POST EXERCISE BS',
            id:         2,
            ordinal:    2,

            group_items: [{
                id:             2,
                ordinal:        0,
                title:          'item 5',
                description:    'testing descrip'
            },{
                id:         3,
                ordinal:    1,
                title: 'item 6'
            }]

        }];

这是我的骨干收藏的要点

        Collections.Exercise_Groups = Backbone.Collection.extend({
            model: Models.Exercise_Group,
            comparator: function(model){
                return model.get('ordinal');
            },
            initialize: function(){

                return this;
            }

从简单开始,我希望能够获取一个模型并将其移动 +1 或 -1 序数,并维护集合中所有模型的 0 索引。

最终,我希望将其提升到一个水平,即我可以放入模型或将它们从任何位置移除,但仍保持 0 索引,或者采用模型并将其移动 +/- X 位置。

有人有完成此任务的推荐方法吗?

EDIT 1

我已经找到了一个解决方案,明天我真正睡一觉后我可能想优化它。无论我相对于原始位置向前还是向后移动模型,它都会保持集合中模型“序数”的 0 索引。

EDIT 2呃,实际上它在边缘案例上有错误。

/**
             * Move model to a specified location. 
             * 
             * @param   int [model id]
             * @param   int [mew item position]
             * @return  this
             */
            move_to: function(m_id, new_pos){

                //keep within range
                if(new_pos < 0)
                    new_pos = 0;
                else if(new_pos > (this.length - 1))
                    new_pos = this.length - 1;


                var model = this.get(m_id),
                    old_pos = model.get('ordinal');


                model.set({
                    ordinal: new_pos
                });
                if(new_pos == old_pos){
                    //trigger associated events
                    this.sort();
                    return this;
                }

                //update indexes of affected models
                this.each(function(m){

                    //ordinal of current model in loop
                    var m_ordinal = m.get('ordinal');

                    //skip if this is the model we just updated
                    if(m.get('id') == m_id)
                        return;

                    if(old_pos < new_pos){
                        //moving down, ordinal is increasing

                        if(m_ordinal <= new_pos && m_ordinal != 0){
                            //this is in the range we care about
                            m.set({
                                ordinal: m.get('ordinal') - 1
                            });

                        }

                    }else if(old_pos > new_pos){
                        //moving up, ordinal is decreasing                  


                        if(m_ordinal >= new_pos && (m_ordinal != (this.length - 1))){
                            //this is in the range we care about
                            m.set({
                                ordinal: m.get('ordinal') + 1
                            });

                        }

                    }

                });

                this.sort();
                return this;

            }

EDIT 3好吧,我想我已经解决了所有问题,一些简单的范围问题。这是我已经彻底测试过的一些代码,我相信它是有效的。

/**
                 * Move model to a specified location. 
                 * 
                 * @param   int [model id]
                 * @param   int [mew item position]
                 * @return  this
                 */
                move_to: function(m_id, new_pos){

                    //keep within range
                    if(new_pos < 0)
                        new_pos = 0;
                    else if(new_pos > (this.length - 1))
                        new_pos = this.length - 1;


                    var model = this.get(m_id),
                        old_pos = model.get('ordinal');

                    log('old_pos ' + old_pos);
                    log('new_pos ' + new_pos);


                    model.set({
                        ordinal: new_pos
                    });
                    if(old_pos == new_pos){
                        //trigger associated events
                        this.sort();
                        return this;
                    }

                    var _this = this;
                    //update indexes of affected models
                    this.each(function(m){

                        //ordinal of current model in loop
                        var m_ordinal = m.get('ordinal');

                        //skip if this is the model we just updated
                        if(m.get('id') == m_id)
                            return;

                        if(old_pos < new_pos){
                            //moving down, ordinal is increasing

                            if(m_ordinal <= new_pos && !(m_ordinal <= 0)){
                                //this is in the range we care about
                                m.set({
                                    ordinal: m.get('ordinal') - 1
                                });

                            }

                        }else if(old_pos > new_pos){
                            //moving up, ordinal is decreasing                  
                             log('p1');

                            if(m_ordinal >= new_pos && !(m_ordinal >= (_this.length - 1))){
                                //this is in the range we care about
                                m.set({
                                    ordinal: m.get('ordinal') + 1
                                });

                            }

                        }

                    });

                    this.sort();                    
                    return this;

                }

EDIT 4

又发现一个bug,修复一下。

Backbone.Collection.prototype.move_to = function(m_id, new_pos) {

    //keep within range
    if(new_pos < 0)
        new_pos = 0;
    else if(new_pos > (this.length - 1))
        new_pos = this.length - 1;


    var model = this.get(m_id),
        old_pos = model.get('ordinal');

    log('old_pos ' + old_pos);
    log('new_pos ' + new_pos);

    model.set({
        ordinal: new_pos
    });
    if(old_pos == new_pos){
        //trigger associated events
        this.sort();
        return this;
    }

    var _this = this;
    //update indexes of affected models
    this.each(function(m){

        log(m.id);

        //ordinal of current model in loop
        var m_ordinal = m.get('ordinal');

        //skip if this is the model we just updated
        if(m.get('id') == m_id)
            return;

        if(old_pos < new_pos){
            //moving down, ordinal is increasing

            if(m_ordinal <= new_pos && m_ordinal >= old_pos && !(m_ordinal <= 0)){
                //this is in the range we care about
                m.set({
                    ordinal: m.get('ordinal') - 1
                }, {
                    silent: true
                });

            }

        }else if(old_pos > new_pos){
            //moving up, ordinal is decreasing                  
             log('p1');

            if(m_ordinal >= new_pos && m_ordinal <= old_pos && !(m_ordinal >= (_this.length - 1))){
                //this is in the range we care about
                m.set({
                    ordinal: m.get('ordinal') + 1
                }, {
                    silent: true
                });

            }

        }

    });

    this.sort();                    
    return this;
};

如果您查看backbone.js源代码,您会发现例如add方法支持将模型添加到某些索引

collectionName.add(model, {at: index});

从位置删除可能需要您为集合创建自定义函数,例如:

// Your Collection

removeAt: function(options) {
  if (options.at) {
    this.remove(this.at(options.at));
  }
}

对于+1 / -1,您可以创建自定义函数并使用内置下划线indexOf函数

// Your Collection

moveUp: function(model) { // I see move up as the -1
  var index = this.indexOf(model);
  if (index > 0) {
    this.remove(model, {silent: true}); // silence this to stop excess event triggers
    this.add(model, {at: index-1});
  }
}

moveDown: function(model) { // I see move up as the -1
  var index = this.indexOf(model);
  if (index < this.models.length) {
    this.remove(model, {silent: true}); // silence this to stop excess event triggers
    this.add(model, {at: index+1});
  }
}

通过这种方式,您还可以将 moveUp 和 moveDown 实现到模型本身,以获得更易于阅读的代码!

// Your Model

moveUp: function() {
  this.collection.moveUp(this);
}

// And the same for moveDown

但现在索引属性不保存在模型本身中。要读取索引只需使用collection.indexOf(model),但是如果您想始终将该信息存储在模型中,您可以绑定到add and remove当对集合进行更改时更新所有索引的事件:

// Your collection

initialize: function(options?) {
  ...
  this.on('add remove', this.updateModelOrdinals);
  ...
},

...

updateModelOrdinals: function() {
  this.each(function(model, index) {
    this.model.set('ordinal', index);
  });
}

瞧!现在您应该拥有所需的功能,而无需重新发明轮子,并且仍然使用 Backbone 自己的功能保持 0 索引!抱歉,有点得意忘形,请问我是否超出了你的理解范围。并阅读backbone.js 源代码 https://github.com/documentcloud/backbone/blob/master/backbone.js,你可以在那里找到非常有用的东西!

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BackboneJS 重新排列集合中模型的最佳方法,同时维护每个模型的 0 索引序数属性 的相关文章

  • 如何从 JavaScript 中的字符串中删除空白字符?

    如何从 JavaScript 中的字符串中删除空白字符 修剪很容易 但我不知道如何将它们从inside字符串 例如 222 334 gt 222334 您可以使用正则表达式 如下所示来替换所有空格 var oldString 222 334
  • JavaScript - 无需布尔值即可运行一次

    有没有办法只运行一段JavaScript代码ONCE 而不使用布尔标志变量来记住它是否已经运行过 具体来说not就像是 var alreadyRan false function runOnce if alreadyRan return a
  • 如何在 Sequelize ORM 中限制连接行(多对多关联)?

    Sequelize 定义了两种模型 具有多对多关联的 Post 和 Tag Post belongsToMany db Tag through post tag foreignKey post id timestamps false Tag
  • 在动态创建的元素上添加事件监听器[重复]

    这个问题在这里已经有答案了 是否可以向所有动态生成的元素添加事件侦听器 Javascript 我不是页面的所有者 因此我无法以静态方式添加侦听器 对于页面加载时创建的所有元素 我使用 doc body addEventListener cl
  • 使用 :hover 作为元素的内联样式(使用 HTML/CSS/php)[重复]

    这个问题在这里已经有答案了 可能的重复 如何将 a hover 规则嵌入到文档中间的样式属性中 https stackoverflow com questions 131653 how do i embed an ahover rule i
  • 避免在 ES6 的函数内定位 this 的对象作用域

    例如 我正在使用 D3 js 运行一个项目 导入特定模块并调用它们的函数 Setup TypeScript ES6 导入特定的 D3 组件 角6 我有一个对象 在本例中是一个角度指令 并在 SVG 画布上绘制一些圆圈 并希望它们在拖动事件上
  • ReactCSSTransitionGroup 组件WillLeave 未调用

    我尝试使用 ReactCssTransition 但不知何故该事件没有被调用 componentWillLeave 这是我的组件 import React Component from react import TransitionGrou
  • 带有 mkdocs 的本地 mathjax

    我想在无法访问互联网的计算机上使用 MathJax 和 Mkdocs 因此我不能只调用 Mathjax CDN Config mkdocs yml site name My Docs extra javascript javascripts
  • 如何在 javascript 中基于类型字符串创建新对象?

    如何基于变量类型字符串 包含对象名称 在 javascript 中创建新对象 现在我有 随着更多工具的出现 列表会变得更长 function getTool name switch name case SelectTool return n
  • 如何知道浏览器空闲时间?

    如何跟踪浏览器空闲时间 我用的是IE8 我没有使用任何会话管理 也不想在服务器端处理它 这是纯 JavaScript 方法来跟踪空闲时间 并在达到一定限制时执行一些操作 var IDLE TIMEOUT 60 seconds var idl
  • JavaScript 中的实时摩尔斯电码转换器

    在看到谷歌关于莫尔斯电码 gmail 的愚人节笑话后 我想我应该尝试用 javascript 创建一个实时莫尔斯电码转换器 我正在使用正则表达式和替换将莫尔斯电码更改为字符 例如 replace g a replace g r 我遇到的问题
  • Javascript onload 不起作用[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在使用
  • 弹出窗口的动态高度取决于内容,可能吗?

    是否有可能获得一个宽度始终为 400px 的弹出窗口 但根据弹出窗口中的内容动态高度 我已经看到了这个 但不知道如何将其应用到弹出窗口 调整 iframe 的宽度高度以适应其中的内容 https stackoverflow com ques
  • 使用 AJAX 和 JQuery 按设定的时间间隔刷新 Rails 部分

    I have a page in my rails application that looks like 现在 我有另一个用 python 编码的人工智能应用程序 它处理视频 显示在 Rails 应用程序页面的左侧 并使用捕获的车辆及其相
  • 检测浏览器选项卡是否具有焦点

    是否有可靠的跨浏览器方法来检测选项卡是否具有焦点 场景是 我们有一个定期轮询股票价格的应用程序 如果页面没有焦点 我们可以停止轮询并为每个人节省流量噪音 特别是当人们喜欢打开具有不同投资组合的多个选项卡时 Is window onblur
  • AngularJS 在指令运行之前通过 AJAX 检索数据

    我正在使用 AngularUIuiMap http angular ui github com directives map实例化谷歌地图的指令 uiMap 指令非常适合处理硬编码数据 mapOptions and myMarkers 但是
  • 搜索多维数组 JavaScript

    我有一个如下所示的数组 selected products 0 r1 7up 61 Albertsons selected products 1 r3 Arrowhead 78 Arrowhead selected products 2 r
  • D3 将现有 SVG 字符串(或元素)追加(插入)到 DIV

    我到处寻找这个问题的答案 并找到了一些我认为可能有用的资源 但最终没有让我找到答案 这里有一些 外部SVG http bl ocks org mbostock 1014829 嵌入SVG https stackoverflow com qu
  • 用javascript调用外部网页(跨域)

    我正在尝试使用以下网络服务来验证提要这个问题 https stackoverflow com questions 11996430 check if a url is a valid feed 但浏览器不允许我向另一台服务器发送 ajax
  • JQuery 删除和内存泄漏

    我正在开发一个游戏 我看到了很多内存消耗 我使用jquery animate 动画完成后 我 remove 元素 我的问题是 从 dom 树中删除一个元素后 对象还存在记忆中吗 Javascript 是一种垃圾收集语言 这意味着当没有代码保

随机推荐