#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解決所有問題
留言
張貼留言