javascript - 关于jq .on方法的问题。

查看:108
本文介绍了javascript - 关于jq .on方法的问题。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

arr中保存的是div的位置,div可以移动删除,现在的问题是如果删除div,他的位置也会加到arr中并且会重复,请问是执行顺序的问题吗?

var arr=[];
function add(){
    var addDiv=$("<div><span>DM54</span></div>");
    addDiv.addClass("draggable");
    addDiv.draggable();
    $(".box").append(addDiv);
}
$('.box')
     .on('click', '#close', function(){
        $("#popup").hide("slow");
       
    }) 
 .on('dblclick', '.draggable', function(){
    $("#popup").show("slow");
    var that=$(this);
    $('#delete').click(function(){
        that.remove();
        })
         })
   .on('mouseup', '.draggable', function(){
     var cache = $(this).css(['top','left']); 
       var location={
            id: $(this).index()+1,
             X: cache.top,
             Y: cache.left
        };
        arr.push(location);
    }) 

代码地址http://runjs.cn/detail/y2qtieiq (位置值是undefined可能是我粘代码问题可以忽略)

解决方案

看了你在 http://runjs.cn/detail/y2qtieiq 的代码,发现一些问题

[1] - 取位置用 .css(["top", "left"])

这一点是 jQuery 1.9 添加的新语法,我孤陋寡闻了,多谢 @熊猫桑

如果我没记错的话,jQuery 应该不支持这种方式获取多个CSS属性的值,你可以分成两句话来写

var cache = {
    top: $(this).css("top"),
    left: $(this).css("left")
};

或者,直接用 .position()

var cache = $(this).position();
// 注意 position() 取出来的位置只有值,没有单位,这与 css 取出来的不同
cache.top = cache.top + "px";
cache.left = cache.left + "px";

[2] - arr.push(location)

这里每次 mouseup 事件都会 push 一个 location 对象到 arr 中去,然而实际上如果是对同一个对象多次操作,arr 里会保存很多个同一对象的位置

解决办法

在 location 有 ID 的情况下,可以使用 map(即 js 对象) 来解决

var all = {};  // 代替 arr (不要求顺序的情况下)
// ...

// 然后在 push 那里改为
all[location.id] = location;

// 之后需要取出来的时候
var data = Object
    .keys(all)
    .map(function(key) { return all[key]; });

[3] - $("#delete").click(...)

这里每境框一次都会绑定一个事件,所以多次弹框之后每次点删除按钮都会触发很多次事件。这里建议你做个初始化绑定,只绑定一次事件。如果你担心每次,或某次弹出来的删除按钮已经不是原来那个了,可以给它加个 .data(...) 值用来标记。

另外,这个事件里用到了 that.remove() 这是没有问题的,问题在于,从 DOM 树里删除了对象,arr 中却仍然存在——其实整个代码中我都没看到哪里有从 arr 里删除对象的代码,所以 arr 的项其实是只增不减的。

解决办法:

var $del = $("#delete");
if (!$del.data("inited")) {
    $del.click(...);
    $del.data("inited", true);
}

然后在 that.remove() 之前(之后好像也可以)

var id = that.data(id);
delete all[id];

不过这样之后,由于 dblclick 事件有可能是不同的 .draggable 触发的,而 $del.click 事件中的 that 是在定义这个事件处理函数的那个 .draggable,所以这里还需要在 .dblclick 中告诉 $del 要删除的是哪一个,然后在 $del 中去删除这一个。(这里有点绕,我一开始没想到,所以是后来补充的这一段)

.on("dblclick", ".draggable", function() {
    $("#popup").show("slow");
    var that = $(this);
    var $del = $("#delete");
    // ① 把触发 dblclick 这个目标给记录下来,备②用
    $del.data("target", that);
    if (!$del.data("inited")) {
        $del.click(function() {
            // ② 从 $del.data 中把目标取出来,要删除的就是这个 $target,
            // 也就是弹框之前双击的那个 .draggable
            var $target = $del.data("target");
            var id = $target.data("id");
            delete all[id];
            $target.remove();
        });
        $del.data("inited", true);
    }
})

[4] - id: $(this).index() + 1

这里单独来看并没有什么问题,但是,这个 index() 是计算是这个元素在当前父元素中是第几个子元素,那么,在 that.remove() 之后,这个 that 后面的所有兄弟元素的 index() 都会发生变化,所以拿它(index())来作为 id 显然是不合适的。同样,建议你通过 .data(...) 来赋予 ID,至于 ID 的取值,你只需要能保证唯一就行了。你甚至可以不要 ID,直接保存对应的 DOM 元素或相应的 jQuery 对象。

 解决办法,生成唯一 ID

var nextId = (function() {
    var id = 1;
    return function() {
        return id++;
    };
})();

// .....

var $this = $(this);
var id = $this.data("id");
if (!id) {
    id = nextId();
    $this.data("id", id);
}

[5] - $("#save").click(...)

这里的 data 中是用的不能唯一对应 DOM 对象的 ID (push(location) 之前在 location 中定义的,上一条已经说明了它的不稳定性)。这还不是仅存的问题,问题是你还要把这个 id 送给服务器,服务器怎么会知道你到底送的是个啥(比如对应的名称是啥)?

解决办法

假设要传递给服务器的是名称。这样的话,需要在生成 location 的时候多加一个属性

location.name = $this.text();

然后在 save 的时候直接序列化前面从 all 中得到的 data 即可。


暂时就发现这些问题,请先思考一下逻辑。写任何程序,代码只是最后的呈现,关键是你要逻辑要经得起推敲!

这篇关于javascript - 关于jq .on方法的问题。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆