前端踩的一些坑
前端踩的一些坑
本节内容
- 事件代理
- 清除标签的所有事件
- bootstrap的模态框自定义方法
- ajax在django里面实现post提交
- ajax提交数据嵌套
1.事件代理
之前写前端的时候发现在ajax里面获取到的部分html插入到主页面中,插入的部分html中的button始终无法绑定click事件。。。各种找问题,最后发现锅是在页面刚请求到的时候,那部分ajax请求到的页面还没有加载到主html中,js绑定事件的时候找不到这个标签,于是就绑定失败。
之后在网上找相关资料,原来js里面有一个概念叫做事件代理和委托,能够解决我的问题。
既然说到了事件代理和委托,那就得涉及到事件冒泡和捕获的概念了。这里应用大饼卷馒头蘸米饭的部分内容:
事件冒泡及捕获
之前的介绍中已经说到了浏览器的事件冒泡机制。这里再详细介绍一下浏览器处理DOM事件的过程。对于事件的捕获和处理,不同的浏览器厂商有不同的处理机制,这里我们主要介绍W3C对DOM2.0定义的标准事件。
DOM2.0模型将事件处理流程分为三个阶段:一、事件捕获阶段,二、事件目标阶段,三、事件起泡阶段。如图:
事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。
也就是说既然我无法在请求到的部分html中绑定click事件,那么我可以在它的父标签上面绑定click事件,当子标签的click事件被触发之后,如果子标签没有绑定,那么这个时间将会冒泡到父标签上(或者先被父标签捕获,而不到达子标签上)。这样就可以实现绑定ajax获取的html里面的标签的click事件了。
jquery代码实现如下:
$(".body_right").click(".btn",function (env){ var btn=$(env.target); console.log(btn) })
这里面的.body_right就是父标签,在父标签上绑定click事件,监听下面的所有(.btn)按钮,当事件被触发的时候,在function的参数里面会传递一个env参数,这个参数里面有一个target属性,通过env.target可以直接拿到被点击的按钮element。之后就可以为所欲为了,哈哈哈。
当然,事件代理也可以用在需要绑定多个子标签的事件上,如果需要绑定多个子标签的click事件,那么js里面需要循环遍历子标签,给每个子标签绑定事件,jquery可以使用each绑定一组子标签,但是事件代理直接绑定这些子标签的父标签,当有事件触发时可以直接找到被点击的子标签,可以大大简化js代码。
2.清除标签的所有事件
上面说发现了一个好东西,事件代理,那么这个好东西当然要用在代码里面去了,但是我发现一个问题,那就是当一个标签绑定了多个事件代理之后,会出现一个问题。。。就是一个事件被多次触发。。。(现实效果是第一次点击,发送一次ajax提交,第二次点击发送两次ajax提交,第三次点击发送3次ajax提交...)为了解决这个问题,就需要在标签被绑定事件之前,先清除其它所有绑定事件对该标签的影响,这里有一个土办法,那就是在jquery里面有一个方法.off()这个方法可以将绑定标签的所有事件清除。下面是jquery代码:
$(".modal-content").off().click("button",function(ev) { console.log($(ev.target)) })
3.bootstrap的模态框自定义方法
项目里面用到了模态框,觉得bootstrap的模态框挺漂亮的,于是拿过来用了用,确实不错,但是当我想自定义模态框里面的东西的时候,发现了一个问题,那就是自己设计的(确定)按钮点击之后模态框并没有关闭,之后去官网找文档,发现bootstrap的模态框里面提供了一些方法来帮助我们实现自定义模态框的操作。 下面是官方文档的内容:
.modal(options) 将页面中的某块内容作为模态框激活。接受可选参数 object。 $('#myModal').modal({ keyboard: false }) .modal('toggle') 手动打开或关闭模态框。在模态框显示或隐藏之前返回到主调函数中(也就是,在触发 shown.bs.modal 或 hidden.bs.modal 事件之前)。 $('#myModal').modal('toggle') .modal('show') 手动打开模态框。在模态框显示之前返回到主调函数中 (也就是,在触发 shown.bs.modal 事件之前)。 $('#myModal').modal('show') .modal('hide') 手动隐藏模态框。在模态框隐藏之前返回到主调函数中 (也就是,在触发 hidden.bs.modal 事件之前)。 $('#myModal').modal('hide') 也就是说绑定(确定)按钮的时候,可以触发模态框的hide事件: $('#Mymodal').modal('hide') //隐藏模态框
$('#Mymodal').modal('show') //显示模态框
4.ajax在django里面实现post提交
由于django默然开启了csrf攻击防护,其实就是在post提交的时候检查如果请求体里面没有它发给你的token,那么就不接受这个post提交并返回403 forbidden错误,那么在ajax提交post数据的时候,需要自己构造一个键值对{csrfmiddlewaretoken: {% csrf_token %}},但是这样用的话js就必须放在html里面让django进行模板渲染,如果js想放在js文件里面的话就需要在html里面定义一个{% csrf_token %},这样会生成一个hidden的input标签,通过js找到这个标签,拿到value,再拼接到ajax的data里面去,就可以实现了。jquery代码如下:
$.ajax("/del_student/",{ type:"POST", data:{id:id,csrfmiddlewaretoken: csrf_token}, success:show_student, complete:$('#Mymodal').modal('hide') });
5.ajax提交数据嵌套
如果ajax提交的数据里面有嵌套,那么在提交的时候需要设定一个参数traditional:"true",默然traditional是false的,那么后端获取嵌套数据的时候将会出问题,将traditional设置成true就可以了。