Eva's Dev Notes

前後端、AI 與日常開發筆記

0%

有新東西就是要來快速嘗試一下~~ 注意 cursor 要是付費版才能使用

至 GitHub clone 專案 Cursor Talk to Figma MCP

然後遵循 README:Get Started 開始

它需要安裝 bun 套件管理工具

1
curl -fsSL https://bun.sh/install | bash

需要在你的專案根目錄執行:

1
2
cd /path/to/your/cursor-talk-to-figma-mcp
bun setup
1
2
3
4
5
# 啟動 WebSocket server(必須持續執行)
bun socket

# 啟動 MCP server(另開一個終端)
bunx cursor-talk-to-figma-mcp
1
2
3
4
5
6
7
8
9
10
// Add the server to your Cursor MCP configuration in ~/.cursor/mcp.json:

{
"mcpServers": {
"TalkToFigma": {
"command": "bunx",
"args": ["cursor-talk-to-figma-mcp"]
}
}
}

以下為圖示:

image.png

閱讀全文 »

在 Vue 中使用動態事件名稱的功能自 Vue 2.6.0 版本開始支持。可以使用 v-on 或 @ 來動態綁定事件名稱

簡單舉例:
根據裝置類型切換事件(桌機 vs 手機)

1
2
3
4
5
6
<script setup>
const event = ref(navigator.maxTouchPoints ? 'touchstart' : 'click')
const handle = () => console.log('Triggered on', event.value)
</script>

<button @[event]="handle">按我</button>

2.「檔案卡片」元件預覽或跳轉:

點擊 (click):選擇/下載檔案
滑鼠移入 (mouseover):預覽檔案摘要

1
2
3
4
5
6
7
8
9
10
<template>
<div class="file-card">
<button v-on="{ click: handleDownload, mouseover: handlePreview }">
{{ fileName }}
</button>
<div v-if="showPreview" class="preview-popup">
{{ previewText }}
</div>
</div>
</template>
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
<script setup lang="ts">
import { ref, computed, nextTick } from 'vue'

const props = defineProps<{ fileName: string; fileUrl: string }>()
const showPreview = ref(false)
const previewText = ref('Loading preview…')

// 點擊 → 觸發下載
const handleDownload = () => {
window.open(props.fileUrl, '_blank')
}

// 滑鼠移入 → 取得並顯示檔案摘要
const handlePreview = async () => {
showPreview.value = true
// 模擬 API 請求
await new Promise(res => setTimeout(res, 300))
previewText.value = `Preview of ${props.fileName}`
}

// 滑鼠移出後隱藏預覽
const hidePreview = () => {
showPreview.value = false
}

// 監聽滑鼠離開整個卡片
const cardRef = ref<HTMLElement | null>(null)
cardRef.value?.addEventListener('mouseleave', hidePreview)
</script>

<style scoped>
.file-card { position: relative; display: inline-block; }
.preview-popup {
position: absolute;
top: 100%;
left: 0;
padding: 0.5rem;
border: 1px solid #ccc;
background: white;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
</style>

Demo

注意:在「同一欄位會因不同情境而切換觸發事件」時,才建議用動態綁定。若只是單純切換事件名稱,建議直接在方法內判斷即可。

也可參考 Michael Hoffmann 這裡的另一實作方式:
https://stackblitz.com/edit/vue-tip-dynamic-event-names?file=src%2FApp.vue

在開發 React 或 Vue 應用時,動態組合 Tailwind CSS class 是常見的需求。但當 class 來源多樣(例如 props 傳入、條件渲染等),你可能會遇到 class 重複、衝突或難以維護的問題,這時候,twMerge 就能幫助你解決這些困難。

什麼是 twMerge

twMerge 是一個專為 Tailwind CSS 設計的 class 合併工

  • 衝突解決:當你從不同來源(例如預設樣式和 props 傳入的 class)合併 class 時,可能會出現相同屬性的重複定義,twMerge 會自動解決這些衝突,保證最終只保留正確的 class。
  • 動態組合:在實際應用中,很多時候 class 字符串是根據條件組合出來的,直接拼接可能會導致意料之外的覆蓋。twMerge 能夠讓你的 class 合併更有條理,避免混淆。

安裝方式:

1
2
3
4

npm install tailwind-merge
# 或
yarn add tailwind-merge

基本使用範例:

1
2
3
4
5
6

import { twMerge } from 'tailwind-merge';

const classes = twMerge("p-4", "p-2");
console.log(classes); // 輸出: "p-2"(自動移除衝突的 p-4)

閱讀全文 »

  • S 指的是 Single responsibility principle(SRP) 單一職責原則
  • O 指的是 Open/close principle(OCP) 開放/封閉原則
  • L 指的是 Liskov substitution principle(LSP) Liskov 替換原則
  • I 指的是 Interface Segregation Principle(ISP) 介面隔離原則
  • D 指的是 Dependency Inversion Principle(DIP) 依賴反轉原則

Single responsibility principle(SRP) 單一職責原則

一個 class 別應該只有一個職責,並且只應該因為一個理由而改變。

C# 程式碼範例:

以違反 SRP 的範例:
在這個範例中,User 類別同時負責使用者資料的管理、資料庫儲存、發送歡迎信和使用者驗證等多個職責。這違反了 SRP。

1
2
3
4
5
6
7
8
9
10
11

public class User
{
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }

public void SaveUserToDatabase() { /* 資料庫儲存邏輯 */ }
public void SendWelcomeEmail() { /* 發送歡迎信邏輯 */ }
public bool ValidateUser() { /* 使用者驗證邏輯 */ return true; }
}

符合 SRP 的範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

public class User
{
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }
}

public class UserRepository
{
public void SaveUser(User user) { /* 資料庫儲存邏輯 */ }
}

public class EmailService
{
public void SendWelcomeEmail(User user) { /* 發送歡迎信邏輯 */ }
}

public class UserValidator
{
public bool ValidateUser(User user) { /* 使用者驗證邏輯 */ return true; }
}

在這個範例中,我們將不同的職責分離到不同的類別中:

  • User 類別只負責使用者資料的管理。
  • UserRepository 類別負責資料庫儲存。
  • EmailService 類別負責發送歡迎信。
  • UserValidator 類別負責使用者驗證。
    這樣做使得每個類別都只有一個職責,並且只因為一個理由而改變,符合了 SRP。

從前端的解度來理解

在前端開發中,我們經常使用元件 (Component) 的概念來構建使用者介面。一個元件通常負責渲染一部分的 UI,並處理與該部分 UI 相關的互動。這與 SRP 的概念非常相似。一個好的前端元件應該只負責單一的職責,例如:

顯示資料: 只負責接收資料並將其渲染到 UI 上。
處理使用者輸入: 只負責處理使用者在介面上的輸入事件,例如按鈕點擊、表單提交等。
發送 API 請求: 只負責向後端發送 API 請求並處理回應。

閱讀全文 »

除了基礎運算子(如 Where、Select 和 OrderBy),LINQ 還提供了許多進階運算子,用於解決更複雜的查詢需求。以下是一些使用頻率較高的進階運算子,以及它們的功能與應用場景。

Projection Operators 投影

Select

範例:投影字串清單中每個字串的第一個字母。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<string> words = ["an", "apple", "a", "day"];

var query = words.Select(word => word.Substring(0, 1));

foreach (string s in query)
{
Console.WriteLine(s);
}

/* This code produces the following output:

a
a
a
d
*/

SelectMany

SelectMany 將一個集合中的子集合展平(Flatten),生成單一層級的結果序列。它非常適合處理嵌套集合。

適用場景:需要從多個子集合中提取元素,並將它們組合為單一集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
List<string> phrases = ["an apple a day", "the quick brown fox"];

var query = from phrase in phrases
from word in phrase.Split(' ')
select word;

foreach (string s in query)
{
Console.WriteLine(s);
}

/* This code produces the following output:

an
apple
a
day
the
quick
brown
fox
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
List<string> phrases = ["an apple a day", "the quick brown fox"];

var query = phrases.SelectMany(phrases => phrases.Split(' '));

foreach (string s in query)
{
Console.WriteLine(s);
}

/* This code produces the following output:

an
apple
a
day
the
quick
brown
fox
*/

在提供一個,處理多對多關係數據(如學生和他們的選修課程)。
範例:攤平學生的課程清單

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

var students = new[]
{
new { Name = "Alice", Courses = new[] { "Math", "Physics" } },
new { Name = "Bob", Courses = new[] { "Biology", "Chemistry" } }
};

// 展平成單一課程清單
var allCourses = students.SelectMany(s => s.Courses);

Console.WriteLine("所有課程:");
foreach (var course in allCourses)
{
Console.WriteLine(course);
}

輸出結果

1
2
3
4
5
6

所有課程:
Math
Physics
Biology
Chemistry
閱讀全文 »

C# 的 LINQ (Language Integrated Query,語言整合查詢) 是一個非常強大的功能,它讓你可以使用類似 SQL 的語法來查詢各種不同的資料來源。這意味著你可以用統一的方式來處理資料,無論資料是來自陣列、列表、資料庫、XML 或其他任何支援 LINQ 的來源。

LINQ 的兩種語法:

LINQ 有兩種主要的語法形式:

  • 查詢語法 (Query Syntax): 看起來很像 SQL 語法,使用 from、where、select 等關鍵字。這種語法比較易讀,尤其是在處理複雜的查詢時。
  • 方法語法 (Method Syntax): 使用擴充方法 (Extension Methods) 來表示查詢運算子。這種語法更簡潔,也更靈活。簡單的查詢或需要鏈式操作時,通常使用方法語法更為方便。
閱讀全文 »

class 是物件導向程式設計 (OOP) 語言的核心功能。它通過邏輯性地組織方法和屬性,來表示並封裝特定的問題概念。

建立 class 與 instance

假設要建立一 person 的 class

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public class Person
{

}

public class Program
{
public static void Main()
{
Person person = new Person();
}
}

閱讀全文 »

新的一年有機會在公司內部接觸一些些後端語言,公司的後端是 ASP.Net,所以開啟了 C# 學習之路
最最初階的學習資源,目前是來自:
dotnetcademy
適用於初學者的 C# 基礎知識

宣告變數,需指定其類型並提供名稱

C# 是 強型別語言 (Strongly Typed Language),這表示每個變數 (Variable) 或常數 (Constant) 在使用之前都必須先明確定義其型別 (Type)。

1
2
3
4
string greeting;
int a, b, c;
List<double> xs;

閱讀全文 »

Write a class that allows getting and setting key-value pairs, however a time until expiration is associated with each key.

The class has three public methods:

set(key, value, duration): accepts an integer key, an integer value, and a duration in milliseconds. Once the duration has elapsed, the key should be inaccessible. The method should return true if the same un-expired key already exists and false otherwise. Both the value and duration should be overwritten if the key already exists.

get(key): if an un-expired key exists, it should return the associated value. Otherwise it should return -1.

count(): returns the count of un-expired keys.

中文說明

set(key, value, duration): 接受一個整數的 key、一個整數值 value,以及一個毫秒為單位的時間 duration。當持續時間結束後,這個鍵值對將不能被存取。如果相同且未過期的鍵存在,則回傳 true,若不存在則回傳 false。如果這個鍵已經存在,其值與持續時間都應該被新傳入的 value 與 duration 覆寫。
get(key):如果存在未過期的鍵,回傳其對應的值。若沒有相對應的鍵,則回傳 -1。
count():回傳現存未過期的鍵的總數量。

閱讀全文 »

Python 的安裝步驟

為什麼要學習 Python?

最近發現 GitHub 上許多新專案都適用 Python 或是要使用的 AI 工具也會是使用 Python 開發,於是決定也來學學 Python!

如何安裝 Python?

  • 前往 Python 的官方網站 下載安裝程式。
  • 按照安裝程式的指示完成安裝。
  • 安裝完成後,打開終端機(或命令提示字元),輸入以下指令確認安裝是否成功:
    1
    python --version
  • 若您有多個專案需使用不同的 Python 版本,建議使用版本管理工具,例如 pyenv。
閱讀全文 »