實現效果:4-01setTimeout應用javascript
又見導航條,先看下css,這裏用的是雪碧圖背景作出圓角的效果,雖然是經典的方法、兼容性好,但這種代碼寫起來實在是有點醜陋。由於須要三層嵌套,分別用背景圖繪製左圓角、右圓角和中間背景,致使dom結構變複雜了、更進一步影響js的代碼簡潔。css
而關於ui的動效,用的正是這一系列題目裏常常出現的「hover父元素激活子元素」的方法來實現,因而天然又得用mouseover
和mouseout
這對兄弟了。可是我仍是被這題坑了很多時間,由於有兩個兩點關鍵的問題想了很久才解決好:java
首先得明白這題和前面題目的不一樣,前面那些題目其實均可以用css的hover
僞類來實現,但這題不行,由於子選單和導航條的主體間是有間隙的,在鼠標從導航條到子選單的路上,子選單就會消失,根本到達不了。。。要解決這個bug,就須要題目提到的setTimeout
登場了,離開選單時,咱們可讓它延遲消失、給用戶的鼠標到達子選單或重回導航條的時間;等再回到導航條或子選單就取消掉這個延時便可。jquery
緊接着第二個大坑出現了,在前面的總結裏也提到怎麼用好mouseover
和mouseout
,因爲這兩個事件會冒泡,同時因爲他們只在跨界時觸發,並且一旦元素佔地太小就會被瀏覽器忽略;爲防止冒上來的事件亂成一團、或者該觸發的沒觸發,就應該作到減小元素嵌套,直接把事件監聽綁定在具體元素上。css3
然而問題是,這個法則在導航條的主體是可行的、可是子選單由於前面提到的三層嵌套構造圓角,已經沒法減小嵌套了,同時還得考慮到子選單也是嵌套在導航條裏的啊。。。這樣一來某些元素除去子元素的範圍、佔地就很小了,會出現前面提到的該觸發卻沒觸發的問題。具體在這題裏的表現,就是當你的鼠標離開子選單時,因爲子選單被子元素擠佔得只剩一點地方了(具體能夠按f12看一下),根本不能靠它觸發mouseout
了,若要解決這個問題,就不得不接收裏面子元素冒泡纔會產生mouseout
事件,有了事件才能進行元素顯隱的控制嘛。數組
但這又致使前面提到的另外一個問題:舉例來講,鼠標離開子選單時,只要鼠標一掃冒泡上來的mouseout
、mouseover
事件就一大堆,而這時只有鼠標離開子選單那個mouseout
纔是應該奏效的。既然咱們不能阻止和篩選子元素上的mouseout
事件,那看來只有讓它和mouseover
的效果相抵消了,由於只有在導航條裏纔會觸發這對事件,離開導航條後就沒有mouseover
來和mouseout
抵消了。同理,反過來進入子選單時天然就用mouseout
來抵消mouseover
達到篩選的目的。瀏覽器
因而就能總結出第二個坑的解決方法了:dom
首先要利用子元素的冒泡,這時就不能使用事件代理了(事件代理函數自己就有篩選事件來源的功能,無法獲取子元素冒泡上來的事件),只能退而求其次,用一個循環來綁定事件吧。ide
經過mouseout
和相應的mouseover
事件進行抵消,達到變相篩選出事件的效果。但要注意,通常用這種抵消都會引發閃爍的,因此抵消並非個通用的解決方法,只是由於正好因爲這題使用了延時和解除延時,顯隱的結果不會馬上顯現,自然就防止了子選單閃個不停的結果出現。wordpress
剩下的代碼裏還要解決幾個小問題:如解決使用了延時帶來的子選單切換卡頓、依照剩餘可佔寬度決定子選單該往左仍是往右定位、同時讓箭頭自動保持在中間等等;相比上面兩個坑都算簡單的啦。
寫到這裏才把解題思路捋清了,可見這看似簡單的幾行js要寫出來得有多蛋疼,這裏真得吐槽下這個ui的問題:把子選單搞成細細的橫向條子其實還好,採用hover做選擇原本也ok,但這時你還專門讓子選單和導航條主體間有間隙,致使實現起來比較難以外,用戶也很容易誤操做啊,那麼點地方放那麼多mouseout
和相應的mouseover
事件的觸發點,手一抖、鼠標一滑很容易就選到別的地方去啊!!
實現效果:4-02自動播放一幻燈片效果
此次是作一個輪播圖,不一樣於那種滑動的輪播效果,這裏用的是隻是將圖片疊在一塊兒而後改變透明度而已(我還另外在展現的圖片上加了個z-index
,防止拖一下圖片就現形)。選擇控件上,用的仍然是這一系列題目喜聞樂見的「hover一個元素激活其餘元素」,只不過這題因dom結構簡單,實現起來可比上一題簡單多了。
主要邏輯作起來也就兩個方面,經過監聽控件來增刪類名以改變樣式、再加上自動定時播放就能夠,這裏我把播放和中止都封裝在一個單例裏了(注意是定義在IIFE裏),結構更清晰一點,也減小了全局變量。
但還有一個問題,那就是淡入效果的實現,思路天然是定時修改透明度,然而因爲一開始給圖片直接添加類名已經讓它的透明度爲1,致使圖片展現時是不透明-->透明-->不透明的過程,效果很不天然,因而乾脆就直接把修改類名展現圖片的代碼去了,直接用淡入展現,效果更好同時又精簡了代碼。
最後再提醒下本身,用RegExp
構造正則時,千萬別忘記\
的轉義!
實現效果:4-03自動改變方向一幻燈片效果
在上面一題多加個方向判斷函數而已,同時這裏我把和輪播有關的東西全都封裝進了autoSlider
這個單例裏去了,全局變量如今就只剩這個單例,接口也能夠寫得簡潔到只有一個初始化調用,真是清爽啊~
簡單體驗arguments
而已,直接貼代碼:
function sum() { var result = 0; for (var i = 0; i < arguments.length; i++) { result += arguments[i]; } return result; } console.log(sum(1, 3, 5, 7));
實現效果:4-05css函數一設置、讀取對象的屬性
簡單的樣式獲取和修改,雖然增刪類名方式就能夠輕鬆實現,但其實這題要的不僅是效果,而是要模擬jquery的css
函數。因爲設定上,該函數的參數應該有三種狀況:
接受一個css屬性名讀取值
接收一個對象(hash表)批量設置css屬性
傳入鍵、值兩個參數直接設置某個css屬性
因此要按參數個數和參數的類型分別進行操做,類型判斷最好使用Object.prototype.toString
,這樣不會出現使用typeof
時模棱兩可的結果。若是遇到不合法的參數數目和類型,就直接用throw
拋出錯誤。
至於樣式的獲取,使用了標準的window.getComputedStyle
方法,這個方法的兼容性其實也夠用了(IE8+),因此徹底能夠不用老舊的currentStyle
。
而在設置樣式屬性時,要明白.
和[]
操做符的不一樣,使用點操做符號的屬性名必須首先是合法的變量名,並且不能是動態的引用(其實就是字符串了,只是引號能夠省略罷了);中括號操做符就不存在這種問題,因此elelment.sytle['background-color']
這種用法也能跑。
實現效果:4-06當前輸入框高亮顯示
繼續事件模擬css僞類的行爲,此次終於不是老冤家hover
了,改爲了文本框focus
,很天然就想到老套路:事件代理+增刪類名。但要注意焦點事件也有一對冒泡和不冒泡的事件存在,其中因爲火狐不支持冒泡的focusin
和focusout
,只支持不冒泡的focus
和blur
,除非只考慮移動端,不然依賴冒泡的事件代理是不能用在處理焦點事件上滴。因此這裏只好用一個循環來完成對全部元素的監聽了。
至於修改的樣式,其實就至關於自定義文本框背景和outline
樣式了,原題是用了背景圖來作,但這徹底能夠用css模擬嘛。然而因爲這裏輸入框是圓角的,除了火狐外並無瀏覽器實現outline
的圓角,因此不能直接修改outline
樣式了,只能假借邊框來實現該效果。同時還得記得把瀏覽器默認outline
關掉,不然效果可就大打折扣。
實現效果:4-07數組練習:各類數組方法的使用
簡單的數組練習,就不按照原題那樣分幾個數組了,這裏直接在一個數組上操做,再搭配一個簡單的處理流程:先用一個事件代理來監聽和分發按鈕的點擊事件,處理完再輸出到dom便可。
具體的數組操做是比較簡單的,不過要注意concat
和slice
這兩個方法不同凡響,它們不是直接在調用數組上操做,而是另外生成新數組進行操做,返回的也是新數組。利用這一點能夠實現數組的深拷貝,但如果想做用到原數組就得另外賦值了。
雖然作這系列的題本不想考慮老舊瀏覽器,但兼容事件畢竟是個經典問題,權當回顧下js高級程序設計裏的內容了。採用的的也是書裏的兼容方法,能用DOM2級別addEventListener
和removeEventListener
就用,再者就是兼容IE8
如下的attachEvent
和detachEvent
(有this指向window
、反向執行的坑),這二者都能綁定多個事件處理程序;最後實在不行再用只能綁定一個處理程序、但兼容性最佳的DOM0級。
實現效果:4-09星級評分系統
星星只是使用背景圖來改變亮滅而已,因此只要在容器上掛上對星星的click
、mouseover
、mouseout
三個事件代理,剩下的就是一些DOM和數據操做了。
---第四課完---