Day10.事件下(学习日记10)
事件的傳播流程
事件流的傳播有三個流程
- 捕獲階段
- 目標階段
- 冒泡階段
事件流的兩種模式
冒泡模式(從里到外 逐層執行對應的事件)
冒泡模式是常用的模式,他現在默認設計模式就是冒泡模式.
```html
<div οnclick="alert(1)">
? ? <button οnclick="alert(2)"></button>
</div>
<script>
? ? document.body.onclick = function () {
? ? ? ? alert(3)
? ? }
? ? document.onclick = function () {
? ? ? ? alert(4)
? ? }
? ? window.onclick = function () {
? ? ? ? alert(5)
? ? }
</script>
以上這個示例 會從button開始不斷向上執行 直到window停止 所以對應的執行結果為2 1 3 4 5
如果我們不想觸發對應的外層事件 只是想觸發本身的事件 那我們就需要禁止冒泡事件了
禁止事件冒泡的處理
stopPropagation(event對象的方法 對于低版本的IE瀏覽器不支持)
document.querySelector('button').onclick = function(e){
? ? //事件源對象
? ? e = e || window.event
? ? //禁止事件冒泡的方法
? ? e.stopPropagation()
? ? alert(2)
}
cancelBubble(event對象的屬性)
//cancelBubble 取消冒泡 默認為false
e.cancelBubble = true
兼容寫法
e.stopPropagation?e.stopPropagation():e.cancelBubble = true
捕獲模式(從外到里 逐層執行對應的事件)
捕獲模式是火狐瀏覽器提出來的模式,IE對應的6,7,8版本不支持.現在的模式一般很少用到捕獲模式.
默認行為
元素標簽有其默認行為(a標簽會默認跳轉頁面 form標簽里面的submit默認提交(刷新),對應的事件也有其默認行為(contextmenu會出現對應的菜單欄等))
e.defaultPrevented 檢查當前是否禁止默認行為
console.log(e.defaultPrevented) //是否阻止默認行為 只讀 默認為false
禁止默認行為
preventDefault(event對象的方法)
e.preventDefault() //preventDefault阻止默認行為
returnValue(event對象的屬性)
e.returnValue = false //兼容ie的
兼容寫法
e.preventDefault?e.preventDefault():e.returnValue = false
return false
//對應的右鍵點擊
window.oncontextmenu = function(e){
? ? console.log('右鍵點擊了')
? ? // e.preventDefault?e.preventDefault():e.returnValue=false
? ? return false //一定要放在最后
}
示例
右鍵點擊出現對應的菜單欄 這個菜單欄自定義(前進功能 后退功能 刷新功能 換膚 打印)
<style>
? ? ? ? * {
? ? ? ? ? ? margin: 0;
? ? ? ? ? ? padding: 0;
? ? ? ? }
? ? ? ? ul {
? ? ? ? ? ? list-style: none;
? ? ? ? ? ? width: 80px;
? ? ? ? ? ? border: 2px solid black;
? ? ? ? ? ? display: none;
? ? ? ? ? ? position: absolute;
? ? ? ? ? ? border-radius: 5px;
? ? ? ? }
? ? ? ? li {
? ? ? ? ? ? border-bottom: 1px solid #000;
? ? ? ? ? ? width: 80px;
? ? ? ? ? ? box-sizing: border-box;
? ? ? ? ? ? line-height: 30px;
? ? ? ? ? ? text-align: center;
? ? ? ? }
? ? </style>
</head>
<body>
? ? <a href="https://www.4399.com/">4399</a>
? ? <ul>
? ? ? ? <li οnclick="history.forward()">前進</li>
? ? ? ? <li οnclick="history.back()">后退</li>
? ? ? ? <li οnclick="location.reload()">刷新</li>
? ? ? ? <li οnclick="document.body.style.backgroundColor=randomColor()">換膚</li>
? ? ? ? <li οnclick="print">打印</li>
? ? </ul>
</body>
</html>
<script>
? ? //事件委托
? ? //獲取父元素
? ? var ul = document.querySelector('ul')
? ? //移入對應的ul內
? ? ul.onmouseover = function (e) {
? ? ? ? e = e || window.event
? ? ? ? if (e.target.nodeName == 'LI') {
? ? ? ? ? ? //排他
? ? ? ? ? ? for (var li of ul.children) {
? ? ? ? ? ? ? ? li.style.backgroundColor = '#fff'
? ? ? ? ? ? }
? ? ? ? ? ? e.target.style.backgroundColor = '#ccc'
? ? ? ? }
? ? }
? ? //右鍵點擊
? ? window.oncontextmenu = function (e) {
? ? ? ? e = e || window.event
? ? ? ? e.parventDefault ? e.parventDefault() : e.returnValue = false
? ? ? ? //顯示ul
? ? ? ? ul.style.display = 'block'
? ? ? ? //改變ul的定位
? ? ? ? ul.style.left = e.pageX + 'px'
? ? ? ? ul.style.top = e.pageY + 'px'
? ? }
? ? //點擊對應的li 使用事件委托隱藏對應的ul
? ? ul.onclick = function (e) {
? ? ? ? e = e || window.event
? ? ? ? if (e.target.nodeName == 'LI') {
? ? ? ? ? ? this.style.display = 'none'
? ? ? ? }
? ? }
? ? function randomColor() {
? ? ? ? var r = Math.random() * 256
? ? ? ? var g = Math.random() * 256
? ? ? ? var b = Math.random() * 256
? ? ? ? return `rgb(${r},${g},${b})`
? ? }
</script>
事件監聽器
eventListener他是一個標準的觀察者模式,他是通過對應的監聽器來監聽事件的觸發和執行.
主要有兩個方法
- addEventListener 添加事件監聽器
- removeEventListener 移除事件監聽器
addEventListener
傳入對應的事件名及處理函數以及對應的是否冒泡
//獲取按鈕
var btn ?= document.querySelector('button')
//添加事件監聽器 傳入 事件名 處理函數 ?是否捕獲(默認的事件模式 冒泡 false 捕獲 true)
// btn.addEventListener('click',function(){
// ? console.log('按鈕點擊了')
// })//指定為冒泡模式
// btn.addEventListener('click',function(){
// ? console.log('按鈕點擊了1')
// },true)//指定為捕獲模式 先執行
// btn.addEventListener('click',function(){
// ? console.log('按鈕點擊了2')
// })
//addEventListener 他可以給一個事件添加多個處理函數
//一個事件 有一個處理函數的數組
//事件監聽器中的事件名 支持自定義
// btn.addEventListener('dblclick',function(){
// ? console.log('雙擊')
// })
//直接使用onclick 進行賦值的操作他會被覆蓋也就是說他只有一個處理函數 后寫會覆蓋先寫的 (屬性賦值操作)
// document.querySelector('div').onclick = function(){
// ? console.log('div被點擊了')
// }
btn.addEventListener('click',handler,false)//指定為冒泡模式
注意事項
- addEventListener可以在一個事件中傳入多個處理函數(一個事件對應一個處理函數組)
- EventListener支持自定義事件名
- 屬性事件賦值不支持多個處理函數(因為會被覆蓋)
removeEventListener
移除對應的添加事件的監聽器,傳入事件名,處理函數,是否冒泡 每個都必須和添加的事件監聽器一致不能不能被移除
btn.addEventListener('click',handler,false)//指定為冒泡模式
// 要移除的事件名 要移除的處理函數(也要一致 如果是匿名函數那么就不能被移除 對象比對的是地址) 模式也要一致
btn.removeEventListener('click',handler,false) ?
function handler(){
? ? console.log('按鈕點擊了')
}
注意事項
如果添加事件監聽器的時候傳入處理函數為匿名處理函數 那么不能被移除(對象比對的是地址)
拖拽
拖拽原理
- 給對應的需要拖拽的元素添加鼠標按下事件
- 再按下事件內添加給區間的元素對應的鼠標移動事件
- 在按下事件內給document添加對應的鼠標彈起事件? 在彈起事件中釋放移動事件及釋放彈起事件
基礎拖拽
- 獲取拖拽的元素
- 給拖拽元素添加鼠標按下事件 并記錄按下的坐標(在對應的盒子里的坐標)
- 在按下事件內給區間元素添加鼠標移動事件 并記錄每次移動的坐標
- 在區間元素的鼠標移動事件中 設置對應的拖拽元素的坐標(移動的坐標=當前的坐標-鼠標點擊位置的坐標+'px')
- 在按下事件內在document中添加鼠標彈起事件 并釋放之前的移動事件及自身的彈起事件
<div></div>
<script>
var box = document.querySelector('div')
box.onmousedown = function(e){
? ? e = e || window.event
? ? //記錄在而盒子上的坐標
? ? var x = e.offsetX
? ? var y = e.offsetY
? ? //在document中移動
? ? document.onmousemove = function(e){
? ? ? ? e = e || window.event
? ? ? ? //獲取頁面上的坐標
? ? ? ? var currentX = e.pageX
? ? ? ? var currentY = e.pageY
? ? ? ? //移動的坐標 = 當前的坐標 - 鼠標點擊位置的坐標 + 'px'
? ? ? ? box.style.left = currentX - x + 'px'
? ? ? ? box.style.top = currentY - y + 'px'
? ? }
? ? document.onmouseup = function(){
? ? ? ? document.onmousemove = null
? ? ? ? document.onmouseup = null
? ? }
}
</script>
區間拖拽
- 獲取拖拽的元素
- 給拖拽元素添加鼠標按下事件 并記錄按下的坐標(在對應的盒子里的坐標)
- 在按下事件內給區間元素添加鼠標移動事件 并記錄每次移動的坐標
- 在區間元素的鼠標移動事件中 獲取對應的區間元素的位置 及 能夠移動的距離 (區間元素的寬/高度 - 自身的寬/高度)
- 設置移動元素處在區間元素的位置 ?移動位置在父元素的坐標 = ?頁面的位置 - 父元素離頁面的位置 鼠標點擊的位置
- 對應坐標位置進行區間判斷 小于0的時候值應該設置為0 大于能夠移動的距離設為最大的距離
- 在按下事件內在document中添加鼠標彈起事件 并釋放之前的移動事件及自身的彈起事件
<div>
? ? <button>
? ? ? ? 移動的按鈕
? ? </button>
</div>
<script>
? ? var box = document.querySelector('div')
? ? var button = document.querySelector('button')
? ? button.onmousedown = function(e){
? ? ? ? e = e || window.event
? ? ? ? //記錄在而盒子上的坐標
? ? ? ? var x = e.offsetX
? ? ? ? var y = e.offsetY
? ? ? ? //在box中移動
? ? ? ? box.onmousemove = function(e){
? ? ? ? ? ? e = e || window.event
? ? ? ? ? ? //獲取區間元素的位置
? ? ? ? ? ? var bx = this.offsetLeft
? ? ? ? ? ? var by = this.offsetTop
? ? ? ? ? ? //獲取能夠移動的最大距離
? ? ? ? ? ? var maxX = ?this.offsetWidth - button.offsetWidth
? ? ? ? ? ? var maxY = ?this.offsetHeight - button.offsetHeight
? ? ? ? ? ? //移動位置在父元素的坐標 = 頁面的位置 - 父元素離頁面的位置 - 鼠標點擊的位置
? ? ? ? ? ? var targetX = e.pageX - bx - x
? ? ? ? ? ? var targetY = e.pageY - by - y
? ? ? ? ? ? //進行區間判斷
? ? ? ? ? ? if(targetX < 0){
? ? ? ? ? ? ? ? targetX = 0
? ? ? ? ? ? }
? ? ? ? ? ? if(targetY < 0){
? ? ? ? ? ? ? ? targetY = 0
? ? ? ? ? ? }
? ? ? ? ? ? if(targetX > maxX){
? ? ? ? ? ? ? ? targetX = maxX
? ? ? ? ? ? }
? ? ? ? ? ? if(targetY > maxY){
? ? ? ? ? ? ? ? targetY = maxY
? ? ? ? ? ? }
? ? ? ? ? ? button.style.left = targetX + 'px'
? ? ? ? ? ? button.style.top = targetY + 'px'
? ? ? ? }
? ? ? ? document.onmouseup = function(){
? ? ? ? ? ? box.onmousemove = document.onmouseup ?= null
? ? ? ? }
? ? }
</script>
封裝一個方法找盒子到頁面的距離
function getBoxToPageDistance(element){
? ? var distance = {
? ? ? ? x:0,
? ? ? ? y:0
? ? } //距離對象
? ? while(element.offsetParent){ //找到body就停止
? ? ? ? distance.x += element.offsetLeft
? ? ? ? distance.y += element.offsetTop
? ? ? ? element = element.offsetParent
? ? }
? ? return distance
}
謝謝觀看!
不知名選手鉉
2023/2/21?20:02
總結
以上是生活随笔為你收集整理的Day10.事件下(学习日记10)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一篇关于营销的功能需求分析
- 下一篇: Hive---DDL