HTML 決定了整個頁面的骨架。
主要分成兩個部分:
<main>
:負責「上傳照片與寫日記」<div id="history">
:顯示「過去的日記紀錄」<input type="file">
:讓使用者上傳圖片<img id="photoPreview">
:顯示預覽圖片(初始隱藏)<textarea>
:輸入文字心情<button>
:送出日記<div id="history">
:下面會動態生成歷史紀錄<main>
<h1>我的照片日記</h1>
<p>上傳今天的回憶 💭</p>
<input type="file" id="photoInput" accept="image/*">
<img id="photoPreview" src="" style="display:none">
<textarea id="diaryText" rows="3" placeholder="寫下你的心情..."></textarea>
<button id="uploadBtn">💾 儲存日記</button>
</main>
<div id="history"></div>
這幾行是基礎操作,用 document.getElementById()
取得 HTML 元素,後面操作會用到
const photoInput = document.getElementById('photoInput');
const photoPreview = document.getElementById('photoPreview');
const uploadBtn = document.getElementById('uploadBtn');
const diaryText = document.getElementById('diaryText');
const historyDiv = document.getElementById('history');
selectedFile 則是用來暫存使用者選的照片:
let selectedFile = null;
當使用者選擇一張圖片時,我們要先在畫面上顯示出來,這就靠 FileReader
FileReader
是一個瀏覽器內建 API,可以讀取本地檔案內容readAsDataURL()
會把圖片轉成 Base64 編碼字串photoPreview.src = e.target.result
:預覽圖片顯示注意:這裡沒有直接上傳圖片,而是轉成 Base64
,因為接下來會存進 localStorage
photoInput.addEventListener('change', e => {
const file = e.target.files[0];
if(file){
selectedFile = file;
const reader = new FileReader();
reader.onload = function(e){
photoPreview.src = e.target.result;
photoPreview.style.display = 'block';
}
reader.readAsDataURL(file);
}
});
這段是最關鍵的地方,實現了「無後端儲存」
uploadBtn.addEventListener('click', () => {
if(!selectedFile){
alert("📷 請先選擇照片!");
return;
}
const diary = diaryText.value.trim();
if(!diary){
alert("✏️ 請輸入日記文字!");
return;
}
const reader = new FileReader();
reader.onload = function(e){
const base64Image = e.target.result;
const diaryEntry = {
image: base64Image,
text: diary,
timestamp: new Date().toISOString()
};
const diaries = JSON.parse(localStorage.getItem('diaries') || '[]');
diaries.unshift(diaryEntry);
localStorage.setItem('diaries', JSON.stringify(diaries));
photoPreview.src = '';
photoPreview.style.display = 'none';
photoInput.value = '';
diaryText.value = '';
renderDiaries();
}
reader.readAsDataURL(selectedFile);
});
我們分段看:
FileReader
再次轉 Base64
:把圖片轉成文字字串
建立一個日記物件:
{
image: "data:image/jpeg;base64,...",
text: "今天吃了很好吃的蛋糕",
timestamp: "2025-10-09T05:00:00.000Z"
}
step1: 用 localStorage.getItem()
取出原本的日記
step2: 用 JSON.parse()
轉成陣列
step3: 把新的日記放在最前面 unshift()
step4: 再存回去:localStorage.setItem()
localStorage 就像是瀏覽器內建的小型資料庫,可以儲存字串資料,永久存在(除非清除快取)
儲存完後要即時更新畫面,顯示最新的日記
清空舊的內容 innerHTML = ''
,並從 localStorage
把資料取出,再用 JavaScript 動態建立每一張「卡片」,加進 <div id="history">
中
function renderDiaries(){
historyDiv.innerHTML = '';
const diaries = JSON.parse(localStorage.getItem('diaries') || '[]');
diaries.forEach(diary => {
const card = document.createElement('div');
card.className = 'diary-card';
const img = document.createElement('img');
img.src = diary.image;
card.appendChild(img);
const textDiv = document.createElement('div');
textDiv.className = 'diary-text';
textDiv.textContent = diary.text;
card.appendChild(textDiv);
historyDiv.appendChild(card);
});
}
在網頁載入時自動執行,這樣重新整理也能看到以前的內容
renderDiaries();
日記在未輸入前的樣子:
選擇照片與輸入文字並按送出:
日記呈現的樣子: