动态生成行,序号随之增加,删除后依然按顺序。所以给动态生成的html元素绑定click事件

本文探讨了在动态生成HTML元素后绑定事件监听的问题。通过使用onclick内联方式解决了事件重复绑定的问题,并实现了添加行及删除时序列号的自动调整。

转自:http://blog.youkuaiyun.com/github_37745328/article/details/60143774

动态添加html元素以后再去事件监听出问题。在实际开发中会遇到要给动态生成的html元素绑定触发事件的情况。
这里写图片描述
就是上面的一张表格要动态实现添加行,然后序列号还要随着增加,当删除的时候序列号依旧是按顺序排列。
刚开始使用jQuery的on方法来解决,但是发现一个问题会出现事件绑定很多次的问题。然后查询了网上的一些资料,使用live进行事件委托,然而还是出现事件绑定多次bug,很崩溃。最后试着用onclick内联,可以完美解决,这里其实有点困惑,但是算是比较完美的解决这个问题。
html:

 <div class="col-sm-12">
           <div class="panel panel-primary">
              <div class="panel-body">
                <div class="block-content collapse in">
                  <div class="span12">
                    <table id="volTab"  class="table">
                          <thead>
                            <tr>
                              <th>ID</th>
                              <th>姓名</th>
                              <th>证件号码</th>
                              <th>手机号码</th>
                              <th>银行卡号</th>
                              <th>E-mail</th>
                              <th>地址</th>
                              <th>删除</th>
                            </tr>
                          </thead>
                          <tbody>
                            <tr id="1">
                            <td>1</td>
                            <td><div><input type="text" class="form-control"/></div></td>
                            <td><div><input type="text" class="form-control"/></div></td>
                            <td><div><input type="text" class="form-control"/></div></td>
                            <td><div><input type="text" class="form-control"/></div></td>
                            <td><div><input type="text" class="form-control"/></div></td>
                            <td><div><input type="text" class="form-control"/></div></td>
                            <td><i class="fa fa-fw fa-minus"></i></td>
                            </tr>
                          </tbody>
                        </table>
                    </div>
                </div>
           </div>
           </div> 
           <button type="button" id="add" style="width:100px;float:left;margin:0 auto;margin-left:40%" class="btn btn-block btn-primary">添加</button>
            <button type="button" id="submit" style="width:100px;float:left;margin:0 auto;margin-left:5px" class="btn btn-block btn-default">提交</button>
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

js:

<script>
 $("#add").click(function(){
        var len=$("#volTab tr").length;    
        $("#volTab").append("<tr id="+len+">"
                               +"<td>"+len+"</td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><i class='fa fa-fw fa-minus' onclick=\'deltr("+len+")\'"+"'></i></td>"+"</tr>");
     });
  var deltr =function(index)
  {
      debugger;
      var b=$("#volTab tr").length;
      $("#"+index).remove();    
     for(var i=index+1,j=index;i<=b;i++,j++){
                 $("#"+i).replaceWith("<tr id="+(i-1)+">"
                               +"<td>"+(i-1)+"</td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><input type='text' class='form-control'></td>"
                               +"<td><i class='fa fa-fw fa-minus' onclick=\'deltr("+(i-1)+")\'"+"'></i></td>"+"</tr>");

            }
  }
</script>

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
<template> <view class="sort-container"> <!-- 顶部导航:返回居左 + 标题居中(保持不变) --> <view class="sort-nav"> <text class="nav-btn back-btn" @click="navigateBack">返回</text> <view class="nav-title-wrapper"> <text class="nav-title">排序</text> </view> <view class="nav-placeholder"></view> </view> <!-- 核心修改:删除拖拽容器,仅保留网格展示 --> <view class="images-grid"> <!-- 网格容器:一排2张,间距10rpx --> <view class="grid-container"> <!-- 遍历图片列表成网格项 --> <view class="grid-item" v-for="(img, idx) in sortedImages" :key="img.key"> <view class="image-item"> <image :src="img.path" class="sort-image" mode="cover"></image> <!-- 序号标签(与索引绑定,自动排序) --> <view class="image-index">{{ idx + 1 }}</view> <!-- 删除按钮(阻止事件冒泡) --> <view class="delete-btn" @click.stop="deleteImage(idx)"> <image src="/static/lawyerletter/delete.svg" class="delete-icon"></image> </view> </view> </view> </view> </view> <!-- 底部操作栏:添加图片 + 确认排序(保持不变) --> <view class="bottom-action"> <text class="add-img-btn" @click="addImage"> <image src="/static/lawyerletter/add.svg" class="add-icon"></image> <text>添加图片</text> </text> <button class="confirm-btn" @click="confirmSort">确定</button> </view> </view> </template> <script setup> import { onLoad} from '@dcloudio/uni-app'; import { ref, onUnmounted , nextTick } from 'vue'; // 1. 布局参数(适配网格展示) const GAP = 10; // 图片间距(水平/垂直) const PADDING = 20; // 容器内边距 // 2. 状态管理(删除拖拽相关状态) const sortedImages = ref([]); // 排序后的图片数组(仅含路径和唯一key) // 3. 页面加载:接收上级页面图片并初始化(删除拖拽坐标相关逻辑) onLoad((options) => { if (options.images) { try { const imgPaths = JSON.parse(decodeURIComponent(options.images)); // 初始化图片列表(仅保留路径和唯一key,删除x/y坐标) sortedImages.value = imgPaths.map((path, idx) => ({ path, key: `img_${idx}_${Date.now()}` // 唯一key确保列表渲染稳定 })); } catch (error) { console.error('解析图片路径失败:', error); sortedImages.value = []; } } }); // 4. 删除图片:删除后自动更新排序(删除拖拽相关对齐逻辑) const deleteImage = (idx) => { if (sortedImages.value.length <= 1) { uni.showToast({ title: '至少保留1张图片', icon: 'none' }); return; } uni.showModal({ title: '删除图片', content: '确定要删除这张图片吗?', success: (res) => { if (res.confirm) { sortedImages.value.splice(idx, 1); // 直接删除对应索引图片 // 序号随数组索引自动更新,无需额外处理 } } }); }; // 5. 添加图片:保持网格布局一致性(删除拖拽坐标相关逻辑) const addImage = () => { uni.showActionSheet({ itemList: ['拍照', '从相册选择'], success: (res) => { const sourceType = res.tapIndex === 0 ? ['camera'] : ['album']; uni.chooseImage({ count: 20 - sortedImages.value.length, // 最多补充到20张 sourceType, sizeType: ['compressed'], success: (res) => { if (res.tempFilePaths.length > 0) { // 新增图片添加到列表末尾(仅保留路径和key) const newImages = res.tempFilePaths.map((path, addIdx) => ({ path, key: `img_${sortedImages.value.length + addIdx}_${Date.now()}` })); sortedImages.value.push(...newImages); // 提示用户 uni.showToast({ title: `添加${res.tempFilePaths.length}张图片`, icon: 'success' }); } }, fail: (err) => { if (err.errMsg.includes('deny')) { uni.showModal({ title: '权限不足', content: `请开启${sourceType[0]}权限`, confirmText: '去设置', success: (res) => res.confirm && uni.openSetting() }); } } }); } }); }; // 6. 确认排序:同步结果到上级页面(删除拖拽对齐逻辑) const confirmSort = () => { // 提取排序后的图片路径(直接按当前数组顺序) const sortedPaths = sortedImages.value.map(img => img.path); // 通知上级页面更新图片顺序 uni.$emit('imagesSorted', sortedPaths); // 返回上级页面 navigateBack(); }; // 7. 返回上级页面(保持不变) const navigateBack = () => { uni.navigateBack(); }; // 8. 页面卸载:清理事件监听(保持不变) onUnmounted(() => { uni.$off('imagesSorted'); }); </script> <style scoped> /* 全局容器:100%高度,flex垂直布局(保持不变) */ .sort-container { height: 100vh; display: flex; flex-direction: column; background-color: #fff; overflow: hidden; } /* 1. 顶部导航样式(保持不变) */ .sort-nav { display: flex; align-items: center; height: 88rpx; padding: 0 24rpx; border-bottom: 1rpx solid #eee; background-color: #fff; position: sticky; top: 0; z-index: 10; } .nav-btn { padding: 10rpx 20rpx; border-radius: 8rpx; min-width: 100rpx; text-align: center; font-size: 28rpx; color: #333; cursor: pointer; } .nav-title-wrapper { flex: 1; display: flex; justify-content: center; align-items: center; } .nav-title { font-size: 32rpx; font-weight: bold; color: #333; } .nav-placeholder { min-width: 100rpx; } /* 2. 图片网格核心样式(删除拖拽相关样式,保留网格) */ .images-grid { flex: 1; padding: 20rpx; box-sizing: border-box; overflow-y: auto; /* 图片超出时垂直滚动 */ background-color: #fafafa; /* 滚动条美化(可选) */ &::-webkit-scrollbar { width: 6rpx; } &::-webkit-scrollbar-thumb { background-color: #ddd; border-radius: 3rpx; } } /* 网格容器:一排2列,间距10rpx */ .grid-container { display: grid; grid-template-columns: repeat(2, 1fr); /* 2列均分宽度 */ grid-gap: 10rpx; /* 行列间距10rpx */ } /* 网格项:固定宽高比(正方形) */ .grid-item { aspect-ratio: 1 / 1; /* 宽高比1:1,正方形图片 */ border-radius: 8rpx; overflow: hidden; box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08); background-color: #fff; } /* 图片容器:相对定位承载子元素(保持不变) */ .image-item { width: 100%; height: 100%; position: relative; } /* 图片样式:填充容器,保持比例(保持不变) */ .sort-image { width: 100%; height: 100%; object-fit: cover; /* 避免图片拉伸变形 */ } /* 序号标签:左上角悬浮(保持不变) */ .image-index { position: absolute; top: 8rpx; left: 8rpx; background-color: rgba(0, 0, 0, 0.6); color: #fff; font-size: 26rpx; font-weight: bold; width: 38rpx; height: 38rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; z-index: 2; } /* 删除按钮:右下角悬浮(保持不变) */ .delete-btn { position: absolute; bottom: 8rpx; right: 8rpx; width: 38rpx; height: 38rpx; border-radius: 50%; background-color: rgba(0, 0, 0, 0.6); display: flex; align-items: center; justify-content: center; z-index: 2; transition: background-color 0.2s ease; cursor: pointer; } .delete-btn:active { background-color: rgba(231, 76, 60, 0.8); } .delete-icon { width: 24rpx; height: 24rpx; color: #fff; } /* 3. 底部操作栏样式(保持不变) */ .bottom-action { display: flex; align-items: center; justify-content: space-between; height: 132rpx; border-top: 1rpx solid #eee; padding: 0 24rpx; gap: 20rpx; background-color: #fff; position: sticky; bottom: 0; z-index: 10; } .add-img-btn { display: flex; align-items: center; justify-content: center; border-radius: 20rpx; width: 140rpx; font-size: 24rpx; color: #333; cursor: pointer; } .add-icon { width: 24rpx; height: 24rpx; margin-right: 8rpx; } .confirm-btn { background-color: #e74c3c !important; color: #fff !important; width: 400rpx !important; height: 70rpx !important; line-height: 70rpx !important; border-radius: 35rpx !important; font-size: 30rpx !important; font-weight: 500 !important; display: flex !important; align-items: center !important; justify-content: center !important; padding: 0 !important; margin: 0 !important; border: none !important; box-shadow: none !important; } .confirm-btn:active { opacity: 0.8; } </style> 根据这个带啊吗修改 将图片拖拽位置后自动排序
最新发布
09-18
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值