分享一次失敗的項目實踐經驗


一、開篇

最近在網上看到了一款canvas實現網頁塗鴉效果的作品,感覺這個效果比較奇特而且在以前沒有學習canvas這樣的功能是不可思議的,所以本人秉着程序員的那一份執着,花了兩三個小時的時間來研究了一下canvas塗鴉作品的代碼,發現里面代碼比較精辟,但是美中不足的是有些代碼的結構會比較的混亂,讓人感覺層次上面有點不太分明。所以本人就打算對這個代碼結構進行重構使其更具有可讀性。但是理想是豐滿的現實是骨感的,經過這一次代碼的分析和實踐下來,對我也是打擊蠻大的,以前從來都是認為前端只要能夠熟悉調試工具就行了,但是這一次調試工具居然“失靈”了,具體的失靈原因最終也沒有找到,失靈表現在:在調試上面去監控元素會發現得到的值是正確的,但是最終運行的結果卻是錯誤。打擊雖大,但是我也是挺高興的,至少我現在懂得了學會了一些代碼重構的方法和理解清楚了什么是this的指向之類的問題

二、代碼結構的編寫

由於我為了鞏固之前在深入學習JavaScript(二)中提到的繼承,所以采用的方法是將執行的方法都書寫在new方法(對應下面的canvas)的父類中,然后在window.onload事件中實例化canvas類,canvas類中是將傳入的參數傳遞給canvas的父類來的
簡化后的JavaScript結構代碼如下:

 

window.onload=function(){
    const A=1;
    var B=2;
    new canvas(A,B);
}
function canvas(a,b){
   var c=3;
   console.log(this.c):
this.init.apply(this,arguments); } canvas.prototype={ init:function(A,B){ console.log(A+","+B); } }

 

 

 

 這里面我們需要注意的是:this.init.apply(this,arguments);這句話主要是用來this指的是當前調用的對象,也就是canvas對象(通過new canvas(A,B)來調用),但是你有沒有注意到將變量c打印出來的結果是undefined,但是我們說this指的是canvas對象,這是為什么呢?其實我們在深入學習JavaScript(一)中就已經介紹過了,只不過沒有在實際的項目中進行詳解,因為通過var創建的變量c,是在window對象中聲明的,不是在canvas對象中,所以我們只需要將var c=3改為this.c=3這樣就可以正常運行了。還有這個時候this所指代的canvas對象包含有它的父類。總的一句話:調用這個方法或者是類的時候調用的對象是什么,那么這里面的this指代的就是什么。如果在調用對象不明確的時候,我們可以在調用對象的上級查找,因為如果是當前的對象沒有發生變化的時候是會繼承上級的this對象到下級的,這樣會導致當前的對象比較難發現,示例:

 

window.onload=function(){
    const A=1;
    var B=2;
    console.log(this);
    new canvas(A,B);
}
function canvas(a,b){
    this.c=3;
    console.log(this.c);
    this.init.apply(this,arguments);
}
canvas.prototype={
    init:function(A,B){
        console.log(A+","+B);
        this.test();
    },
    test:function(){
        alert('this is test');
    }
}

 

 

 

分析:在this.test()這個執行語句中,我們單從這個語句很難分析出this指代的是什么,所以我們需要向上查找,在canvas對象中的apply方法調用了init這個函數,由於這個canvas對象是被new canvas(A,B)初始化的,所以canvas對象中的this指代的是canvas對象,即canvas對象中的方法和變量。因為this對象沒有改變,所以this會一級一級的向下繼承,最終this.test()中的this就是指代canvas對象

PS:apply的用法跟call的用法相似,但是只要的用途是用來將當前傳入的參數傳遞給父類,這里我們以apply為例來進行講解

在上面的例子中我們對apply這個方法傳入的參數是:A=1;B=2,這一步相信地球人都可以看得出來。所以關鍵還是理解arguments這個代表什么意思,arguments這個會被編譯器解析為不定長的數組(其實在JavaScript中的數組都是不定長的,這個有別於其他的高級語言,例如:C#、java),然后會分別將A=1,B=2分別存放在數組的0號位上和1號位上,所以arguments=[1,2],call的作用是一樣一樣的,但是不是通過arguments這個參數來代表要傳入的參數,而是直接將參數寫在里面,例如:call(this,A,B)

 

三、其他一些需要注意的細節和知識點回顧

CSS 精靈技術

CSS精靈技術這個對於比較年老的程序員來說應該都聽說過吧,但是新一代的程序員中使用的比較少

個人認為主要的原因是:

1、制作一張精靈圖花費的時間比較久(但是node.js的出現已經有了生成圖片的工具)

2、精靈圖不是矢量圖,所以不能夠適應現在的響應式布局

3、精靈要求在CSS定位上面的操作准確,這個會增大程序員的時間成本

但是CSS精靈技術也是有自己的有點的

1、精靈圖其實就是將圖標集成為一張圖片,所以在瀏覽器向服務器發送請求的時候,服務器也就只需要返回一次數據就夠了(當然這里沒有包括JavaScript、HTML、CSS文件和其他文件),這個也是最重要的。

PS:這里面的CSS精靈技術權當溫故知新,如果沒興趣的同學可以跳過。本人也認為現在的SVG圖標已經基本上代替了以前的這種CSS精靈技術,而且更加方便

 好的,我們這就來開始精靈技術的案例

我們先准備一張雪碧圖

 然后HTML代碼是這樣的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CSS精靈技術DEMO</title>
    <style>
        #showArea{

        }
        .btn{
            width:200px;
            height:65px;
            background:url(DEMO.png);
            background-position:0px -65px;
            
        }
        .btn:hover{
            background-position:0px -130px;
        }
    </style>
</head>
<body>
    <div id="showArea">
        <div class="btn"></div>
    </div>
</body>
</html>

 

運行后的結果是:

 

幾個獲取坐標的API之間的辨析

這里我們以寬相關的來做辨析,獲取長的基本上一模一樣

offsetX,clientX,offsetLeft,window.screen.width

offsetX:所在的DOM對象中的坐標,以DOM對象的左上角坐標為原點

clientX:獲取的是相對於WINDOW對象的寬度

如果是DOM對象與左邊距為0的時候,那么clientX=offsetX

但是如果是存在margin-left這個值得時候,那么clientX=offsetX+offsetLeft

相信說到這里大家都猜到offsetLeft指的是什么吧,沒錯offetLeft指的是DOM對象相對於WINDOW的偏移量

window.screen.width:這個具體指的是屏幕的分辨率寬度,一般在移動設備上使用

 

四、相關的源碼

這里面提供了一個制作失敗的代碼供大家引以為鑒,里面的代碼中有很多功能都沒有實現,主要的問題是在畫布中畫筆和線段不能同步,這個也是導致失敗的原因,希望各位大神看一看怎樣修改,知道的麻煩再留言中告訴我一下,在此不勝感激,以上就是在這個項目中的體會所得。下載地址

 


免責聲明!

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



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