前言
最近小葉子有點疲憊,主要是在外地工作生活上不太適應,吃一樣的東西,我居然會拉肚子,而且是一個星期一個星期的。。。。
臉上長了一個豆豆一個星期還沒消,我那個去啊。
昨天上午上班后,本來想繼續研究javascript方面的東西的,但是下午要開會,結果一開就是4.5小時,哎喲,我那個怎么感覺很累啊,
明明是坐着的啊,開完會腰酸背痛的,回來吃過飯,本來想接着學習,卻迷迷糊糊的睡着了......
按照進度我們本來想要開始做小窗口的,但是也碰到點問題,除了各大微博,其它數據全部是RSS,與我想象的數據源不一樣,所以這塊還需要點時間,加之今天起來還是有點疲憊,那我們不如這個周末就休息下吧,來做幾道有意思的面試題好了,當是對前面學習的總結好了。
事情不順利不要緊,我們一步一步來,沒有什么事情做不完的。
布局類
讓我們一起來做一個頁面
首先,我們需要一個布局。
請使用CSS控制3個div,實現如下圖的布局。
我們前面已經學了很多CSS方面的東西了,我們現在來看看這道題,我們會怎么做呢?
這道題限制了只能使用三個div,並且我多float布局比較厭惡,所以第一步應該不會采用float,但是也必須考慮各個瀏覽器的兼容性,於是我第一份答案出來了:
1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <style type="text/css"> 5 body { margin: 0; } 6 div { background-color: Gray; color: White; text-align: center; } 7 .main { margin-left: 310px; height: 350px; } 8 .sidebar1 { width: 300px; height: 200px; position: absolute; top: 0; } 9 .sidebar2 { width: 300px; height: 140px; position: absolute; top: 210px; } 10 11 </style> 12 </head> 13 <body> 14 <div class="main">main 15 </div> 16 <div class="sidebar1">sidebar1 17 </div> 18 <div class="sidebar2">sidebar2 19 </div> 20 </body> 21 </html>
各位看到了,雖然我比較像用inline-block,但是實施起來時候發現有點困難,並且我這里想到了其它東西:
主要內容優先原則,不管是怎樣的布局,我的main內容皆應該放到最前面,優先加載,這也對后面將之改成響應式布局有好處。
這樣做還有一個好處便是,我們主要內容若是臨時要在左邊的話,改起來也必將方便,不要動到html結構。
好了,我們現在來看看有沒有其它方法,比如float:
1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <style type="text/css"> 5 body { margin: 0; } 6 div { background-color: Gray; color: White; text-align: center; } 7 .main { margin-left: 310px; height: 350px; } 8 .sidebar1 { width: 300px; height: 200px; float: left; } 9 .sidebar2 { width: 300px; height: 140px; float: left; clear: left; margin-top: 10px; } 10 11 </style> 12 </head> 13 <body> 14 <div class="main">main 15 </div> 16 <div class="sidebar1">sidebar1 17 </div> 18 <div class="sidebar2">sidebar2 19 </div> 20 </body> 21 </html>
有以下幾個問題:
① 因為我們主要區域在前,所以后面兩個浮動元素要改變位置才行,這與我們主要內容在前規則違背
② 若是此處主要內容要顯示在左邊的話,原來的CSS與HTML結構皆需改變
③ 瀏覽器兼容問題,原來的做法是沒有兼容問題的,這里使用float不久后IE6下又會莫名其妙的搞好多問題出來(IE3像素,清楚浮動)
所以就這塊布局來說,我是不會使用float布局的。
PS:哪位大哥有不同的意見請一定留言
第二部分:用javascript優化布局
由於我們的用戶群喜歡放大看頁面
於是我們給上一題的布局做一次優化。
當鼠標略過某個區塊的時候,該區塊會放大25%,
並且其他的區塊仍然固定不動。
於是我們來看看這道題第二個需求,他要鼠標划上擴大25%,根據我們布局1的話,這個題應該比較簡單,而且某些情況下也許鏈js都不必使用了,但是我們這里不管他:
PS:各位請不要小看這一塊,你認真做了的話,他會讓你感受到,沒jquery並且沒有形成自己庫的渺小,單單是設置樣式,設置class都會費盡很多

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 7 body { margin: 0; } 8 div { background-color: Gray; color: White; text-align: center; } 9 .main { margin-left: 310px; height: 350px; } 10 .sidebar1 { width: 300px; height: 200px; position: absolute; top: 0; } 11 .sidebar1:hover { background-color: Green; border: 1px solid black; z-index: 100; } 12 .sidebar2 { width: 300px; height: 140px; position: absolute; top: 210px; } 13 </style> 14 <script type="text/javascript"> 15 function preViewHtml(el) { 16 if (!el) return false; 17 var w = parseInt(el.offsetWidth); 18 var h = parseInt(el.offsetHeight); 19 setCss(el, 'width', w * 1.25 + 'px'); 20 setCss(el, 'height', h * 1.25 + 'px'); 21 setCss(el, 'background-color', parseInt(el.offsetHeight) * 1.25 + 'px'); 22 23 addEvent(el, 'mouseout', function () { 24 setCss(el, 'width', ''); 25 setCss(el, 'height', ''); 26 }); 27 28 } 29 30 function addEvent(el, type, fn) { 31 if (el.attachEvent) { 32 el['e' + type + fn] = fn; 33 el[type + fn] = function () { obj['e' + type + fn](window.event); } 34 el.attachEvent('on' + type, obj[type + fn]); 35 } else 36 el.addEventListener(type, fn, false); 37 } 38 function removeEvent(el, type, fn) { 39 if (el.detachEvent) { 40 el.detachEvent('on' + type, obj[type + fn]); 41 el[type + fn] = null; 42 } else 43 el.removeEventListener(type, fn, false); 44 } 45 46 function addClass(el, k) { 47 48 } 49 50 function removeClass(el, k) { 51 52 } 53 54 function getCss(el, k) { 55 if (el) { 56 if (el.style[k]) { 57 return el.style[k]; 58 } 59 return null; 60 } 61 } 62 63 function setCss(el, k, v) { 64 if (el) { 65 if (!el.style || el.style.length == 0) { 66 el.style = {}; 67 } 68 el.style[k] = v; 69 } 70 } 71 </script> 72 </head> 73 <body> 74 <div class="main">main 75 </div> 76 <div class="sidebar1" id="preView" onmouseover="preViewHtml(this)" >sidebar1 77 </div> 78 <div class="sidebar2">sidebar2 79 </div> 80 </body> 81 </html>
這個代碼有很多問題,其實我本意也不完全是這個意思啦,其實要做好這道題我覺得應該做好以下幾個事情:
① 封裝獲取dom的函數
② 封裝操作dom屬性的函數
③ 封裝操作class的函數
④ 封裝事件綁定的函數
有了以上幾塊后,這道題便很簡單了,所以我們這里還是來封裝以下吧。。。雖說我還真沒全部寫過,沒有jquery操作dom真討厭。。。
1 function getById(id) { 2 3 } 4 5 function getAttr(el, k) { 6 7 } 8 9 function setAttr(el, k, v) { 10 11 } 12 13 function addClass(el, k) { 14 15 } 16 17 function removeClass(el, k, v) { 18 19 } 20 21 function getStyle(el, k) { 22 23 } 24 25 function setStyle(el, k, v) { 26 27 } 28 29 function addEvent(el, type, func) { 30 31 } 32 33 function removerEvent(el, type, func) { 34 35 }
以下附上實現的代碼:
首先來幾個簡單的:
1 function getById(id) { 2 return id ? document.getElementById(id) : null; 3 } 4 5 function getAttr(el, k) { 6 if (el) { 7 return el.getAttribute[k]; 8 } 9 return null; 10 } 11 12 function setAttr(el, k, v) { 13 if (el) { 14 el.setAttribute(k, v); 15 } 16 } 17 18 function addClass(el, k) { 19 if (el) { 20 var arr = el.className.split(' '); 21 var arrClass = []; 22 var isExist = false; 23 for (var i = 0, len = arr.length; i < len; i++) { 24 if (arr[i] != '') arrClass.push(arr[i]); 25 if (arr[i] == k) { 26 isExist = true; 27 break; 28 } 29 } 30 if (isExist == false) { 31 arrClass.push(k); 32 var cls = arrClass.join(' '); 33 el.className = cls; 34 setAttr(el, 'class', cls) 35 } 36 } 37 } 38 39 function removeClass(el, k) { 40 if (el) { 41 var arr = el.className.split(' '); 42 var arrClass = []; 43 for (var i = 0, len = arr.length; i < len; i++) { 44 if (arr[i] != '' && arr[i] != k) arrClass.push(arr[i]); 45 } 46 47 var cls = arrClass.join(' '); 48 el.className = cls; 49 setAttr(el, 'class', cls) 50 } 51 }
我們看到,firefox可以獲取class列表,而ie幾個瀏覽器只有className這一屬性,所以操作class時候我們要用到。
但是獲取當前樣式卻比較麻煩,還需要計算各個樣式表的比重,我們這里用不到就暫時忽略了。
以上簡單測試了一番,基本沒有問題,我最后加上事件綁定,便暫時告一段落。
1 function addEvent(el, type, func) { 2 if (el) { 3 if (el.attachEvent) { 4 el.attachEvent('on' + type, func); 5 } else { 6 el.addEventListener(type , func, false); 7 } 8 } 9 } 10 11 function removerEvent(el, type, func) { 12 if (el) { 13 if (el.attachEvent) { 14 el.detachEvent('on' + type, func); 15 16 } else { 17 el.removeEventListener(type, func, false); 18 } 19 } 20 }
以上是很簡陋的做法,若是要完全解決兼容性方法,需要call篡改IE事件中this指向,以及傳入的e參數,但是那樣對刪除事件有提出了麻煩,我們這里便不管他了。
結語
今天狀態不佳,暫時這樣了吧,先去吃個飯再說。