0%

JS實作- expense tracker 記帳簿

完成後的成品

觀察須製作的功能

  1. 重新整理網頁後,保有過去執行的狀態:localstorage
    • 實作內有使用:
    • localstorage:setItem,getItem
    • jason.stringfy/jason.parse

  1. 在new transation輸入資料後,會將資料傳入history中
    • add transation之後,頁面不會刷新(spa)(e.preventdefault)
  2. 摸到history中的項目,會出現刪除符號,點擊後刪除

  1. 輸入的金額,會顯示於上方income、expense,並且計算總額
    • 有正負值
    • 計算收入、花費

呈現完整語法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
$(document).ready(function () {
//預設值的設置,取得存在本地的資料或是空陣列
var transactions = JSON.parse(localStorage.getItem('Transactions')) || [];

//陣列初始
if (transactions.length > 0) {
initHistory(transactions);
}
//點擊按鈕的事件
$('.btn').click(function (e) {
e.preventDefault();
//console.log('click');
//取得表格中的值
const text_val = $('#text').val();
const amount_val = $('#amount').val();
let id = generateID();

addTransactions(id, text_val, amount_val, transactions);

//推入陣列
transactions.push({
id: id,
name: text_val,
amount: amount_val
})


localStorage.setItem('Transactions', JSON.stringify(transactions));


})
updateValue(transactions);

});


//在list中插入
function addTransactions(id, name, amount, transactions) {
console.log('amount:', amount);

const Transaction_str = $('<li></li>').appendTo('#list');

Transaction_str.addClass(amount < 0 ? 'minus' : 'plus');
Transaction_str.html(`${name}<span> ${amount}</span><button class="delete-btn" data-id="${id}">x</button>`);
$('#list').append(Transaction_str);


$('#text').val('');
$('#amount').val('');

//刪除鈕 要交易交出後再綁事件
$('.delete-btn').last().click(function () {
$(this).parent().remove();
let id = $(this).data('id');
//console.log(id);
deleteFromLocalstorage(transactions, id); //要記得傳入id

});

}
//從localstorage刪除
//要記得在參數放入id
function deleteFromLocalstorage(transactions, id) {
transactions.forEach(function (item, index, arr) {
//console.log('item', item);
//console.log('index', index);
//console.log('arr', arr);
if (item.id === id) {
arr.splice(index, 1);
}
});
//迴圈刪除後,要儲存到localStorage才有確實刪去
localStorage.setItem('Transactions', JSON.stringify(transactions));
}


// Generate random ID
function generateID() {
return Math.floor(Math.random() * 100000000);
}


//數值更新計算
function updateValue(transactions) {
const amounts_arr = transactions.map(function (transaction) {
return transaction.amount
})

console.log(amounts_arr);

//計算加總
var total = 0;
$.each(amounts_arr, function () { total += parseFloat((this)) || 0; });
//傳回YOUR BALANCE
$('#balance').text(`$${total}`);
console.log(total);


//*************************** */
//從陣列找出>0的值,放置income
//console.log(amounts)
var income = amounts_arr.filter(
function (item) {
return item > 0
}
)
console.log(income);

var totalIncome = 0;
$.each(income, function () { totalIncome += parseFloat((this)) || 0; });

console.log(totalIncome); //回傳220
//傳回到income
$('#money-plus').text(`$${totalIncome}`);
//***************************** */
//從陣列找出<0的值,放置income
var expense = amounts_arr.filter(
function (item) {
return item < 0
}
)
console.log(expense);

var totalExpense = 0;
$.each(expense, function () { totalExpense += parseFloat((this)) || 0; });

console.log(totalExpense);
//傳回到expense
$('#money-minus').text(`$${totalExpense}`)


}

//init
function initHistory(transactions) {
transactions.forEach(transaction => {
addTransactions(transaction.id, transaction.name, transaction.amount, transactions);
});
updateValue(transactions);

}


各項目拆解:

add transations按下去之後,頁面不刷新,直接將資料傳入紀錄中

1
2
3
4
5
6
$(document).ready(function () {
$('.btn').click(function () {
console.log('click');
})
});
//點擊後,有印出click,但很快的刷新頁面
  • 加入e.preventDefault(); 用來阻止預設動作的發生

讓transation輸入後顯示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$(document).ready(function () {
$('.btn').click(function (e) {
e.preventDefault();
console.log('click');
addTransactions('cash', '200');
})
});


function addTransactions(name, amount) {
var Transaction_str = `<li class='plus' >${name}<span> ${amount}</span><button class="delete-btn">x</button></li>`
$('#list').append(Transaction_str);
}

//

  • 提交之後清空
    • 選擇該輸入框,並利用val(),使內部的值清空
1
2
3
$('#text').val('');
$('#amount').val('');

從表格中取得值

  • 製作按鈕的點擊事件,取得表格中的值
  • 將值傳入函式的參數addTransactions(text_val, amount_val);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $(document).ready(function () {
    $('.btn').click(function (e) {
    e.preventDefault();
    console.log('click');

    //取得表格中的值
    const text_val = $('#text').val();
    const amount_val = $('#amount').val();
    addTransactions(text_val, amount_val);
    })

    });

製作刪除紐

  • 原本的撰寫方式,為選到最後一個刪除鈕,並點擊加以刪除
  • 此方式造成,無法確實刪除資料
1
2
3
4
$('.delete-btn').last().click(function () {
console.log('del');
})
}

  • 修改方式,只能綁定一筆transatin或是綁定最後一筆

  • 查看若實現點擊後刪除,是會刪除什麼?

    1
    2
    3
    4
     $('.delete-btn').last().click(function () {
    console.log(this);
    })
    }

  • 要刪除的是整筆資料,所以要去尋找他鄰近的元素

    1
    2
    3
    $('.delete-btn').last().click(function () {
    $(this).parent().remove();
    })

localstorage 執行

筆記補充:LocalStorage介紹

從此實作,可以看到它是一個陣列,裡面是物件

  • 設置一個空陣列
  • 並將物件push進去
1
2
3
4
5
6
7
8
9
10
//預設值的設置,取得存在本地的資料或是空陣列
var transactions = JSON.parse(localStorage.getItem('Transactions')) || [];

//推入陣列
transactions.push({
name: text_val,
amount: amount_val
})
localStorage.setItem('Transactions', JSON.stringify(transactions));

  • 增加初始function
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //init
    function initHistory(transactions) {
    transactions.forEach(transaction => {
    addTransactions(transaction.name, transaction.amount);
    });

    }

    //將此函式放於 $(document).ready()之中

    //陣列初始
    if (transactions.length > 0) {
    initHistory(transactions);
    }

將transation刪除後,並沒有完全從localstorage刪除

運用id來刪除

  • 從此段落:localstorage 執行,圖片中的存取陣列可以看到,沒有設置id

  • id是在addTransactions使用

    1
    2
    3
    4
    5
    6
    7
    8
    // Generate random ID
    function generateID() {
    return Math.floor(Math.random() * 100000000);
    }

    //floor:無條件捨去
    //ceil:無條件進位

  • 在創造的陣列中\物件,都加入id

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const id = generateID();
    addTransactions(id, text_val, amount_val);

    //推入陣列
    transactions.push({
    id: id,
    name: text_val,
    amount: amount_val
    })

  • 在addTransactions的函式中也要加入id

    1
    2
    3
    4
    function addTransactions(id, name, amount) {

    console.log(id, name, amount);}

  • 在button加入data-id

和資料有關的時候:data-原來欄位名稱

1
const Transaction_str = `<li class='plus' >${name}<span> ${amount}</span><button class="delete-btn"  data-id="${id}">x</button></li>`

  • 確定點擊刪除鈕的時後,是有抓到該id
    1
    2
    3
    4
    5
    6

    $('.delete-btn').last().click(function () {
    $(this).parent().remove();
    let id = $(this).data('id');
    console.log(id);
    })
  • let id = $(this).data(); 查看id時 取得的是物件
  • 應改為

此時還沒有真正刪除id,只是確定有抓到id :point_up_2:

jquery data(): 自定義屬性 (data attributes),讓我們可以任意讀寫資料在元素上,而且不會影響頁面的 layout
jQuery Data

  • 利用forEach、splice()刪除陣列內的資料

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function deleteFromLocalstorage(transactions, id) {
    transactions.forEach(function (item, index, arr) {
    //console.log('item', item);
    //console.log('index', index);
    //console.log('arr', arr);
    if (item.id === id) {
    arr.splice(index, 1);
    }
    });
    //迴圈刪除後,要儲存到localStorage才有確實刪去
    localStorage.setItem('Transactions', JSON.stringify(transactions));
    }
    ````


    * 查看迴圈的資料
    ![](https://i.imgur.com/FexS5lt.png)


    * 確實刪除存在localstorage的資料
    ```javascript
    localStorage.setItem('Transactions', JSON.stringify(transactions));

判斷輸入的數字大小,並給予class

  • 放在addTransactions()函式之中
1
2
3
4
5
6
const Transaction_str = $('<li></li>').appendTo('#list');

Transaction_str.addClass(amount < 0 ? 'minus' : 'plus');
Transaction_str.html(`${name}<span> ${amount}</span><button class="delete-btn" data-id="${id}">x</button>`);
$('#list').append(Transaction_str);

數值的更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function updateValue(transactions) {
const amounts_arr = transactions.map(function (transaction) {
return transaction.amount
})

console.log(amounts_arr);

//計算加總
var total = 0;
$.each(amounts_arr, function () { total += parseFloat((this)) || 0; });
//傳回YOUR BALANCE
$('#balance').text(`$${total}`);
console.log(total);


//*************************** */
//從陣列找出>0的值,放置income
//console.log(amounts)
var income = amounts_arr.filter(
function (item) {
return item > 0
}
)
console.log(income);
var totalIncome = 0;
$.each(income, function () { totalIncome += parseFloat((this)) || 0; });

//console.log(totalIncome); //回傳220
//傳回到income
$('#money-plus').text(`$${totalIncome}`);
//***************************** */
//從陣列找出<0的值,放置income
var expense = amounts_arr.filter(
function (item) {
return item < 0
}
)
console.log(expense);

var totalExpense = 0;
$.each(expense, function () { totalExpense += parseFloat((this)) || 0; });

console.log(totalExpense);
//傳回到expense
$('#money-minus').text(`$${totalExpense}`)


}
  • 創造一個amount的陣列
1
2
3
4
5
const amounts_arr = transactions.map(function (transaction) {
return transaction.amount
})
console.log(amounts_arr);

  • 計算加總數值
    1
    2
    3
    4
    5
    6
    var total = 0;
    $.each(amounts_arr, function () { total += parseFloat((this)) || 0; });
    //傳回YOUR BALANCE
    $('#balance').text(`$${total}`);
    console.log(total);

  • income 收入加總計算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//從陣列找出>0的值,放置income
//console.log(amounts)
var income = amounts_arr.filter(
function (item) {
return item > 0
}
)
console.log(income);
var totalIncome = 0;
$.each(income, function () { totalIncome += parseFloat((this)) || 0; });

//console.log(totalIncome); //回傳220
//傳回到income
$('#money-plus').text(`$${totalIncome}`);

  • expense支出加總
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//從陣列找出<0的值,放置expense
var expense = amounts_arr.filter(
function (item) {
return item < 0
}
)
console.log(expense);

var totalExpense = 0;
$.each(expense, function () { totalExpense += parseFloat((this)) || 0; });

console.log(totalExpense);
//傳回到expense
$('#money-minus').text(`$${totalExpense}`)


錯誤修正:

  • 調換推入陣列以及addTransactions的順序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//點擊按鈕的事件
$('.btn').click(function (e) {
e.preventDefault();
//console.log('click');
//取得表格中的值
const text_val = $('#text').val();
const amount_val = $('#amount').val();
let id = generateID();

//推入陣列
transactions.push({
id: id,
name: text_val,
amount: amount_val
});

addTransactions(id, text_val, amount_val, transactions);




localStorage.setItem('Transactions', JSON.stringify(transactions));

updateValue(transactions);
})
  • 將updateValue()放入事件中
1
2
3
4
5
6
7
8
//刪除鈕 要交易交出後再綁事件
$('.delete-btn').last().click(function () {
$(this).parent().remove();
let id = $(this).data('id');
//console.log(id);
deleteFromLocalstorage(transactions, id); //要記得傳入id
updateValue(transactions);
});