Вот ваш JS Bin сортировкой компонент:
App.MyListComponent = Ember.Component.extend({
tagName: 'ul',
didInsertElement() {
let opts = {};
opts.update = this.updateList.bind(this);
this.$().sortable(opts);
},
updateList() {
this.$().sortable('cancel');
Ember.run.next(() => {
this.get('content').removeAt(0);
});
}
});
И тогда это ваш JS Bin updated с кодом из ember-ui-sortable repo на следующее:
App.MyListComponent = Ember.Component.extend({
tagName: 'ul',
uiOptions: [
'axis',
'containment',
'cursor',
'cursorAt',
'delay',
'disabled',
'distance',
'forceHelperSize',
'forcePlaceholderSize',
'grid',
'handle',
'helper',
'opacity',
'placeholder',
'revert',
'scroll',
'scrollSensitivity',
'scrollSpeed',
'tolerance',
'zIndex'
],
destroySortable: Ember.on('willDestroyElement', function() {
this.$().sortable('destroy');
}),
initSortable: Ember.on('didInsertElement', function() {
let opts = {};
['start', 'stop'].forEach((callback) => {
opts[callback] = Ember.run.bind(this, callback);
});
this.$().sortable(opts);
this.get('uiOptions').forEach((option) => {
this._bindSortableOption(option);
});
}),
contentObserver: Ember.observer('content.[]', function() {
Ember.run.scheduleOnce('afterRender', this, this._refreshSortable);
}),
move(oldIndex, newIndex) {
let content = this.get('content');
let mutate = this.getWithDefault('mutate', true);
let item = content.objectAt(oldIndex);
if (content && mutate) {
content.removeAt(oldIndex);
content.insertAt(newIndex, item);
}
if(!mutate){
this.attrs.moved(item, oldIndex, newIndex);
}
},
start(event, ui) {
ui.item.data('oldIndex', ui.item.index());
},
stop(event, ui) {
const oldIndex = ui.item.data('oldIndex');
const newIndex = ui.item.index();
this.move(oldIndex, newIndex);
},
_bindSortableOption: function(key) {
this.addObserver(key, this, this._optionDidChange);
if (key in this) {
this._optionDidChange(this, key);
}
this.on('willDestroyElement', this, function() {
this.removeObserver(key, this, this._optionDidChange);
});
},
_optionDidChange(sender, key) {
this.$().sortable('option', key, this.get(key));
},
_refreshSortable() {
if (this.isDestroying) { return; }
this.$().sortable('refresh');
}
});
Как вы видите, довольно немного дополняет ваш оригинал, поэтому вы можете взглянуть на то, что вы пропустили, и, надеюсь, это вам поможет. Возможно, было бы неплохо установить этот компонентный аддон через ember-cli, но также посмотреть на конкурирующие решения, например ember-sortable и другие, используя что-то вроде ember-observer.
У меня нет ответа на ваш вопрос, но я могу хотя бы предложить POV, с которым вам следует рассмотреть возможность анализа вашей ситуации. Плагин JQuery UI Sortable основан на прямой манипуляции с DOM, которая будет выполняться как обратные вызовы, которые регистрируются им при пожаре на пользователях событий мыши. Ember с другой стороны использует HTMLbars, который также имеет DOM-манипуляционную логику, которая намного сложнее и должна быть погружена в понимание такого поведения. Вам следует избегать прямого манипулирования DOM и мутацией массива 'content' на компоненте. Это разумный способ делать вещи. – canufeel
Я думаю, я также должен добавить, что если вы хотите получить это с самого начала, вы должны «отвязать» массив 'content' до того, как будете на самом деле мутировать, чтобы вы не попали в адвентирующий ад. – canufeel
@ canufeel, вы правы, это проблема DOM. Когда я смоделирую обновление в компоненте, как в этом [JS Bin] (http://emberjs.jsbin.com/huciqinoho/edit?html,js,output), тогда он работает. Однако я думаю, что, должно быть, был какой-то способ Эмбер. Может быть, это проблема с Glimmer, которая не может сделать правильный diff после того, как DOM был изменен jQuery UI? – Lucas