Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jquery ui jQuery UI可排序,带有React.js bug_Jquery Ui_Reactjs_Jquery Ui Sortable_Reactjs Flux - Fatal编程技术网

Jquery ui jQuery UI可排序,带有React.js bug

Jquery ui jQuery UI可排序,带有React.js bug,jquery-ui,reactjs,jquery-ui-sortable,reactjs-flux,Jquery Ui,Reactjs,Jquery Ui Sortable,Reactjs Flux,我在React中有一个由jQueryUI支持的可排序列表。当我拖放列表中的一个项目时,我想更新数组,以便将列表的新顺序存储在那里。然后使用更新的数组重新呈现页面。i、 e.this.setState({data:_todoList}) 当前,当您拖放一个项目时,jQuery UI DnD可以工作,但该项目在UI中的位置不会改变,即使页面使用更新的数组重新呈现。i、 e.在UI中,即使定义其位置的数组已成功更新,项目仍会恢复到它以前在列表中的位置 如果拖放项目两次,则它将移动到正确的位置

我在React中有一个由jQueryUI支持的可排序列表。当我拖放列表中的一个项目时,我想更新数组,以便将列表的新顺序存储在那里。然后使用更新的数组重新呈现页面。i、 e.
this.setState({data:_todoList})

当前,当您拖放一个项目时,jQuery UI DnD可以工作,但该项目在UI中的位置不会改变,即使页面使用更新的数组重新呈现。i、 e.在UI中,即使定义其位置的数组已成功更新,项目仍会恢复到它以前在列表中的位置

如果拖放项目两次,则它将移动到正确的位置

    // Enable jQuery UI Sortable functionality
    $(function() {
      $('.bank-entries').sortable({
        axis: "y",
        containment: "parent",
        tolerance: "pointer",
        revert: 150,
        start: function (event, ui) {
            ui.item.indexAtStart = ui.item.index();
        },
        stop: function (event, ui) {
            var data = {
                indexStart: ui.item.indexAtStart,
                indexStop: ui.item.index(),
                accountType: "bank"
            };
            AppActions.sortIndexes(data);
        },
      });
    });

    // This is the array that holds the positions of the list items
    var _todoItems = {bank: []};

    var AppStore = assign({}, EventEmitter.prototype, {
      getTodoItems: function() {
        return _todoItems;
      },
      emitChange: function(change) {
        this.emit(change);
      },
      addChangeListener: function(callback) {
        this.on(AppConstants.CHANGE_EVENT, callback);
      },
      sortTodo: function(todo) {
        // Dynamically choose which Account to target
        targetClass = '.' + todo.accountType + '-entries';

        // Define the account type
        var accountType = todo.accountType;

        // Loop through the list in the UI and update the arrayIndexes
        // of items that have been dragged and dropped to a new location
        // newIndex is 0-based, but arrayIndex isn't, hence the crazy math
        $(targetClass).children('form').each(function(newIndex) {
          var arrayIndex = Number($(this).attr('data-array-index'));
          if (newIndex + 1 !== arrayIndex) {
            // Update the arrayIndex of the element
            _todoItems[accountType][arrayIndex-1].accountData.arrayIndex = newIndex + 1;
          }
        });

        // Sort the array so that updated array items move to their correct positions
        _todoItems[accountType].sort(function(a, b){
          if (a.accountData.arrayIndex > b.accountData.arrayIndex) {
            return 1;
          }
          if (a.accountData.arrayIndex < b.accountData.arrayIndex) {
            return -1;
          }
          // a must be equal to b
          return 0;
        });

        // Fire an event that re-renders the UI with the new array
        AppStore.emitChange(AppConstants.CHANGE_EVENT);
      },
    }


  function getAccounts() {
    return { data: AppStore.getTodoItems() }
  }

  var Account = React.createClass({
      getInitialState: function(){
          return getAccounts();
      },
      componentWillMount: function(){
          AppStore.addChangeListener(this._onChange);

          // Fires action that triggers the initial load
          AppActions.loadComponentData();
      },
      _onChange: function() {
          console.log('change event fired');
          this.setState(getAccounts());
      },
      render: function(){
          return (
              <div className="component-wrapper">
                  <Bank data={this.state.data} />
              </div>
          )
      }
  });
//启用jQuery UI可排序功能
$(函数(){
$('.bank entries')。可排序({
轴:“y”,
遏制:“家长”,
公差:“指针”,
回复:150,
开始:功能(事件、用户界面){
ui.item.indexAtStart=ui.item.index();
},
停止:功能(事件、用户界面){
风险值数据={
indexStart:ui.item.indexAtStart,
indexStop:ui.item.index(),
账户类型:“银行”
};
应用分类指数(数据);
},
});
});
//这是保存列表项位置的数组
var_todoItems={bank:[]};
var AppStore=assign({},EventEmitter.prototype{
getTodoItems:函数(){
返回待办事项;
},
emitChange:功能(更改){
这个。发射(改变);
},
addChangeListener:函数(回调){
this.on(AppConstants.CHANGE\u事件,回调);
},
Sortodo:函数(todo){
//动态选择目标帐户
targetClass='.+todo.accountType+'-entries';
//定义帐户类型
var accountType=todo.accountType;
//在UI中循环浏览列表并更新ArrayIndex
//已拖放到新位置的项目的列表
//newIndex是基于0的,但arrayIndex不是,因此需要进行疯狂的计算
$(targetClass).children('form')。每个(函数(newIndex){
var arrayIndex=Number($(this.attr('data-array-index'));
if(newIndex+1!==arrayIndex){
//更新元素的arrayIndex
_todoItems[accountType][arrayIndex-1].accountData.arrayIndex=newIndex+1;
}
});
//对数组进行排序,以便更新的数组项移动到正确的位置
_todoItems[accountType].sort(函数(a,b){
如果(a.accountData.arrayIndex>b.accountData.arrayIndex){
返回1;
}
if(a.accountData.arrayIndex
由于React使用虚拟DOM,因此必须使用函数React.findDOMNode()来访问实际的DOM元素

我将在组件的componentDidMount方法中调用jQuery UI函数,因为必须已经呈现元素才能访问

// You have to add a ref attribute to the element with the '.bank-entries' class
$( React.findDOMNode( this.refs.bank_entries_ref ) ).sortable( /.../ );
(你需要知道的一切都在这里)


希望这有意义并解决您的问题

jQueryUISortable不能与React一起工作的原因是它直接变异了DOM,这在React中是一个很大的禁忌


要使其正常工作,您必须修改jQuery UI Sortable,以便保留DnD功能,但当您删除元素时,它不会修改DOM。相反,它可能会触发一个事件,用元素的新位置触发React渲染。

诀窍是调用
Sortable('cancel')
在可排序的
停止
事件中,然后让React更新DOM

componentDidMount() {
    this.domItems = jQuery(React.findDOMNode(this.refs["items"]))
    this.domItems.sortable({
        stop: (event, ui) => {
            // get the array of new index (http://api.jqueryui.com/sortable/#method-toArray)
            const reorderedIndexes = this.domItems.sortable('toArray', {attribute: 'data-sortable'}) 
            // cancel the sort so the DOM is untouched
            this.domItems.sortable('cancel')
            // Update the store and let React update (here, using Flux)
            Actions.updateItems(Immutable.List(reorderedIndexes.map( idx => this.state.items.get(Number(idx)))))
        }
    })
}

下面是一个可能有用的例子:感谢@MikeDriver的建议,但这句话让我不想说“需要注意的关键是我们让render()方法什么都不做”。我正试图利用渲染方法来保持React/Flux架构。我觉得如果你偏离React架构,使用jquery插件而不是React固有的等效功能,那么就必须做出妥协。我不是说你不应该在React中使用jquery插件-显然,在某些情况下re这是唯一可行的解决方案,但是,如果想让事情保持“反应”状态,那就有点像是在马从IMO跑出去后关上牲口棚的门。谢谢!这是迄今为止我发现的最简单的解决方法!是的!
cancel
是唯一有效的方法——100%优于实现“可排序”的ReactJS组件