原生js練習題---第四課

0x1setTimeout應用

實現效果:4-01setTimeout應用javascript

又見導航條,先看下css,這裏用的是雪碧圖背景作出圓角的效果,雖然是經典的方法、兼容性好,但這種代碼寫起來實在是有點醜陋。由於須要三層嵌套,分別用背景圖繪製左圓角、右圓角和中間背景,致使dom結構變複雜了、更進一步影響js的代碼簡潔。css

而關於ui的動效,用的正是這一系列題目裏常常出現的「hover父元素激活子元素」的方法來實現,因而天然又得用mouseovermouseout這對兄弟了。可是我仍是被這題坑了很多時間,由於有兩個兩點關鍵的問題想了很久才解決好:java

首先得明白這題和前面題目的不一樣,前面那些題目其實均可以用css的hover僞類來實現,但這題不行,由於子選單和導航條的主體間是有間隙的,在鼠標從導航條到子選單的路上,子選單就會消失,根本到達不了。。。要解決這個bug,就須要題目提到的setTimeout登場了,離開選單時,咱們可讓它延遲消失、給用戶的鼠標到達子選單或重回導航條的時間;等再回到導航條或子選單就取消掉這個延時便可。jquery

緊接着第二個大坑出現了,在前面的總結裏也提到怎麼用好mouseovermouseout,因爲這兩個事件會冒泡,同時因爲他們只在跨界時觸發,並且一旦元素佔地太小就會被瀏覽器忽略;爲防止冒上來的事件亂成一團、或者該觸發的沒觸發,就應該作到減小元素嵌套,直接把事件監聽綁定在具體元素上。css3

然而問題是,這個法則在導航條的主體是可行的、可是子選單由於前面提到的三層嵌套構造圓角,已經沒法減小嵌套了,同時還得考慮到子選單也是嵌套在導航條裏的啊。。。這樣一來某些元素除去子元素的範圍、佔地就很小了,會出現前面提到的該觸發卻沒觸發的問題。具體在這題裏的表現,就是當你的鼠標離開子選單時,因爲子選單被子元素擠佔得只剩一點地方了(具體能夠按f12看一下),根本不能靠它觸發mouseout了,若要解決這個問題,就不得不接收裏面子元素冒泡纔會產生mouseout事件,有了事件才能進行元素顯隱的控制嘛。數組

但這又致使前面提到的另外一個問題:舉例來講,鼠標離開子選單時,只要鼠標一掃冒泡上來的mouseoutmouseover事件就一大堆,而這時只有鼠標離開子選單那個mouseout纔是應該奏效的。既然咱們不能阻止和篩選子元素上的mouseout事件,那看來只有讓它和mouseover的效果相抵消了,由於只有在導航條裏纔會觸發這對事件,離開導航條後就沒有mouseover來和mouseout抵消了。同理,反過來進入子選單時天然就用mouseout來抵消mouseover達到篩選的目的。瀏覽器

因而就能總結出第二個坑的解決方法了:dom

  1. 首先要利用子元素的冒泡,這時就不能使用事件代理了(事件代理函數自己就有篩選事件來源的功能,無法獲取子元素冒泡上來的事件),只能退而求其次,用一個循環來綁定事件吧。ide

  2. 經過mouseout和相應的mouseover事件進行抵消,達到變相篩選出事件的效果。但要注意,通常用這種抵消都會引發閃爍的,因此抵消並非個通用的解決方法,只是由於正好因爲這題使用了延時和解除延時,顯隱的結果不會馬上顯現,自然就防止了子選單閃個不停的結果出現。wordpress

剩下的代碼裏還要解決幾個小問題:如解決使用了延時帶來的子選單切換卡頓、依照剩餘可佔寬度決定子選單該往左仍是往右定位、同時讓箭頭自動保持在中間等等;相比上面兩個坑都算簡單的啦。

寫到這裏才把解題思路捋清了,可見這看似簡單的幾行js要寫出來得有多蛋疼,這裏真得吐槽下這個ui的問題:把子選單搞成細細的橫向條子其實還好,採用hover做選擇原本也ok,但這時你還專門讓子選單和導航條主體間有間隙,致使實現起來比較難以外,用戶也很容易誤操做啊,那麼點地方放那麼多mouseout和相應的mouseover事件的觸發點,手一抖、鼠標一滑很容易就選到別的地方去啊!!

0x2自動播放一幻燈片效果

實現效果:4-02自動播放一幻燈片效果

此次是作一個輪播圖,不一樣於那種滑動的輪播效果,這裏用的是隻是將圖片疊在一塊兒而後改變透明度而已(我還另外在展現的圖片上加了個z-index,防止拖一下圖片就現形)。選擇控件上,用的仍然是這一系列題目喜聞樂見的「hover一個元素激活其餘元素」,只不過這題因dom結構簡單,實現起來可比上一題簡單多了。

主要邏輯作起來也就兩個方面,經過監聽控件來增刪類名以改變樣式、再加上自動定時播放就能夠,這裏我把播放和中止都封裝在一個單例裏了(注意是定義在IIFE裏),結構更清晰一點,也減小了全局變量。

但還有一個問題,那就是淡入效果的實現,思路天然是定時修改透明度,然而因爲一開始給圖片直接添加類名已經讓它的透明度爲1,致使圖片展現時是不透明-->透明-->不透明的過程,效果很不天然,因而乾脆就直接把修改類名展現圖片的代碼去了,直接用淡入展現,效果更好同時又精簡了代碼。

最後再提醒下本身,用RegExp構造正則時,千萬別忘記\的轉義!

0x3自動改變方向一幻燈片效果

實現效果:4-03自動改變方向一幻燈片效果

在上面一題多加個方向判斷函數而已,同時這裏我把和輪播有關的東西全都封裝進了autoSlider這個單例裏去了,全局變量如今就只剩這個單例,接口也能夠寫得簡潔到只有一個初始化調用,真是清爽啊~

0x4agruments應用一求出函數參數的總和

簡單體驗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));

0x5css函數一設置/讀取對象的屬性

實現效果:4-05css函數一設置、讀取對象的屬性

簡單的樣式獲取和修改,雖然增刪類名方式就能夠輕鬆實現,但其實這題要的不僅是效果,而是要模擬jquery的css函數。因爲設定上,該函數的參數應該有三種狀況:

  • 接受一個css屬性名讀取值

  • 接收一個對象(hash表)批量設置css屬性

  • 傳入鍵、值兩個參數直接設置某個css屬性

因此要按參數個數和參數的類型分別進行操做,類型判斷最好使用Object.prototype.toString,這樣不會出現使用typeof時模棱兩可的結果。若是遇到不合法的參數數目和類型,就直接用throw拋出錯誤。

至於樣式的獲取,使用了標準的window.getComputedStyle方法,這個方法的兼容性其實也夠用了(IE8+),因此徹底能夠不用老舊的currentStyle

而在設置樣式屬性時,要明白.[]操做符的不一樣,使用點操做符號的屬性名必須首先是合法的變量名,並且不能是動態的引用(其實就是字符串了,只是引號能夠省略罷了);中括號操做符就不存在這種問題,因此elelment.sytle['background-color']這種用法也能跑。

0x6當前輸入框高亮顯示

實現效果:4-06當前輸入框高亮顯示

繼續事件模擬css僞類的行爲,此次終於不是老冤家hover了,改爲了文本框focus,很天然就想到老套路:事件代理+增刪類名。但要注意焦點事件也有一對冒泡和不冒泡的事件存在,其中因爲火狐不支持冒泡的focusinfocusout,只支持不冒泡的focusblur,除非只考慮移動端,不然依賴冒泡的事件代理是不能用在處理焦點事件上滴。因此這裏只好用一個循環來完成對全部元素的監聽了。

至於修改的樣式,其實就至關於自定義文本框背景和outline樣式了,原題是用了背景圖來作,但這徹底能夠用css模擬嘛。然而因爲這裏輸入框是圓角的,除了火狐外並無瀏覽器實現outline的圓角,因此不能直接修改outline樣式了,只能假借邊框來實現該效果。同時還得記得把瀏覽器默認outline關掉,不然效果可就大打折扣。

0x7數組練習:各類數組方法的使用

實現效果:4-07數組練習:各類數組方法的使用

簡單的數組練習,就不按照原題那樣分幾個數組了,這裏直接在一個數組上操做,再搭配一個簡單的處理流程:先用一個事件代理來監聽和分發按鈕的點擊事件,處理完再輸出到dom便可。

具體的數組操做是比較簡單的,不過要注意concatslice這兩個方法不同凡響,它們不是直接在調用數組上操做,而是另外生成新數組進行操做,返回的也是新數組。利用這一點能夠實現數組的深拷貝,但如果想做用到原數組就得另外賦值了。

0x8事件練習:封裝兼容性添加、刪除事件的函數

實現效果:4-08事件練習:封裝兼容性添加、刪除事件的函數

雖然作這系列的題本不想考慮老舊瀏覽器,但兼容事件畢竟是個經典問題,權當回顧下js高級程序設計裏的內容了。採用的的也是書裏的兼容方法,能用DOM2級別addEventListenerremoveEventListener就用,再者就是兼容IE8如下的attachEventdetachEvent(有this指向window、反向執行的坑),這二者都能綁定多個事件處理程序;最後實在不行再用只能綁定一個處理程序、但兼容性最佳的DOM0級。

0x9星級評分系統

實現效果:4-09星級評分系統

星星只是使用背景圖來改變亮滅而已,因此只要在容器上掛上對星星的clickmouseovermouseout三個事件代理,剩下的就是一些DOM和數據操做了。

---第四課完---

相關文章
相關標籤/搜索