Skip to main content

要開學了

· 2 min read

今天,是我整個暑假待在花蓮的最後一日

嗯對,想了一想,2個月裡幾乎從早到晚,都待在我家四樓琴房練琴、看電腦、打遊戲、聽歌、睡覺、思考人生、emo... 總之除了尿尿、吃飯、洗澡、睡覺,沒離開過琴房。

出門

所以決定在暑假的最後時刻,至少出門一下,就約了朋友,早上9.去打羽毛球,結果到了現場,發現場館在辦活動,沒辦法打,就去朋友家坐了。去他家大概就是看電視、玩Roblox、講幹話,整個早上就這樣過了~

然後到差不多12.吧,決定去看場館活動結束沒,到那邊發現還是有活動,問了一下那邊人員說快結束了,所以我們就先去吃八方,再回來打球。

八方雲集

呵呵大家一定吃過八方吧!都吃什麼口味啊?這次我是點辣味泡菜鍋貼+咖哩水餃 ,我決定下次不點辣味了!太辣了而且吃了覺得喉嚨好乾、不舒服,還有我吃咖哩水餃一口塞,直接燙到掉眼淚,真的!沒在誇大,燙到爆! 然後我朋友很雷,醬油掉地上灑出來,噴到我腳上🫠 所以今天吃的很狼狽,不過八方我是真心覺得不錯啦,蠻便宜的又好吃!

打羽球

大概從13:30打到17:00 中間沒什麼休息,打完全身濕,回去時外面下雨,但不管了,淋雨走回朋友家,衣服、頭髮全濕透,然後我好臭喔!

休息一陣子後,驚恐的發現,我右手一用力,就有有很強烈的沉重感和下墜感,完全無法出力,還一度沒辦法拿東西。這就是太久沒運動的後果,我想隔天起床,應該會全身酸痛吧!

好吧!開學第一天主修課直接完蛋,手真的沒辦法出力...

嗯,但是蠻開心的,我喜歡打球時,汗一直狂噴、全身濕透累到爆,可是很爽的感覺!好像把這幾個月來的壓力?)emo的情緒都發洩出來了?)啊 還有色慾,會不會很變態,但就真的啊!

開學

最後,祝大家開學後的生活都能順利!盡量要過得開心,畢竟青春只有一次,很多事只有現在能做,所以 加油吧...

排球少年

· 2 min read

排球少年是一部動漫,這部我重刷應該有5次了吧!從國小看到現在,動漫出了四季,一共85集, 每次重刷都還是很興奮,看都看不膩!!以下我來和大家分享這部動漫一開始的劇情:

主角:「日向翔陽」在故事的一開始,是位喜歡排球的國中生,但他的學校沒有正式的排球部,不過日向不放棄,硬邀其他足球、網球社的同學, 一起參加正式比賽,結果慘敗給影山飛雄的隊伍。

日向到了高中,進入了烏野高中排球社,而影山也是,他們兩個一開始就是互看對方不順眼,後來 就慢慢磨合、吵架,然後打比賽,後面的各位自己去看吧,只看字沒辦法體驗到那種感覺,真的非常熱血!!也很激勵人心

我放一些很帥的名言:

「沒什麼好擔心的,大家只要向前看就好,背後由我來守護!」

── 西谷夕


「我不需要喝采,我只要穩紮穩打」

── 北 信介


「不准低頭!排球是永遠向上看的運動!」

── 烏養教練


「不想輸需要理由嗎?」

── 日向翔陽


「無需追憶昨日」

── 稻荷崎高中排球部布條口號


「抱著得過且過的心態,加入一群熱血沸騰的人之中,是最沒有禮貌的行為」

── 谷地仁花的母親


「無論身處怎樣的劣勢,繼續戰鬥的理由只有一個,那就是比賽還沒有結束」

── 影山飛雄


「沒有一定會輸的比賽,除非放棄」

── 日向翔陽

大家快去看吧!我是用動畫瘋看,yt或Netflix應該都有

晚安~ 隨筆紀錄現在時間 2026-8-29 1:14

Line

· 3 min read

首先 先來抱怨一下賴

有沒有人覺得Line很難用?? 照片與影片有保存期限,聊天紀錄還要自行備份,加好友超麻煩, 重點是近期又推動 訂閱制功能,超級討人厭!!!動不動就問你要不要訂閱,但那些訂閱功能,在其他通訊軟體免費版全都有。

不太能理解為什麼台灣人那麼愛用

上網查了一下,有人分析是因為:

  • 當年簡訊需付費,LINE免費的優勢極具吸引力
  • LINE當時拍攝很多電視廣告,迅速提升品牌知名度
  • 推出熊大等原創角色IP與貼圖經濟,甚至舉辦活動吸引大量粉絲排隊參與
  • 發展貼圖、官方帳號等,讓使用者轉移成本,用戶更難輕易更換平台。

好吧,我想短期內,應該是很難改變大家都用賴的這個習慣


社群

不過最近,我發現賴裡面有個還不錯的功能,就是社群,主要特點:

  • 沒人知道你是誰:其他成員和管理員只能看到你的匿名暱稱與大頭貼,看不到真實 LINE 帳號、LINE ID 、電話號碼
  • 隱私:好友不會知道你加入了哪些社群
  • 人數:單一社群最多可容納高達 5,000 人
  • 訊息保留:新加入時,最多可瀏覽最近 6 個月的歷史聊天訊息

重點是我覺得最特別的是:LINE 社群內建有「自動程式(Bot)」功能

自動程式(Bot)

這東西很酷,像是當新成員進入時,會自動發歡迎詞或板規,也可預約訊息,例如每到10.就自動發:「該睡覺了喔,別再聊了」,還有關鍵字回覆,如你打:/自介,可能就會跳出一些預先設定好的自動回覆。

AI 機器人

在社群裡,賴官方的機器人,會看著我們聊天,可怕吧!一但你違反社群守則,機器人會馬上停用你的帳戶

社群守則

  • 不可交換聯絡資訊:不能留個人 LINE ID、電話號碼、FB/IG 社交帳號連結
  • 嚴禁單獨會面意圖:禁止男女交友、約會、約炮
  • 嚴禁非法與敏感商業話題:禁止討論或推廣博弈、虛擬幣投資、傳直銷
  • 嚴禁短時間內洗版:禁止短時間內瘋狂傳送重複的文字、貼圖,或大量轉貼外部內容農場連結

順帶一提,我就是因為短時間內重複傳太多一樣的貼圖,而被停用🫠然後很emo在這邊打文章

還有,提醒各位「社群」和「群組」是完全不一樣的喔!


然後啊

大家知道LINE其實可以創多個帳戶喔!不需綁定電話號碼,只要有電子郵件就可以,我自己在BlueStacks模擬器裡面的Line帳號,就是和我手機的帳號不一樣,我有兩個帳號。 但記得就是,創的時候要把國家改成美國或英國之類的,不強制要求電話號碼的國家

但當然只用電子郵件創的帳號,會限制一些功能,例如:不能入社群🫠、手機版無法登入
呃不過我自己用起來,加好友、聊天、創群組那些功能都正常,如果被迫需要多帳號,可以創喔!!

最後

推薦幾款通訊軟體給大家:

以上都是不錯用的軟體,最後希望賴趕快解封,我要炸群 🤓

鋼琴大師班選拔

· 2 min read

今天,我媽傳了一則訊息給我,內容就是叫我去參加國際大師鋼琴藝術節選拔
我隨便敷衍一下,回他:啊呀!我不是鋼琴主修,現在手上沒曲子,報名那個也不會上啦

沒想到我媽是認真的,他罵了我一頓:這不是主不主修的問題,你不是暑假整天都在琴房嗎?怎麼會沒有曲目?你看別人去年都有上,你為什麼不行, 而且高中會補助,有機會就要爭取,而且你不是都要隨時有曲目,隨時都要準備好

嗯對,我無法反駁... 所以後來我決定用之前期末考曲子「李斯特超技10」這首去錄影,這個大師班有幾個注意事項:

  • 報名費$4500 (若甄選有上,會全額退費,全高中生名額只有15名)
  • 報名截止日 10/15
  • 繳交 5 分鐘以上之鋼琴獨奏 YouTube 連結,可單首或多首
  • 錄取公告日 不晚於11/10

全台高中生只有15個名額,我怎麼可能上...真的不想浪費爸媽的錢,所以我昨天有和我媽頂嘴...因為真的覺得自己做不到啊

好啦,總之就去把超技拿回來好好複習

然後也快開學了呢,唉好多事要面對欸...該怎麼辦啊? 我快不行了,最近失去了最在意的人、最不想失去的人,我到底會花多久才有辦法走出來啊啊啊啊...真的很痛苦


五月天「夜訪吸血鬼」有句歌詞:
上帝遺棄我們
卻又要給黯淡的月照亮世界
要我們無盡又無情的繁衍
看愛過的人 一一告別
做過的夢 一一凋謝
只留下我獨自殘喘的千年

很有感慨,看著愛人離我而去,卻無能為力,再說什麼也無法挽回了,而那些夢想,想和他一起吃飯、散步、抱抱、牽手、很多很多, 還有一起去看這美麗的世界,都再也無法達成了...

量子危機

· 3 min read

今天來介紹「量子危機」這本書,這本書以漫畫的方式,介紹簡單的量子知識

以下整理這本書提到的的知識:

1 什麼是量子?

首先,量子並不是一種具體的物質,它指的是「物理量的最小不連續單位」, 例如我們講「光量子」意思就是「光的能量最小、不可再分割的基本單位」。

2 量子疊加

指的是「在微觀粒子未經觀測前,可以同時處於多種物理狀態的機率組合中
最有名的例子是:薛丁格的貓
假想有一個密閉的黑箱子,裡面放了致命的毒藥機關,而機關由一個處於疊加狀態的放射性原子決定是否啟動,我們得打開箱子才可知道毒藥機關是否被啟動。

而把一隻貓放進去,在沒打開箱子前,照疊加原理來看,機關處於「既被啟動了、又沒被啟動」兩種狀態,而這隻貓便處在「又活又死」的疊加狀態。聽起來很荒謬吧!貓活又死是什麼鬼? 其實這個實驗是,薛丁格故意用來嘲諷當時的量子力學大師們(如波爾等人),對機率論與觀測機制的盲目信仰,他故意把微觀世界的規律,套用到巨觀世界裡,所以才顯得如此荒謬。

3 量子位元

「位元」是資訊最小單位,用0或1來表示,而利用第2點所說的量子疊加原理,把「同時存在兩種不同狀態的量子系統當作位元使用 ,讓兩種狀態分別代表0和1來儲存訊息。

利用量子位元建構的電腦,可運算比傳統位元更有效率。

4 量子糾纏

指「兩個以上的量子粒子,因某些原因產生關聯,使彼此行為互相影響

舉例來說:有兩個粒子有50%朝⬆️50%朝⬇️的機率,在還沒進行觀測前,兩個粒子都是既朝上又朝下,這概念和之前提到第二點量子疊加的意思一樣 「在微觀粒子未經觀測前,同時存在各種可能狀態」
即使相距光年之遙,只要觀測其中一個粒子的狀態(例如朝上⬆️),另一個粒子的狀態就會瞬間確定(瞬間朝下⬇️)所以只要測量其中一個狀態,另一個不須經過任何測量時間,會瞬間呈現與第一個對應的狀態

5 量子穿隧

巨觀世界裡,當一顆球遇到一面牆,球會無法穿越牆,被反彈回來, 但在微觀量子世界裡,它有一定的機率可以穿牆而過。「一個粒子即使所具備的能量不足以跨過障礙,它仍有小機率會出現在障礙物的另一邊」這就是量子穿隧效應。 但要是障礙無限高或無限厚的話,那粒子還是過不去的。

6 量子加密通訊

量子加密並非用來傳送資訊本身,而是用來傳輸「密鑰」。
利用「量子疊加」這個特性,傳送者把密鑰的相關資訊,已量子態傳給接收者,一但有人在中途竊取資訊,量子態就會發生變化,接收者和傳送者核對密鑰時,就會發現不符,而知道有人竊聽並廢棄該次傳輸。


以上,就是這本書的知識,不會太難吧!我覺得還蠻有趣的,希望大家看完不要睡著

vorssaint

· 2 min read

今天來介紹一款超厲害的工具

vorssaint

這是一款完全免費開源的macOS選單列工具,裡面有非常多的功能,例如:系統監控、保持 Mac 喚醒、應用程式音量控制、快速視窗切換、滑鼠滾輪方向調整、等等。

這邊介紹幾個

1.截圖、錄製螢幕

特別功能:

  • 截圖完後可直接編輯
  • 錄製螢幕時可選擇mac聲音或麥克風
  • 螢幕錄製完也可直接編輯,mac聲音和麥克風會是獨立音軌,都可調整

替代文字 替代文字

2.放射狀選單

這功能很方面,就是捷徑的概念,可設定成你常開的文件、app、等... 替代文字

3.剪貼板

特別功能:

  • 儲存所有複製過的文字
  • 可釘選複製文字

替代文字

4.視窗排列

很多視窗的排列方式,都可設定快捷鍵 替代文字

5.分區式面板

這裡可以看到很多資訊、設定 如:

  • 設定各 App 的音量大小
  • CPU、GPU、電池的溫度
  • 目前功耗值、電池健康度
  • 保持喚醒 (讓 Mac不進入睡眠模式)
  • 記憶體資訊

替代文字

先介紹到這邊,大家快去試試

快來安裝看看吧!

Cryptomator

· One min read

大家是否曾經懷疑那些傳到雲端的檔案,隱私真的安全嗎?
又或者你有沒有不想給他人偷看的秘密照片、影片或文件?

這邊,推薦一款加密工具: Cryptomator

Cryptomator 是什麼?

這是來自德國開源的加密工具

運作原理:
在本地加密 → 將加密後的保險箱資料夾放在雲端同步資料夾
而雲端同步的永遠只有亂碼

為什麼選擇 Cryptomator?

1.開源且無須註冊:不需有帳號,密碼掌握在自己手上。
2.檔名與結構全數加密:點開看到的只是一堆亂碼和無意義的資料夾,無法推斷你放了什麼資料。
3.單一檔案獨立加密:修改小檔時只需同步該檔案,不會觸發全盤重新上傳。
4.電腦版完全免費(但手機版好像要錢)

怎麼用

1.安裝
2.建立加密檔案庫
3.設定密碼(建議儲存Recovery Key 別相信自己大腦)。
4.解鎖保險箱,將秘密文件放入掛載的虛擬硬碟中。

快去試試看吧

MDX 實戰篇

· 10 min read

前言

上一章基礎篇,都在講無聊的語法,相信大家看一下就馬上按叉叉關掉了,但這一篇要講的內容,就比較有趣了啦!

那我們進入正題吧

首先 MDX有兩種寫法

1.引用外部React元件:事先在外部寫一個React組件,再引用到MDX的import使用。

2.直接在MDX檔裡寫簡單的Inline JSX。


第一種示範

當你閒閒沒事時,就可以出個題來考考大家

Q: 哪一首歌曲,不是收錄在「自傳」這張專輯中?

好!讓我們來看看這是怎麼寫出來的

1.去專案的 src/components/ 資料夾下,新增一個.jsx的檔案,我是取名Quiz.jsx,當然也可以取MAYDAY.jsx 隨便你要叫什麼

2.在.jsx檔裡開始寫,這邊直接展示程式碼

有點長
import React, { useState } from 'react';

export default function Quiz({ question, options, correctAnswerIndex, explanation }) {
const [selected, setSelected] = useState(null);
const [submitted, setSubmitted] = useState(false);

const handleOptionClick = (index) => {
if (submitted) return;
setSelected(index);
};

const handleSubmit = () => {
if (selected === null) return;
setSubmitted(true);
};

const handleReset = () => {
setSelected(null);
setSubmitted(false);
};

return (
<div style={{
border: '1px solid var(--ifm-color-emphasis-300)',
borderRadius: '8px',
padding: '16px',
margin: '16px 0',
backgroundColor: 'var(--ifm-card-background-color)'
}}>
{question && (
<h4 style={{ marginTop: 0, marginBottom: '12px', fontSize: '1.1rem' }}>
{question}
</h4>
)}

<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
{options.map((option, idx) => {
let optionBg = 'transparent';
let borderColor = 'var(--ifm-color-emphasis-300)';

if (selected === idx) {
borderColor = 'var(--ifm-color-primary)';
optionBg = 'var(--ifm-color-primary-lightest)';
}

if (submitted) {
if (idx === correctAnswerIndex) {
borderColor = 'var(--ifm-color-success)';
optionBg = 'var(--ifm-color-success-lightest, rgba(0,200,0,0.1))';
} else if (selected === idx) {
borderColor = 'var(--ifm-color-danger)';
optionBg = 'var(--ifm-color-danger-lightest, rgba(200,0,0,0.1))';
}
}

return (
<button
key={idx}
onClick={() => handleOptionClick(idx)}
style={{
textAlign: 'left',
padding: '10px 14px',
borderRadius: '6px',
border: `2px solid ${borderColor}`,
backgroundColor: optionBg,
cursor: submitted ? 'default' : 'pointer',
color: 'var(--ifm-font-color-base)',
fontSize: '0.95rem',
transition: 'all 0.2s',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}
>
<span>{option}</span>
{submitted && idx === correctAnswerIndex && <span>🩵正確</span>}
{submitted && selected === idx && idx !== correctAnswerIndex && <span>🥲錯誤</span>}
</button>
);
})}
</div>

<div style={{ marginTop: '16px', display: 'flex', gap: '10px', alignItems: 'center' }}>
{!submitted ? (
<button
onClick={handleSubmit}
disabled={selected === null}
style={{
backgroundColor: selected === null ? '#ccc' : 'var(--ifm-color-primary)',
color: 'white',
border: 'none',
borderRadius: '4px',
padding: '6px 16px',
cursor: selected === null ? 'not-allowed' : 'pointer',
fontWeight: 'bold'
}}
>
送出答案
</button>
) : (
<button
onClick={handleReset}
style={{
backgroundColor: 'transparent',
border: '1px solid var(--ifm-color-emphasis-500)',
color: 'var(--ifm-font-color-base)',
borderRadius: '4px',
padding: '6px 12px',
cursor: 'pointer'
}}
>
重新作答
</button>
)}
</div>

{submitted && explanation && (
<div style={{
marginTop: '12px',
paddingTop: '12px',
borderTop: '1px dashed var(--ifm-color-emphasis-300)',
color: 'var(--ifm-font-color-base)',
fontSize: '0.9rem'
}}>
👍🏿<strong>解析:</strong>{explanation}
</div>
)}
</div>
);
}

3.再來就可以到.mdx檔中引入,一樣直接展示程式碼

👍🏿👍🏿
import Quiz from '@site/src/components/Quiz';

<Quiz
question="Q: 哪一首歌曲,不是收錄在「自傳」這張專輯中?"
options={[
'如果我們不曾相遇',
'嘿!我要走了',
'頑固',
'成名在望'
]}
correctAnswerIndex={1}
explanation="不用解釋吧!五迷一秒作答"
/>

如此以來就搞定了!但還是要來學學程式碼當中的邏輯,只會複製貼上就太無趣了
我們挑個比較重要的區域來講


教學

export default function Quiz({ question, options, correctAnswerIndex, explanation })

這是元件傳參 定義了這個元件可以接收 4 個外部傳入的資料(題目、選項、正確答案索引、解析)。

{submitted && idx === correctAnswerIndex && <span>🩵正確</span>}
{submitted && selected === idx && idx !== correctAnswerIndex && <span>🥲錯誤</span>}

這是在說條件
顯示第一行的條件:

  • 已按下送出答案(submitted === true)
  • 當前這個選項是正確答案(idx === correctAnswerIndex)

顯示第二行的條件:

  • 已按下送出答案(submitted === true)
  • 使用者點選的這個選項不是正確答案(idx !== correctAnswerIndex)
if (submitted) {
if (idx === correctAnswerIndex) {
borderColor = 'var(--ifm-color-success)';
optionBg = 'var(--ifm-color-success-lightest, rgba(0,200,0,0.1))';
} else if (selected === idx) {
borderColor = 'var(--ifm-color-danger)';
optionBg = 'var(--ifm-color-danger-lightest, rgba(200,0,0,0.1))';
}
}

這是在處理答案送出後的動態樣式

  • 標準答案選項(idx === correctAnswerIndex):框線與背景強制套用綠色(color-success)
  • 使用者選錯的那一選項(selected === idx):框線與背景強制套用紅色(color-danger)

好!先解到這邊 我們來看第二種


第二種示範

先玩玩看吧!

五月天團員職稱配對

先點選一位團員,再點選對應的職稱!

團員
職稱 / 樂器

這段直接寫在.mdx檔裡面
來揭曉程式碼

很長別嚇到了

import React, { useState } from 'react';

export const MaydayMatch = () => {
const [selectedMember, setSelectedMember] = useState(null);
const [selectedRole, setSelectedRole] = useState(null);
const [matchedPairs, setMatchedPairs] = useState({});
const [statusMessage, setStatusMessage] = useState('先點選一位團員,再點選對應的職稱!');

const members = ['阿信', '怪獸', '石頭', '瑪莎', '冠佑'];
const roles = ['鼓手', '吉他手/團長', '主唱', '貝斯手', '吉他手'];

const correctPairs = {
'阿信': '主唱',
'怪獸': '吉他手/團長',
'石頭': '吉他手',
'瑪莎': '貝斯手',
'冠佑': '鼓手'
};

const handleSelectMember = (name) => {
if (matchedPairs[name]) return;
setSelectedMember(name);
if (selectedRole) {
checkPair(name, selectedRole);
} else {
setStatusMessage(`已選擇【${name}】,請選擇對應的職稱...`);
}
};

const handleSelectRole = (role) => {
const isRoleMatched = Object.values(matchedPairs).includes(role);
if (isRoleMatched) return;

setSelectedRole(role);
if (selectedMember) {
checkPair(selectedMember, role);
} else {
setStatusMessage(`已選擇【${role}】,請選擇對應的團員...`);
}
};

const checkPair = (member, role) => {
if (correctPairs[member] === role) {
setMatchedPairs(prev => ({ ...prev, [member]: role }));
setStatusMessage(`🤓讚喔`);
} else {
setStatusMessage(`🫠答錯了!這麼簡單欸`);
}
setSelectedMember(null);
setSelectedRole(null);
};

const isCompleted = Object.keys(matchedPairs).length === members.length;

return (
<div style={{
padding: '20px',
borderRadius: '12px',
border: '1px solid var(--ifm-color-emphasis-300)',
backgroundColor: 'var(--ifm-card-background-color)',
margin: '24px 0',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.05)'
}}>
<h3 style={{ marginTop: 0, marginBottom: '8px' }}>五月天團員職稱配對</h3>
<p style={{ margin: '0 0 16px 0', color: 'var(--ifm-color-emphasis-700)', fontSize: '0.95rem' }}>
{isCompleted ? '讚讚 已完成所有配對!' : statusMessage}
</p>

<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
<span style={{ fontWeight: 'bold', fontSize: '0.85rem', color: 'var(--ifm-color-emphasis-600)' }}>團員</span>
{members.map(m => {
const isMatched = !!matchedPairs[m];
const isSelected = selectedMember === m;
return (
<button
key={m}
onClick={() => handleSelectMember(m)}
disabled={isMatched}
style={{
padding: '10px 14px',
borderRadius: '8px',
textAlign: 'left',
border: isSelected ? '2px solid var(--ifm-color-primary)' : '1px solid var(--ifm-color-emphasis-300)',
backgroundColor: isMatched ? 'var(--ifm-color-success-lightest)' : isSelected ? 'var(--ifm-color-primary-lightest)' : 'transparent',
color: isMatched ? 'var(--ifm-color-success-darkest)' : 'inherit',
cursor: isMatched ? 'not-allowed' : 'pointer',
fontWeight: isSelected || isMatched ? 'bold' : 'normal',
transition: 'all 0.2s ease'
}}
>
{m} {isMatched && '✓'}
</button>
);
})}
</div>

<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
<span style={{ fontWeight: 'bold', fontSize: '0.85rem', color: 'var(--ifm-color-emphasis-600)' }}>職稱 / 樂器</span>
{roles.map((r, idx) => {
const isMatched = Object.values(matchedPairs).includes(r);
const isSelected = selectedRole === r;
return (
<button
key={idx}
onClick={() => handleSelectRole(r)}
disabled={isMatched}
style={{
padding: '10px 14px',
borderRadius: '8px',
textAlign: 'left',
border: isSelected ? '2px solid var(--ifm-color-primary)' : '1px solid var(--ifm-color-emphasis-300)',
backgroundColor: isMatched ? 'var(--ifm-color-success-lightest)' : isSelected ? 'var(--ifm-color-primary-lightest)' : 'transparent',
color: isMatched ? 'var(--ifm-color-success-darkest)' : 'inherit',
cursor: isMatched ? 'not-allowed' : 'pointer',
fontWeight: isSelected || isMatched ? 'bold' : 'normal',
transition: 'all 0.2s ease'
}}
>
{r} {isMatched && '✓'}
</button>
);
})}
</div>
</div>
</div>
);
};

<MaydayMatch />

程式碼非常長,挑2個核心重點講

import React, { useState } from 'react';

這是指是在 .mdx 檔宣告組件
最後再寫<MaydayMatch/>指呼叫並執行這個組件

const checkPair = (member, role) => {
if (correctPairs[member] === role) {
setMatchedPairs(prev => ({ ...prev, [member]: role }));
setStatusMessage(`🤓讚喔`);
} else {
setStatusMessage(`🫠答錯了!這麼簡單欸`);
}
setSelectedMember(null);
setSelectedRole(null);
};

這段在判定有沒有答對

在前面時,有先寫好答案 correctPairs = { '阿信': '主唱', '怪獸': '吉他手/團長' ... } 使用者點選後,程式會去查答案發現:

答對:跳出「🤓讚喔」,接著把這組正確配對存進 matchedPairs 記錄過的團員,畫面上的按鈕就會變綠色且不能再點。

答錯:跳出「🫠答錯了!這麼簡單欸」

總結

第一種和第二種的對比

優點缺點適用時機
第一種(引用外部 React 元件)1.檔案乾淨
2.邏輯可跨頁面重複使用
要額外建立.jsx檔、複雜複雜邏輯、大型組件
第二種(直接寫在.mdx)1.快速方便
2.免開新檔案
文章原始碼會變超長、無法給其他文章複用簡單組件、單篇特製

感謝大家看到這裡 辛苦啦

我覺得就是根據各位需求,兩種方法都很好,這篇就先這樣啦!
之後會再寫更多有趣的實用範例,不會寫教學,就是純分享,敬請期待!

有任何問題或建議,歡迎寫信聯絡我! 信箱:aa10200809@gmail.com

一期一會

· 2 min read
tip

這是我的「BlogBlog 同樂會 – 2026 年 8 月」 的投稿文章。本月主題是「一期一會」,由 ikuka 主持。如果你有自己的部落格,歡迎一起來參加!


這個詞我想到了一些不同面向的解釋方法

1.人生第一次:

今年7月,去看了人生第一場五月天演唱會,體悟到了親自蒞臨現場的那種感動,我想這就是演唱會存在的必要吧!萬人大合唱和在家自己唱就是不一樣,一定不會忘記這場演唱會,畢竟是第一次~

2.一生只有一次的相遇:

我這個人的個性,不太會社交,現實相處後,也不會主動要ig,所以和很多人真的是一期一會。自己的社群平台,也沒有經常聊天、聯絡的朋友,基本上除了必要通知、公事聯絡,一天下來不會有訊息,不免有點感傷,因為若沒有持續聯繫、刻意的約出去相見,一輩子也不會再見了吧!

但後來也覺得,社群媒體是個蠻假相片面的東西,反正也沒訊息,留著看表面熱鬧也沒意義,所以就把社群app刪了。

3.遺憾,一期一會就好:

我們常被人告誡,人生只有一次,勇敢去做,不要留遺憾。去向喜歡的人告白、去見想見的人、去做想做的事。而我也銘記在心,但終究還是留遺憾了。

幾個月前和自己重要的人,斷絕聯繫了,還有許多話沒說、還有好多想做的事還沒和他一起做,可是一切都太遲了,再也來不及了。希望下一次遇到自己重視的人,都能好好把握住,不留遺憾。

4.或許沒有下次了,好好珍惜吧:

愛情是個特別的東西,永遠沒有為什麼,或許你今天還在跟另一半擁抱,隔天他就傳訊息說「我們分手吧」,很難知道會不會突然有一天,你愛的人突然就說不愛你了

所以,重要的人給你的每個擁抱、親吻、見面,都好好珍惜吧!因為誰知道,搞不好沒有下次了。


「一期一會」這是個簡單的四個字,道理並沒有很深,只是提醒我們,當下的每個瞬間,都是此生唯一的一次

台北行程規劃

· One min read

8/6要去台北聽張育瑞大師的音樂會!!

注意事項

1.取票:到全家機台點KKTIX 取票號碼:51046712

2.音樂會地點:臺北市政府親子劇場
   搭乘板南線(往南港)市政府站 2號出口 (走市府連通道)

3.注意時間安排,音樂會19:30開始

希望當天順利,非常期待音樂會!

另外,8/7要去新竹上主修、副修
主修12:30 副修15:30
上課加油啊~