一道面試題帶來的前端優化——實現星星點評


前言

人人都會失業,這不巧小的這里就准備失業了,團隊解散不是病,突然解散要人命。

我們工作中面對這種突然團隊解散的問題,對職業生涯規划是有很大問題的,他可以讓你一夜回到革命前:

比如我幾年的工齡(<=1)沒了;比如我今年年底年終獎又只有半年的了,比如我在這里努力的結果付諸東流了......

說來說去,就一個結果,小的需要找工作了。於是那天就把簡歷掛了出來,也恰好有個招聘,就過去了,應該說毫無感覺,帶着及其失落的感情過去了......

面試過程中的題基本全知道,不管有印象的沒印象的,反正全知道......但是知道不等於了解,了解不等於深入!這里又要為自己平時的不積累埋單了。

根據那次面試,我這里有兩個總結點,最近會形成研究:javascript中的this;javascript中的冒泡機制

其實關於這兩個東西,我其實早有興趣研究,也早該研究,省略一萬字......反正最后沒有研究。

說回主題、說回正題

面試過程中,提出的一道題比較有意思,完了我一直想試試,這里提出來大家研究:

這是在當當上截的圖,我要完成的功能就是這個。

鼠標滑動到某個星上就將幾個高亮顯示。

最簡單與最戳相差不遠

碰到這類題,我一般使用神器jquery,但是我們做前端開發的,若是沒有一定涵養,第一次的方法必定是最容易實現的,往往也是最戳的:

話不多說,先上代碼:

鼠標划上選中
 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         body { background: #dfdfdf;}
 7         ul, li { margin: 0; padding: 0}
 8         li { list-style: none;}
 9         #comment_star li { background: url("s1.jpg") no-repeat -29px 0; display: inline-block; text-indent: -999px; width: 26px; height: 26px;}
10         #comment_star li.star_selcted { background-position: 0 0; }
11     </style>
12     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
13     <script type="text/javascript">
14         $(document).ready(function () {
15             $('#comment_star li').mouseenter(function (e) {
16                 var el = $(this);
17                 el.addClass('star_selcted');
18 
19             }).mouseleave(function (e) {
20                 var el = $(this);
21                 el.removeClass('star_selcted');
22             });
23         });
24     </script>
25 </head>
26 <body>
27     <ul id="comment_star">
28         <li star="1">1</li>
29         <li star="2">2</li>
30         <li star="3">3</li>
31         <li star="4">4</li>
32         <li star="5">5</li>
33     </ul>
34 </body>
35 </html>

功能一鼠標划上變顯示選中

思路:給每個li添加事件,改變其class影響背景變化:

於是乎我們完成了功能的第一步,現在我們要將鼠標划上的前面幾個都給選中,這不好辦呢。。。於是退一步又都加上id吧!

用到的圖片:

丑陋的完成功能
 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         body { background: #dfdfdf;}
 7         ul, li { margin: 0; padding: 0}
 8         li { list-style: none;}
 9         #comment_star li { background: url("s1.jpg") no-repeat -29px 0; display: inline-block; text-indent: -999px; width: 26px; height: 26px;}
10         #comment_star li.star_selcted { background-position: 0 0; }
11     </style>
12     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
13     <script type="text/javascript">
14         $(document).ready(function () {
15             $('#comment_star li').mouseenter(function (e) {
16                 var el = $(this);
17                 var num = el.attr('star');
18                 for (var i = 1; i <= parseInt(num); i++) {
19                     $('#s' + i).addClass('star_selcted');
20                 }
21             }).mouseleave(function (e) {
22                 var el = $(this);
23                 var num = el.attr('star');
24                 for (var i = 1; i <= parseInt(num); i++) {
25                     $('#s' + i).removeClass('star_selcted');
26                 }
27             });
28         });
29     </script>
30 </head>
31 <body>
32     <ul id="comment_star">
33         <li star="1" id="s1">1</li>
34         <li star="2" id="s2">2</li>
35         <li star="3" id="s3">3</li>
36         <li star="4" id="s4">4</li>
37         <li star="5" id="s5">5</li>
38     </ul>
39 </body>
40 </html>

這個丑陋的代碼,已經慘不忍賭,實現的效果尤使讓我不想看:

1 使用ul標簽,其html的結構可縮減

2 為每個li綁定事件,划上幾次事件,離開幾次事件。。。。

3 多出了很多id......

4 顯示效果也沒有做優化,用的qq截圖,有點晃動

但是戳的代碼也有他的優化的方法:

 1 $('#comment_star').delegate('li', 'mouseenter', function (e) {
 2     var el = $(this);
 3     var num = el.attr('star');
 4     for (var i = 1; i <= parseInt(num); i++) {
 5         $('#s' + i).addClass('star_selcted');
 6     }
 7 }).delegate('li', 'mouseleave',function (e) {
 8     var el = $(this);
 9     var num = el.attr('star');
10     for (var i = 1; i <= parseInt(num); i++) {
11         $('#s' + i).removeClass('star_selcted');
12     }
13 });

說是簡單優化,其實也沒什么說的,無非是把事件綁定到了ul上,所需操作依舊很多。

如何優化?

對該題優化的主旨為:

零請求、無流量

減少dom操作

零請求無流量來說,這里做的很好了,但是dom操作來說,怎一坑爹可言,其實我最開始想到的方法之所以在我看來不好優化,

因為他從開始就錯了,有了一個錯誤的開始,一個錯誤的基礎,要怎么優化都是徒勞,所以我們改變思路,改變dom結構

改變背景圖片:demo.gif,小生還是用ps搞的呢,居然還是有點不像。。。

改變dom結構

我的思路是使用兩個div處理,因為是邊寫邊發,所以我也不知道行不行得通,我們首先來看看使用一個div平鋪會怎樣?

 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         body { background: #dfdfdf; }
 7         .star { background: url("demo.gif") repeat 0 0; width: 150px; height: 26px; }
 8         #star { }
 9         #s_star { background-position: 0 -30px;  }
10     </style>
11     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
12     <script type="text/javascript">
13         $(document).ready(function () {
14  
15         });
16     </script>
17 </head>
18 <body>
19     <div id="star" class="star">
20     </div>
21     <div id="s_star" class="star">
22     </div>
23 </body>
24 </html>

形成了一下圖形

 

現在我們來做一件壞事,看看可不可以將兩個div重合:

1 body { background: #dfdfdf; }
2 .star { position: relative;}
3 .star div { background: url("demo.gif") repeat 0 0; width: 150px; height: 26px; }
4 #s_star { background-position: 0 -30px; position: absolute; left: 0; top: 0; }

若是改變其中一個寬帶的話......

 

於是我感覺我好像離我要的效果近了。於是我加了一點代碼,設置個斷點來看看:

$(document).ready(function () {
    $('.star').mouseenter(function (e) {
                
        var s = '';
    }).mouseleave(function (e) {

    });
});

 

我在想這里兩個屬性是否對我有用?我是否可以根據他們設置div的寬度呢?

 

 1 $(document).ready(function () {
 2     $('.star').mouseenter(function (e) {
 3         var el = $(this);
 4         var x = e.clientX;
 5         var left = el.offset().left;
 6         var w = x - left
 7 
 8         var s = '';
 9     }).mouseleave(function (e) {
10 
11     });
12 });

我這樣的話是不是獲得鼠標相對於元素坐標的位置了呢?然后根據該屬性設置絕對定位元素寬度試試:

即將成功的代碼
 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         body { background: #dfdfdf; }
 7         .star { position: relative;}
 8         .star div { background: url("demo.gif") repeat 0 0; width: 150px; height: 26px; }
 9         #s_star { background-position: 0 -30px; position: absolute; left: 0; top: 0; width: 0; }
10         
11     </style>
12     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
13     <script type="text/javascript">
14         $(document).ready(function () {
15             $('.star').mousemove(function (e) {
16                 var el = $(this);
17                 var x = e.clientX;
18                 var left = el.offset().left;
19                 var w = x - left
20                 $('#s_star').css('width', w + 'px');
21                 var s = '';
22             }).mouseleave(function (e) {
23 
24             });
25         });
26     </script>
27 </head>
28 <body>
29     <div class="star">
30         <div id="star">
31         </div>
32         <div id="s_star">
33         </div>
34     </div>
35     
36 </body>
37 </html>

 我們看到我鼠標指哪里,絕對定位寬度就到哪里,於是我們離勝利就只差一步了!!!判斷寬度:

 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         body { background: #dfdfdf; }
 7         .star { position: relative; width: 150px;}
 8         .star div { background: url("demo.gif") repeat 0 0; width: 150px; height: 26px; }
 9         #s_star { background-position: 0 -30px; position: absolute; left: 0; top: 0; width: 0; }
10         
11     </style>
12     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
13     <script type="text/javascript">
14         $(document).ready(function () {
15             $('.star').mousemove(function (e) {
16                 var el = $(this);
17                 var x = e.clientX;
18                 var left = el.offset().left;
19                 var w = x - left;
20                 var tmp = w % 30 - 30;
21                 w = w - tmp;
22                 $('#s_star').css('width', w + 'px');
23                 var s = '';
24             }).mouseleave(function (e) {
25                 $('#s_star').css('width', '0px');
26             });
27         });
28     </script>
29 </head>
30 <body>
31     <div class="star">
32         <div id="star">
33         </div>
34         <div id="s_star">
35         </div>
36     </div>
37 </body>
38 </html>

現在我們就發現,他完全按照我的套路出牌了啦!!!優化結束!!!

這樣的代碼我就可以結束了,我感覺基本達到我的要求了!

當當的做法

 閉門造車結束,我們來看看當當是怎么做的呢?

我們先截個圖看看,我大概知道是什么回事了,於是我們來模擬一番:

當當的背景圖:

我們發現他是一張整圖,然后我也試試實現以下代碼:

 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         body { background: #dfdfdf; }
 7         #star { background: url("dang.jpg") repeat 0 0; width: 335px; height: 26px; }
 8     </style>
 9     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
10     <script type="text/javascript">
11         $(document).ready(function () {
12            
13         });
14     </script>
15 </head>
16 <body>
17     <div id="star">
18     </div>
19 </body>
20 </html>

毫無修飾的情況下是這個樣子,那么我們來簡單調整下下:

 #star { background: url("dang.jpg") repeat -140px 0; width: 135px; height: 26px; }

於是基本還原,現在來加上樣式控制,當當寫了幾個css,我這里就東施效顰一番,直接不寫css了:

看我實現的代碼
 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         body { background: #dfdfdf;  }
 7         #star { background: url("dang.jpg") no-repeat -140px 0; width: 135px; height: 26px; }
 8     </style>
 9     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
10     <script type="text/javascript">
11         $(document).ready(function () {
12             $('#star').mousemove(function (e) {
13                 var el = $(this);
14                 var x = e.clientX;
15                 var left = el.offset().left;
16                 var w = x - left;
17                 w = -140 + w;
18                 el.css('background-position', w + 'px 0');
19                 var s = '';
20             }).mouseleave(function (e) {
21                 var el = $(this);
22                 el.css('background-position', '-140px 0');
23             });
24         });
25     </script>
26 </head>
27 <body>
28     <div id="star">
29     </div>
30 </body>
31 </html>

你看着,他會跟着鼠標走動,那么我們功能就已經實現一半了。

 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         body { background: #dfdfdf;  }
 7         #star { background: url("dang.jpg") no-repeat -140px 0; width: 140px; height: 26px; }
 8     </style>
 9     <script src="http://www.cnblogs.com/jquery-1.7.1.js" type="text/javascript"></script>
10     <script type="text/javascript">
11         $(document).ready(function () {
12             $('#star').mousemove(function (e) {
13                 var el = $(this);
14                 var x = e.clientX;
15                 var left = el.offset().left;
16                 var w = x - left;
17                 w = -140 + w;
18                 if (w < 0) w = -1 * w;
19                 w = parseInt(w / 28) * 28;
20                 el.css('background-position', '-' + w + 'px 0');
21                 var s = '';
22             }).mouseleave(function (e) {
23                 var el = $(this);
24                 el.css('background-position', '-140px 0');
25             });
26         });
27     </script>
28 </head>
29 <body>
30     <div id="star">
31     </div>
32 </body>
33 </html>

於是我可恥的認為自己實現了當當的功能了。。。。。

至於當當實現的方法,和我實現的方法,各位同學可以研究下,我可恥的認為估計當當的好吧。。。。

結語

有時候我在想我的js功底如何才能進步,如何才能成為高手,閱讀jquery源碼雖說是一個方式,當更應該平時多思考多動手的說,

看看各大網站實現方案,與自己所想的實現方案,就可以看到差距了。

而且我們平時面試的時候也不要小看那些面試題,其實他都是有針對性的,可以歸納為一個知識點做研究,

我認為這也是一個進步的方向,最后期待各位拿出自己的解決方案喲。

 如果你覺得這篇文章還不錯,請幫忙點擊一下推薦,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM