vue学习:事件传递(冒泡和捕获),事件委托,jquery中的事件委托,$event 获取元素,vue事件修饰符 快来打我* 2021-09-19 14:52 627阅读 0赞 ### **事件传递 ----冒泡和捕获** ### **DOM事件标准定义了两种事件流**,这两种事件流分别是捕获和冒泡。 和许多Web技 术一样,在它们成为标准之前,Netscape和微软各自不同地实现了它们。Netscape选择实现了捕获事件流,微软则实现了冒泡事件流。幸运的 是,W3C决定组合使用这两种方法,并且大多数新浏览器都遵循这两种事件流方式。 **默认情况下,事件使用冒泡事件流**,不使用捕获事件流。然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true。 ## ## ### 冒泡事件流: ### 在冒泡过程中的任何时候都可以终止事件的冒泡,在遵从W3C标准的浏览器里可以通 过调用事件对象上的**stopPropagation()**方法,在Internet Explorer里可以通过设置事件对象的**cancelBubble属性为true。**如果不停止事件的传播,事件将一直通过DOM冒泡直至到达文档根。即从被点击的元素到此元素的祖先元素直至根元素,**从下到上**。 ### 捕获事件流: ### 事件的处理将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。在这个过程中,**事件会被从文档 根到事件目标元素之间各个继承派生的元素所捕获**,如果事件监听器在被注册时设置了useCapture属性为true,那么它们**可以被分派给这期间的任何 元素以对事件做出处理**;否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。即根元素到被点击的元素,从上到下。 ### **事件代理(委托)** ### 说明:**事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)。** 原理:事件委托是**利用事件的冒泡原理来实现的** 。事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件。 使用原因: 1. 绑定事件太多,浏览器占用内存变大,严重影响性能; 2. Ajax出现,局部刷新盛行,每次加载完,都要重新绑定事件; 3. 部分浏览器移除元素时,绑定的事件没有被及时移除,导致内存泄漏,严重影响性能; 4. Ajax中重复绑定,导致代码耦合性过大,影响后期维护 如下demo 01,列表在给新增或删除的列表项时,绑定或删除相应事件监听的工作枯燥并繁杂,而使用事件委托,将监听器安装在列表项的父元素上后,当子元素的事件冒泡到父`ul`元素时,只需要检查事件对象的target属性,捕获真正被点击的节点元素的引用。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>测试</title> </head> <body> <div> <ul id="parent-list"> <li id="post-1">Item 1</li> <li id="post-2">Item 2</li> <li id="post-3">Item 3</li> <li id="post-4">Item 4</li> <li id="post-5">Item 5</li> <li id="post-6">Item 6</li> </ul> </div> <script> //找到父元素,添加监听器。。。 document.getElementById('parent-list').addEventListener('click', function (e) { //e.target是被点击的元素 //如果被点击的是li元素 if(e.target && e.target.nodeName =="LI") { //注意这里的nodeName标签名要用大写 e.target.style.color="red"; //执行操作,,, console.log('List item', e.target.id, "was clicked"); } }) </script> </body> </html> ## ## demo02 当需要给所有的a标签绑定click事件时使用事件委托,而部分a标签又包含图片img、span元素,用户希望点击span或img标签也能触发相应的click事件。这时就需要:**从触发click事件的元素开始,逐级向上查找,直到找到a标签为止**。代码如下 document.addEventListener("click", function(e) { var node = e.target; while (node.parentNode.nodeName != "BODY") { if (node.nodeName == "A") { console.log("a"); break; } node = node.parentNode; } }, false); ### **JQuery中的事件委托** ### jQuery中的事件委托方式比较丰富,如下 1、用on方法,代码如下: $(function(){ $("#lists").on("click","li",function(event){ var target = $(event.target); target.css("background-color","red"); }) }) 2.用delegate()方法,代码如下: $(function(){ $("#lists").delegate("li","click",function(event){ var target = $(event.target); target.css("background-color","red"); }) }) on()方法和delegate()方法对于事件委托的写法很像。并且执行事件委托的时候只有子元素(本文中的li)会触发事件,而**代为执行的父元素(本文中为ul)不会触发事件**,所以我们**不需要盘判断触发事件的元素节点名**,这一点明显优于原生的JavaScript。 3.用bind()方法,代码如下: $(function(){ $("#lists").bind("click","li",function(event){ var target = $(event.target); if(target.prop("nodeName")=="LI"){ target.css("background-color","red");} }) }) **bind()方法**同原生的JavaScript实现方法一样,当父元素代子元素执行事件时,父元素也会触发事件,所以我们需要判断一下触发事件的元素名。此外,用bind()方法给元素绑定事件的时候要注意,它只能给已经存在DOM元素添加事件,不能给未来存在DOM 元素添加添加事件。如果要频繁地添加DOM元素,并且给新添加的DOM元素绑定事件的话,用live(),delegate(),on()等方法。**鉴于jQuery从1.7之后就不推荐live()和delegate()方法了,所以大家还是使用on()方法吧**。 ### **vue中使用`$event`:** ### **vue中直接套用上述代码会报错(无法找到target),使用`$event`**`传入到vue组件方法中,如下` <template> <div class="page"> <div> <ul id="parent-list" @click="checkClick($event)"> <li id="post-1">Item 1</li> <li id="post-2">Item 2</li> </ul> </div> </div> </template> <script> export default { name: 'Login', methods: { checkClick:function(e){ if(e.target && e.target.nodeName == 'LI') { //执行操作,,, console.log('List item', e.target.id, "was clicked") } } } } </script> ## ## ### vue中使用$event 获取当前元素、父子兄弟元素 ### <tempalte> <button @click = “getEvent($event)”>点击</button> </template> <script> export default { methods:{ getEvent(e) { console.log(e) // e.target 是你当前点击的元素 // e.currentTarget 是你绑定事件的元素 #获得点击元素的前一个元素 e.currentTarget.previousElementSibling.innerHTML #获得点击元素的第一个子元素 e.currentTarget.firstElementChild # 获得点击元素的下一个元素 e.currentTarget.nextElementSibling # 获得点击元素中id为string的元素 e.currentTarget.getElementById("string") # 获得点击元素的string属性 e.currentTarget.getAttributeNode('string') # 获得点击元素的父级元素 e.currentTarget.parentElement # 获得点击元素的前一个元素的第一个子元素的HTML值 e.currentTarget.previousElementSibling.firstElementChild.innerHTML }, } } </script> ### vue事件处理 ### 如果需要**在内联语句处理器中访问原生DOM事件。可以使用特殊变量`$event`,把它传入到`methods`中的方法中**。 在Vue中,**事件修饰符**处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。在Vue中事件修饰符主要有: * **`.stop`**:等同于JavaScript中的`event.stopPropagation()`,防止事件冒泡 * **`.prevent`**:等同于JavaScript中的`event.preventDefault()`,防止执行预设的行为(比如阻止a链默认跳转和form表单提交,注意:如果事件可取消,则取消该事件,而不阻止事件的进一步传播) * **`.capture`**:与事件冒泡的方向相反,事件捕获由外到内 * **`.self`**:只当事件在该元素本身(而不是子元素)触发时触发回调 * **`.once`**:只会触发一次 <!-- 阻止单击事件冒泡 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件侦听器时使用事件捕获模式 --> <div v-on:click.capture="doThis">...</div> <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 --> <div v-on:click.self="doThat">...</div> ### .stop 阻止事件冒泡 ### 冒泡事件:嵌套两三层父子关系,然后所有都有点击事件,点击子节点,就会触发从内至外 子节点-》父节点的点击事件,如下 <div class="testPage"> <div class="outeer" @click="outer"> <div class="middle" @click="middle"> <button @click="inner">点击我(^_^)</button> </div> </div> <p>{ { message }}</p> </div> <script> export default { name: 'Login', data(){ return { message:'测试冒泡事件', } }, methods: { inner: function () { this.message = 'inner: 这是最里面的Button'; console.log(this.message); }, middle: function () { this.message = 'middle: 这是中间的Div'; console.log(this.message); }, outer: function () { this.message = 'outer: 这是外面的Div'; console.log(this.message); } } } </script> 在点击上加上.stop相当于调用了`event.stopPropagation(),阻止了事件冒泡传递,`点击子节点不会捕获到父节点的事件。`代码如下` <div class="testPage"> <div class="outeer" @click="outer"> <div class="middle" @click.stop="middle"> <button @click="inner">点击我(^_^)</button> </div> </div> <p>{ { message }}</p> </div> 效果如下, ![20190526103551549.jpg][] ### **`.prevent取消默认事件`** ### 说明:该方法将通知 Web 浏览器**不要执行与事件关联的默认动作**(如果存在这样的动作)。例如,如果 type 属性是 "submit",在事件传播的任意阶段可以调用任意的事件句柄,通过调用该方法,可以阻止提交表单。注意,如果 Event 对象的 cancelable 属性是 fasle,那么就没有默认动作,或者不能阻止默认动作。无论哪种情况,调用该方法都没有作用。 如下可以阻止a超链接标签的默认跳转 <a href="home" @click.prevent>跳转</a> ## ## ### .native 修饰符 ### **.native - 监听组件根元素的原生事件。 主要是给自定义的组件添加原生事件。**普通的标签使用.native修饰事件是无效的,如下 <button @click.native="clickFn">测试native的作用</button> <el-button type="primary" @click.native="clickFn">组件上使用native的作用</el-button> ## 按键修饰符 ## 在监听键盘事件时,我们经常需要监测常见的键值。 Vue 允许为 `v-on` 在监听键盘事件时添加按键修饰符: <!-- 只有在 keyCode 是 13 时调用 vm.submit() --> <input v-on:keyup.13="submit"> <input v-on:keyup.enter="submit"> <!-- 缩写语法 --> <input @keyup.enter="submit"> 全部的按键别名:记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名: * `.enter` * `.tab` * `.delete` (捕获 “删除” 和 “退格” 键) * `.esc` * `.space` * `.up` * `.down` * `.left` * `.right` 可以通过全局 `config.keyCodes` 对象自定义按键修饰符: // 可以使用 v-on:keyup.f1 Vue.config.keyCodes.f1 = 112 [20190526103551549.jpg]: /images/20210726/a94d356fd79f46d49b5109c5966afeac.png
还没有评论,来说两句吧...