jQuery 以正确的顺序插入元素 vs detach().sort()?
假设我有以下 html 结构:
<ul>
<li>1</li>
<li>2</li>
<li>4</li>
</ul>
是否可以(以及如何)以正确的顺序插入新元素
而不分离元素和手段?原因是,我相信如果您 .detach() 和 .append() 元素,您将导致页面回流(我认为如果元素移动,无论如何都会发生)。但由于某种原因,与追加/分离/排序/追加相比,将其插入正确的位置似乎更干净。
我已经在 jQuery 中看到了 nth-child 选择器,并且我也在使用 underscore.js 框架(它提供了 _.sortedIndex
,它告诉我元素的正确位置),但我可以似乎没有找到将其放入其中的正确方法。
一些背景: 我正在使用backbone.js,并且我有一个项目集合。然后我假设我需要集合的视图(或集合中每个项目的视图?)。当我向集合中添加元素时,我设置了比较器,因此集合已正确排序,但页面上的视图未排序。
对于那些通过谷歌到达这里的人,这是我最终在backbone.js中想到的:
Item = Backbone.Model.extend({});
ItemList = Backbone.Collection.extend({
model: Item,
comparator: function(item) {
return item.get('id');
}
});
ItemView = Backbone.View.extend({
tagName: 'li',
className: 'item',
initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.model.view = this;
},
render: function() {
$(this.el).text(this.model.get('name'));
return this;
}
});
App = Backbone.View.extend({
el: $('#mylist'),
initialize: function() {
_.bindAll(this, 'add_one', 'add_all', 'render');
this.items = new ItemList();
this.items.bind('add', this.add_one);
this.items.bind('refresh', this.add_all);
this.items.bind('all', this.render);
this.items.add(new Item({id: 2, name: 'two'}));
this.items.add(new Item({id: 5, name: 'five'}));
this.items.add(new Item({id: 1, name: 'one'}));
this.items.add(new Item({id: 4, name: 'four'}));
this.items.add(new Item({id: 3, name: 'three'}));
this.items.add(new Item({id: 6, name: 'six'}));
this.items.add(new Item({id: 5.5, name: 'five.five'}));
},
add_one: function(item) {
var view = new ItemView({model: item});
var visible = this.$(view.tagName+'.'+view.className);
var newel = view.render().el;
var idx = this.items.indexOf(item);
if (visible.length == idx) {
$(this.el).append(newel);
}
else {
visible.eq(idx).before(newel);
}
},
add_all: function() {
this.items.each(this.add_one);
}
});
app = new App();
Let's say I have the following html structure:
<ul>
<li>1</li>
<li>2</li>
<li>4</li>
</ul>
Is it possible (and how) to insert a new element <li>3</li>
in the correct order without detaching the elements and resorting? Reason being, I believe if you .detach() and .append() the elements, you will cause a page reflow (which I suppose would happen anyways if the elements move around). But for some reason, it seems much cleaner to insert it in the right spot vs append/detach/sort/append.
I've seen the nth-child selector in jQuery and I'm working with the underscore.js framework too (which provides _.sortedIndex
which tells me the correct position of the element), but I can't seem to figure out the right way to put it in there.
Some background:
I'm working with backbone.js and I have a collection of items. Then I assume I need a View of the collection (or view per item in the collection?). When I add an element to the collection, I have the comparator set so the collection is sorted properly, but the View on the page is not sorted.
For those getting here via google, here's what I eventually came up with in backbone.js:
Item = Backbone.Model.extend({});
ItemList = Backbone.Collection.extend({
model: Item,
comparator: function(item) {
return item.get('id');
}
});
ItemView = Backbone.View.extend({
tagName: 'li',
className: 'item',
initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.model.view = this;
},
render: function() {
$(this.el).text(this.model.get('name'));
return this;
}
});
App = Backbone.View.extend({
el: $('#mylist'),
initialize: function() {
_.bindAll(this, 'add_one', 'add_all', 'render');
this.items = new ItemList();
this.items.bind('add', this.add_one);
this.items.bind('refresh', this.add_all);
this.items.bind('all', this.render);
this.items.add(new Item({id: 2, name: 'two'}));
this.items.add(new Item({id: 5, name: 'five'}));
this.items.add(new Item({id: 1, name: 'one'}));
this.items.add(new Item({id: 4, name: 'four'}));
this.items.add(new Item({id: 3, name: 'three'}));
this.items.add(new Item({id: 6, name: 'six'}));
this.items.add(new Item({id: 5.5, name: 'five.five'}));
},
add_one: function(item) {
var view = new ItemView({model: item});
var visible = this.$(view.tagName+'.'+view.className);
var newel = view.render().el;
var idx = this.items.indexOf(item);
if (visible.length == idx) {
$(this.el).append(newel);
}
else {
visible.eq(idx).before(newel);
}
},
add_all: function() {
this.items.each(this.add_one);
}
});
app = new App();
Run it here: http://jsfiddle.net/dlamotte/L4j3b/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你可以使用 jQuery
fiddle 页面: http://jsfiddle.net/Hrjks/
更好的是:
fiddle :http://jsfiddle.net/Hrjks/1/
you can use a jQuery
fiddle page: http://jsfiddle.net/Hrjks/
Better yet:
fiddle for this:http://jsfiddle.net/Hrjks/1/
我最近遇到了同样的问题,我用以下函数修复了。
它基本上是获取父级的所有子级,然后执行过滤器。如果您只需要比较它的值,您可以通过避免回调来简单地做到这一点,但在我的情况下,这是需要的,因为我按几个标准进行排序。
如果您想按降序排序,只需将
append
替换为prepend
,将before
替换为last
和
应该可以工作。last
的第一个欢迎在我的游乐场玩:http://jsfiddle.net/crodas/FMEkb/5/
I had the same problem recently and I fixed with the following function.
It is basically getting all the child of
parent
, then doing afilter
. If you only need to compare its values you can do it simple by avoiding the callback but in my case it was needed as I was sorting by several criteria.If you want to sort with a descending order just replace
append
byprepend
,before
bylast
andfirst
forlast
and it should be working.Feel free to play in my playground: http://jsfiddle.net/crodas/FMEkb/5/