用JS寫星星評分


#js製作星星評分
#location.href,get方法傳送數值到php
#閉包


這是我在web程式設計課程中,期末專案的其中一項功能。
製作簡單的星星評分,用js去控制星星的顏色變化,然後點按後能將值傳送到php後端去處理
塞入資料庫中
但這篇文章就只寫前端的部分。

首先html原始碼的部分會需要五個★,這邊星星的部分是直接用字元的方式來做。

<span class="star" id="0" ></span>
<span class="star" id="1" ></span>
<span class="star" id="2" ></span>
<span class="star" id="3" ></span>
<span class="star" id="4" ></span>

接著再css中,用font-size改變星星的大小,並且一開始都是灰色的。
<style>
    .star{
        color:#ddd;
        font-size:80px;
    }
</style>


接著要用js去控制,當滑鼠滑過星星的時候,被滑到的星星、跟它之前的星星都會變成黃色
譬如說滑到第三顆星星(id=2)則id=0、1的星星都一起變成黃色

步驟:
首先var一個叫做star的陣列:star[];
用for迴圈,讓陣列的元素各代表要控制的星星(物件)
包兩個for迴圈,用onmouseover事件,當滑過星星時,讓它和之前的星星都變成黃色。
包兩個for迴圈,用onmouseout,當離開星星時,讓它和之前的星星都變成灰色。
用for迴圈,判斷點擊哪一個星星時,會送過去什麼數值給php。

程式碼:
<script>
    var star=[];
    for(var i=0;i<5;i++){
        star[i] = document.getElementsByClassName("star")[i];
    }


    for (var i =0;i<star.length;i++){
        star[i].onmouseover = function(i){return function(){
            for(var j=0;j<star.length;j++){
                if(j<=i){
                    star[j].style.color = "yellow";
                }
            }
        };}(i);
    }
    /*第一個for迴圈是要判斷哪一個星星被點到了。
    第二個迴圈再onmouseover這個方法裡面,是要讓id小於等於被點到的i的星星變色。
    */


    for (var i =0;i<star.length;i++){
        star[i].onmouseout = function(i) {return function() {
            for(var j=0;j<star.length;j++){
                if(j<=i){
                    star[j].style.color = "#ddd";
                }
            }
        };}(i);
    }

    for (var i =0;i<star.length;i++){
        star[i].onclick =function(i) {return function() {
            var value=star[i].id;   
            location.href="star.php?score="+value;  
        };}(i);
    }
    /*
    這裡定義變數value是所點擊的星星的id,
然後用location.href到star.php網頁,用網址列傳值過去。
    */

</script>

*
在寫onclick、onmouseover以及onmouseout事件時,遇到困難。
原先的寫法是(演示版):
for(var i=0;i<5;i++){
    star[i].onclick = function(){
        console.log(i);
    }
}
卻發現無論點擊哪一個,console出來的值皆是5,無法正確取得被點擊的星星的值。
這是因為var的作用域問題。

因此不直接指派整個函式給事件,且不讓函式裡面的i跟著外面的for迴圈定義的i,
用閉包的方法,將外面的i傳遞進去,然後在閉包裡面處理程序。
在這邊簡易地寫了一段程式碼:
var num =1;
var test=function(value){
    return function(){
        console.log(value);
        value +=3;
        console.log(value);
    };  
}(num);
test();
console.log(num);

結果是1、4、1;
可以看到這樣的寫法是將num的值帶入value,接著傳入裡面的函式去作用。
所以第一次console時,value =1;
接著處理過後value變成了3,但在外部 num 依然是沒有被改變的,所以是1;

在function裡面再return一個function是「閉包」的寫法。
test是外層,而return的function是內層。
用閉包的寫法,內層的變數作用的範圍僅在內層。外層無法使用。
若再繼續呼叫test(),
則value仍會繼續存取,返回的值隨著呼叫一次、兩次、三次,變為:4、7、10

#或者可以用let解決所有問題







留言