jquery实现表格行自定义顺序

2019-12-05  本文已影响0人  超人鸭

这次记录一下刚做的一个功能(需求),使用jquery实现表格行自定义顺序,由于实际工作中这个需求涉及到的条件比较多,所以超人鸭就直接按我工作中的情况来讲这个功能,不做模拟。
先看看实现的具体功能:


image.png

表格行的排序是输入框,正常情况下是不可编辑的,当点击上面的编辑排序按钮后,就可以输入想要更换的顺序,并且显示右边的操作按钮:


image.png
点击保存后保存新的排序,并且表格行按排序更换顺序;点击取消排序号返回到编辑前的情况,并且隐藏操作按钮。这里有几个限制条件,第一,排序号不能重复;第二,排序的范围只能在原本的范围内。
知道需求后开始整理思路:
  1. 输入框只能输入正整数,并且一开始是disable。
  2. 点击了编辑排序后,输入框全部要取消disable,然后显示后面的操作按钮。
  3. 点击取消后,排序号要退回到原来的值,所以要保存原本的排序,所以在上一个事件,点击编辑排序按钮的时候,就需要保存原本的排序,用一个数组保存起来,可以用each去遍历输入框,点击取消后要隐藏操作按钮与让输入框变成disable状态。
  4. 点击保存后,要根据限制条件做校验,先是最大值和最小值,编辑前的排序号已经被我用数组保存起来,所以用这个数组求得正确的最大最小值,然后需要求得编辑后的最大最小值,一样,用一个数组把编辑后的排序保存起来,求得最大最小值,去比较就可以。然后判断是否重复,把编辑后的排序号数组去重,然后和原数组比较长度就可以判断。
  5. 保存成功后,更换表格的顺序,这项目不是vue的数据渲染,所以只能操作dom,我的思路是用删除表格行再按特定的顺序插进去来实现,这里用到jq两个操作dom的api,prependafter,那如果获取到特定顺序的表格行呢,需要和输入框的做关联,输入的排序号是输入框的value,用到value选择器:
    $("input[value = '1']"),根据这个输入框来获取到表格行。
    接下来就是具体实现了,先看看大概的html:
// 表格里面
<table>
  <tbody>
    <tr>
      <td>
        <input type="text" name="order-input" disabled onkeyup="changeValue(this)" >
      </td>
    </tr>
    .....
  </tbody>
</table>

// 表格上面的按钮
<span class="order-edit-btn">编辑排序</span>
<div style="display: none;">
  <button class="save-order-btn">保存</button>
  <button class="cancel-order-btn">取消</button>
</div>

大概的html就是这样,因为实际开发还有其他条件,所以都是用class来当选择器。接下来是实现:

  1. 输入框的限制放在最后,涉及到其他问题,首先点击编辑排序的时候:
var orderList = []  // 保存原排序的数组,全局变量
var maxOrder = 0  // 正确的最大值,全局变量
var minOrder = 0 // 正确的最小值,全局变量

$(".order-edit-btn").click(function () {
  $(this).next().show() // 显示操作按钮
  $('table').find("input[name='order-input']").attr("disabled",false)  // 让序号输入框可以输入
  
  orderList = []  // 重置
  $('table').find("input[name='order-input']").each(function(){  // 得到全部序号的数组
    orderList.push(parseInt($(this).val()))
  })
  
  maxOrder = Math.max.apply(Math,orderList)  // 得到最大值
  minOrder = Math.min.apply(Math,orderList)  // 得到最小值
})
  1. 点击取消按钮的事件:
$(".cancel-order-btn").click(function() {
  $('table').find("input[name='order-input']").each(function (index) {  // 让排序号撤回到编辑前的值
    $(this).val(orderList[index])
  })

  $('table').find("input[name='order-input']").attr("disabled",true) // 让序号不可编辑
  
  $(this).parent().hide()  // 隐藏操作按钮
})
  1. 点击保存按钮,需要对新编辑的排序号做校验,所以需要再声明一个数组:
$(".save-order-btn").click(function () {
  var newOrderList = []  // 保存编辑后的排序号
  $('table').find("input[name='order-input']").each(function() {
    newOrderList.push(parseInt($(this).val()))
  })
  var newMaxOrder = Math.max.apply(Math, newOrderList)  // 得到新的最大值
  var newMixOrder = Math.min.apply(Math, newOrderList)  // 得到新的最小值
  // 下面是校验
  if (newMixOrder < minOrder) {
    alert('最小值不能小于' + minOrder)
    return
  }
  if(newMaxOrder > maxOrder) {
    alert('最大值不能小于' + maxOrder)
    return
  }
  newOrderList = newOrderList.filter((x, index, self) => self.indexOf(x) === index)  // 去重
  if (newOrderList.length < orderList.length) {
    alert('不能出现重复序号')
    return
  }

  // 到这里如果没问题排序号就已经更新了,接下来是要实现表格行的更换顺序
  /*上面说到,需要先把表格行先删掉,再插入到对应的位置,这里离分为两种情况,第一条也就是序号为一的表格行和其他表格行,如果是第一条表格行就
    直接插入到表格的最上面,用到prepend,其他情况就是插到上一个行的后面,用到after,所以需要获取到上一个行的dom,下面看实现
  */
  var prevTrDom = null  // 保存上一个行的dom
  for (var i = minOrder; i <= maxOrder; i++) {
    if (i === minOrder) {  // 如果是第一行的情况下
      let temDom = $("input[name='order-input'][value = " + i + "]").parent().parent() // 保存这个tr的dom,重要
      $("input[name='order-input'][value = " + i + "]").parent().parent().remove()  // 先将这个dom在表格里面删掉
      $('table').find('tbody').prepend(temDom) // 在表格的最前面插入这个行
      prevTrDom = temDom  // 此时代表上一行的dom就是这一行 

    } else {   // 除了第一行的其他行
      let temDom = $("input[name='order-input'][value = " + i + "]").parent().parent() // 同样要先保存
      $("input[name='order-input'][value = " + i + "]").parent().parent().remove()  // 删掉
      prevTrDom.after(temDom) // 插入
      prevTrDom = temDom  // 更新代表上一行的dom
    }
  }

  $('table').find("input[name='order-input']").attr("disabled", true)  // 同样让输入框恢复不可编辑
  $(this).parent().hide()  // 隐藏操作按钮
})

理论上来说,写到这里除了输入框的限制输入正整数外,需求功能都实现了。但还有一个问题,看上面的实现表格更换顺序,里面最关键的就是获取到与排序号关联的表格行tr:

 $("input[name='order-input'][value = " + i + "]").parent().parent()

我用到input的value选择器,注意里面如果要写变量要想我那样写,不然 i 会被识别成字符串。可能是之前做的都是vue的项目,都习惯了数据的双向绑定与动态更新,但是在原生dom里面的输入框,当你输入后,它的value是不会实时更新的:


image.png

可以看到还是我改变前输入的值,所以上面说到的排序号,虽然我编辑了,输入框的值改变了,但是它的value还是没有变,所以上面的实现表格更换顺序会没有反应,所以现在的问题就是实现输入框一输入,它的value就会更新,超人鸭在百度找到了一个方法,刚好可以和限制输入框只能输入正整数写在一起。还记得我上面写的输入框的html代码吗?

<input type="text" name="order-input" disabled onkeyup="changeValue(this)" >

监听输入框的onkeyup事件:

function changeValue(obj) {
  $(obj).attr("value",$(obj).val().replace(/^(0+)|[^\d]+/g,''));
}

实现了输入框vlaue的实时更新与正则匹配过滤掉非正整数。
到这里就完成了所说的功能,欢迎留言指教。
作者微信: ***Promise_fulfilled ***

上一篇下一篇

猜你喜欢

热点阅读