jquery – 解析Ember和Dragula对DOM的看法

我正在使用Dragula在Ember中创建一组拖放组件.我将项目列表传递给包含多个可丢弃存储桶的父包装器.最初过滤此项目列表,以便它们在正确的存储桶中呈现正确的项目.然后将Dragula连接起来,以便可以拖放项目.当发生drop事件时,我尝试更新底层的Ember对象.这可能导致重新应用过滤器并进行一些渲染.问题是DOM已被Dragula操纵,并且与Ember认为它应该是不同的并且DOM节点刚刚消失.

当Ember和Dragula都认为他们拥有DOM及其当前的代表时,我怎么能让他们玩得很好?我已经尝试取消了draggle drop事件,然后让Ember设置了有限的成功值.

DND-包装/ template.hbs

{{yield (action "register")}}

DND-包装/ component.js

export default Ember.Component.extend({
  drake: null,buckets: [],items: [],initDragula: Ember.on('willInsertElement',function() {
    this.set('drake',window.dragula());
  }),setupDragulaEvents: Ember.on('didInsertElement',function() {
    this.get('drake').on('drop',(itemEl,destinationEl,sourceEl) => {
      let dest = this.buckets.findBy('element',destinationEl);
      let source = this.buckets.findBy('element',sourceEl);
      let item = this.items.findBy('element',itemEl);

      item.component.set('item.bucket',dest.component.get('value'));
    });
  }),actions: {
    register(type,obj) {
      if(type === 'bucket') {
        this.get('drake').containers.push(obj.element);
        this.buckets.pushObject(obj);
      }
      else {
        this.items.pushObject(obj);
      }
    }
  }
});

DND-桶/ template.hbs

<h2>bucket {{value}}</h2>
<ul>
    {{#each filteredItems as |item|}}
    {{dnd-item item=item register=register}}
  {{/each}}
</ul>

DND-桶/ component.js

export default Ember.Component.extend({
  items: null,registerWithWrapper: Ember.on('didInsertElement',function() {
    this.register('bucket',{
      component: this,element: this.$('ul')[0]
    });
  }),filteredItems: Ember.computed('items.@each.bucket',function() {
    return this.get('items').filterBy('bucket',this.get('value'));
  })
});

DND项/ template.hbs

{{item.title}}

DND项/ component.js

export default Ember.Component.extend({
  registerWithWrapper: Ember.on('didInsertElement',function() {
    this.register('item',element: this.$()[0]
    });
  })
});

在线演示:http://ember-twiddle.com/c086d2853a926c310a23

GitHub演示:https://github.com/RyanHirsch/dragula-ember-example

解决方法

我遇到了你正在描述的完全相同的问题.我花了好几个小时尝试不同的东西来解决它,我想我终于提出了一个hacky但可行的解决方案.它的关键是我必须强制“源”桶在触发掉落事件后重新渲染其物品.

不幸的是,我不得不使用蛮力来重新渲染工作,在任何父视图上调用rerender都不起作用. Ember认为从DOM中消失的项目仍然存在并且正确呈现.

我最终使用{{#if listVisible}} {{/ if}}将dbI-bucket模板中的filteredItems列表包装起来.如果你然后设置itemsVisible false和true它会强制列表重新渲染并修复DOM损坏.我还必须确保这些集合在runloop中渲染之前和之后.

resetView: function() {
  Ember.run.scheduleOnce('render',this,() => {
    this.set("listVisible",false);
  });
  Ember.run.scheduleOnce('afterRender',true);
  });
}

在我的情况下,我在更新drop回调中的模型后触发了resetView.虽然这个修复很麻烦,但视觉效果是可以接受的.如果DOM元素确实消失了,它们就会被替换掉,这有点不和谐.但是,99.9%的时间没有丢失DOM元素,根本没有视觉故障.

相关文章

jQuery插件的种类 1、封装对象方法 这种插件是将对象方法封装起来,用于对通过选择器获取的jQuery对象进...
扩展jQuery插件和方法的作用是非常强大的,它可以节省大量开发时间。 入门 编写一个jQuery插件开始于给...
最近项目中需要实现3D图片层叠旋转木马切换的效果,于是用到了jquery.roundabout.js。 兼容性如图: ht...
一、什么是deferred对象? 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异...
AMD 模块 AMD(异步模块定义,Asynchronous Module Definition)格式总体的目标是为现在的开发者提供一...