摘要:自定義多級右鍵菜單實現(xiàn)效果自定義多級右鍵菜單第五課第六題中已經(jīng)通過事件實現(xiàn)了一級右鍵菜單,所以這題只要在上面再添加事件喚出子菜單即可。
0x1完美拖拽
實現(xiàn)效果:
6-01完美拖動
這里沒有使用h5的拖動,畢竟原題也是考察借助鼠標(biāo)事件實現(xiàn)自定義的拖動,所以就借鑒了《js高級程序設(shè)計》里的自定義拖動自己封裝了個拖動api,當(dāng)然由于做這個系列題目使用的都是es5的語法,所以IE8往下就兼容不到了(有興趣的可以自己一試)。
首先有一個自定義的事件對象構(gòu)造函數(shù)EventTarget,內(nèi)部封裝了事件的監(jiān)聽、觸發(fā)、移除監(jiān)聽三個基本操作。再由EventTarget拓展一個和拖動操作有關(guān)的單例對象,這個對象是的主要任務(wù)就是把指定元素上的觸發(fā)的鼠標(biāo)事件轉(zhuǎn)換為觸發(fā)我們自定義的拖動事件,該對象接口方法介紹如下:
enable():開啟整個文檔上拖動事件與鼠標(biāo)事件的關(guān)聯(lián)
disable():關(guān)閉拖動事件與鼠標(biāo)事件的關(guān)聯(lián),也就是點(diǎn)擊時不再觸發(fā)自定義的拖動操作
addHandler(eventName, handler):給相應(yīng)拖動事件添加處理函數(shù)。注意由于拖動事件是全局關(guān)聯(lián),所以若處理函數(shù)是針對指定元素的操作,不僅要先在該元素上添加class="draggable",而且在處理函數(shù)里還要判斷觸發(fā)事件的就是該元素才行
removeHandler(eventName, handler):移除指定的拖動事件上的某個處理函數(shù)
再介紹下三個自定義的拖動事件:
dragstart:由mousedown轉(zhuǎn)換而來,事件對象的屬性有:
type: "dragstart"
target: 鼠標(biāo)點(diǎn)擊的draggable元素
clientX, clientY: 同mousedown
drag:由mousemove轉(zhuǎn)換而來,事件對象的屬性有:
type: "drag"
target: 鼠標(biāo)點(diǎn)擊的draggable元素
clientX, clientY: 同mousemove
diffX, diffY: 用于校正clientX, clientY與實際要達(dá)到的拖動位置的偏差。需在dragstart做指定,否則默認(rèn)值為0
dragend:由mouseup轉(zhuǎn)換而來,事件對象的屬性有:
type: "dragend"
target: 鼠標(biāo)點(diǎn)擊的draggable元素
clientX, clientY: 同mouseup
api有了,我們就可以調(diào)用enable開啟拖動,再和原生的事件一樣給題目中的拖動塊添加三個事件處理函數(shù)即可。只是要注意由于addHandler方法不能指定元素,所以還得在拖動塊上添加class="draggable"、并在處理函數(shù)里做個判斷才行。利器在手,接下來要做的限制移動范圍、展示坐標(biāo)、回放拖動等都是小case啦,這題的代碼就當(dāng)是這套api的示例了。
0x2仿騰訊微博效果實現(xiàn)效果:
6-02仿騰訊微博效果
這次來個大制作,只要再搭個后臺弄點(diǎn)數(shù)據(jù)交互,幾乎就是一個完整的webApp了。就頁面而言,主要就是實現(xiàn)表單獲取數(shù)據(jù)和數(shù)據(jù)列表的展現(xiàn),所以這里分別封裝了兩個單例MsgForm和MsgList對應(yīng)表單和展示列表,來實現(xiàn)相關(guān)的功能。
MsgForm只提供了init方法來添加各個表單組件的事件監(jiān)聽。該部件最重要的就是對表單的驗證了,既要有提交時的驗證,也要保證能在輸入時即時給出字?jǐn)?shù)提醒。正則用的溜的話其實也不難。
至于MsgList則主要實現(xiàn)增刪DOM的操作,難點(diǎn)就是呈現(xiàn)和隱藏兩個動畫的實現(xiàn)。這里利用setTimeout手動調(diào)節(jié)出了效果,寫得還是比較ugly的,拓展性還不強(qiáng)。
最后注意幾個語法上的問題,一是鍵盤事件也是可以使用輔助按鍵屬性:ctrlKey, altKey, shiftKey, metaKey,而不用像第五課做過的一題那樣去緩存按鍵了。第二就是用js獲取的css屬性值,不論是通過element.style還是window.getComputedStyle(),返回的都是字符串,所以要進(jìn)行運(yùn)算只能手動轉(zhuǎn)為數(shù)字;這一點(diǎn)和js中獲取寬高、位置的屬性如offsetWidth等直接返回數(shù)字不同。
0x3自定義多級右鍵菜單實現(xiàn)效果:
6-03自定義多級右鍵菜單
第五課第六題中已經(jīng)通過contextmenu事件實現(xiàn)了一級右鍵菜單,所以這題只要在上面再添加事件喚出子菜單即可。
首先解決第五課第六題題在實現(xiàn)時留下的一個bug:菜單有時會顯示到容器外。原因很簡單,由于是先定位菜單再顯示菜單,導(dǎo)致要依靠寬高的定位并不能起作用;所以這里保證菜單先顯現(xiàn)出來擁有寬高即可。
然后就是實現(xiàn)多級子菜單了,這里直接使用css的hover偽類控制顯隱,只把定位交給mouseover事件來做即可。因為如果使用mouseover和mouseout控制顯隱,由于冒泡的特性會導(dǎo)致移到子菜單前父菜單就已經(jīng)消失的問題,雖然前面做過的題目有用過setTimeout延遲消失來解決這一問題的,但這樣寫起來實在太丑陋了,不考慮兼容老舊瀏覽器情況下還是用css做更清晰高效。
至于如何定位,也是沿用第五課的思路:設(shè)置各級子菜單絕對定位;顯示菜單時先計算容器右側(cè)和底部的剩余空間;再分別判斷能否容得下子菜單的寬高,若容得下則子菜單出現(xiàn)在父元素右下角,否則就做出相應(yīng)的變化。
最后再總結(jié)遇到的幾個問題:
子菜單定位時遇到的問題:js的offsetTop, offsetLeft屬性獲得的都是相對父容器的位置而不是絕對位置,要獲取絕對位置必須進(jìn)行向上遍歷。
子菜單li元素的寬度不能容得下其文本內(nèi)容,導(dǎo)致文本折疊:不設(shè)置寬度的絕對定位元素,其寬度是由最長的文本內(nèi)容決定的。若文本自動換行那最長文本就是最長單詞而已,所以得設(shè)置white-space: nowrap;使文本不換行,才能保證li元素的寬度能夠容得下其所有文本內(nèi)容。而具體關(guān)于元素寬高為auto時其寬高在不同情況會受到什么影響,我會專門寫一篇文章來分析分析~
---第六課完---
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/79424.html
摘要:計算屬性計算屬性關(guān)鍵詞。計算屬性在處理一些復(fù)雜邏輯時是很有用的。接下來我們看看使用了計算屬性的實例實例原始字符串計算后反轉(zhuǎn)字符串計算屬性的指向?qū)嵗龂L試一下實例中聲明了一個計算屬性。提供的函數(shù)將用作屬性的。依賴于,在發(fā)生改變時,也會更新。 Vue.js 計算屬性 計算屬性關(guān)鍵詞: computed。 計算屬性在處理一些復(fù)雜邏輯時是很有用的。 可以看下以下反轉(zhuǎn)字符串的例子:實例 1 {{...
摘要:標(biāo)簽的認(rèn)識一標(biāo)簽的分類雙標(biāo)簽如單標(biāo)簽如換行標(biāo)簽二標(biāo)簽的關(guān)系嵌套關(guān)系如與父子關(guān)系并列關(guān)系如與兄弟關(guān)系三排版標(biāo)簽標(biāo)題標(biāo)簽比較重要,一般用作網(wǎng)站的段落標(biāo)簽水平線標(biāo)簽單標(biāo)簽換行標(biāo)簽標(biāo)簽網(wǎng)頁布局標(biāo)親盒子四文本格式化標(biāo)簽文本加粗標(biāo)簽不推薦使用的加粗標(biāo)HTML標(biāo)簽的認(rèn)識一、標(biāo)簽的分類1、雙標(biāo)簽 如 2、單標(biāo)簽 如 換行標(biāo)簽 二、標(biāo)簽的關(guān)系1、嵌套關(guān)系 如 與title 父子關(guān)系2、并列關(guān)系如與 兄弟關(guān)系...
閱讀 1625·2021-11-02 14:42
閱讀 521·2021-10-18 13:24
閱讀 939·2021-10-12 10:12
閱讀 1817·2021-09-02 15:41
閱讀 3201·2019-08-30 15:56
閱讀 2873·2019-08-29 16:09
閱讀 2056·2019-08-29 11:13
閱讀 3617·2019-08-28 18:06