文章加密

;

2024年11月28日 星期四

ts, 特別注重css

css:

1.
父元素底下的子元素間距離左邊的元素間格8px並且不加在最後一個元素上,省了寫not last child的部分
.alert {
  padding:10px;
  >*+* {
     margin-left: 8px;
   }
}




2. v-bind在css 是vue3的var() 語法糖

限制與注意事項

  1. 數值需自行加單位
    如果綁定的值是數字,記得附加單位,例如:

    margin-top: v-bind(gap + 'px');
  2. 僅支持樣式作用域內
    v-bind() 只能用在 <style scoped> 中,不能直接用於全局樣式。

  3. 瀏覽器兼容性
    這依賴於 CSS 變數,因此需要現代瀏覽器的支持。


<template>
  <div class="box"></div>
</template>

<script>
export default {
  props: {
    gap: {
      type: String,
      default: '10',
    },
  },
};
</script>

<style scoped lang="scss">
.box {
  padding-top: v-bind(gap +'px'); // 將 props.gap 動態綁定到 CSS
}
</style>



// 以下 var()
<template>
  <div class="dynamic-box" :style="`--dynamic-color: ${color};`">
    Styled by props!
  </div>
</template>

<script>
export default {
  props: {
    color: {
      type: String,
      default: 'blue',
    },
  },
};
</script>

<style lang="scss">
.dynamic-box {
  background-color: var(--dynamic-color);
  padding: 10px;
  border: 1px solid var(--dynamic-color);
}
</style>



3.
  • :deep(.a + .a)
    這表示選擇作用域內類名為 .a 的元素,並選中其後直接緊接另一個 .a 元素的組合。這是正確且有效的寫法。

  • :deep(.a) { & + .a { } }
    這是一種嵌套的寫法,表示與上一個寫法等價,選擇 .a 元素,並設置它後面直接相鄰的 .a 元素樣式。

因此,兩種寫法的選擇器目的是相同的。


4. constant()env() 是 CSS 函數,用於訪問環境變數。這些變數通常由設備或瀏覽器設置,用於適配特定設備(例如具有瀏海的手機)。它們最常用於處理安全區域(safe area insets)的布局。


1. constant()

  • 概念constant() 是早期的 CSS 函數,曾被用來引用瀏覽器環境變數,例如 iOS Safari 中的安全區域(safe area)。
  • 狀態已被廢棄,現已由 env() 取代。
  • 支持情況:僅支持一些舊版的 iOS Safari(12 及更早版本)。

範例:

padding-top: constant(safe-area-inset-top);

在支持的瀏覽器中,這會將 padding-top 設置為設備頂部的安全區域高度。


2. env()

  • 概念env() 是現代 CSS 中推薦的方式,用於訪問環境變數,提供對設備特定屬性的支持,例如安全區域。
  • 支持情況:現代瀏覽器,包括 iOS Safari、Chrome 等。

範例:

padding-top: env(safe-area-inset-top);

這是目前標準方式,用來確保內容不會與瀏海等設備元素重疊。


使用場景

這兩個函數通常用於適配帶有安全區域的設備,尤其是 iPhone 帶有瀏海或圓角的情況。

常見環境變數

  • safe-area-inset-top:安全區域的上間距
  • safe-area-inset-bottom:安全區域的下間距
  • safe-area-inset-left:安全區域的左間距
  • safe-area-inset-right:安全區域的右間距

範例:

body { padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }





結論

  • 如果需要兼容舊版 iOS Safari:可以同時使用兩者,例如:
    padding-top: constant(safe-area-inset-top); padding-top: env(safe-area-inset-top);
  • 在現代開發中,優先使用 env(),因為它是 CSS 的標準化功能且被廣泛支持。


5.字面量类型 ( Literal type )是 JavaScript 本身提供的一个准确变量

type Status = 'success' | 'error' | 'pending';  // 用|設定多的types,叫做union types 聯合型別

let requestStatus: Status = 'success'; // 僅允許這三種值


測驗練習:

function iTakeFoo(foo: 'foo') {}
const test = {
  someProp: 'foo'
};

iTakeFoo(test.someProp); // Error: Argument of type string is not assignable to parameter of type 'foo'

这是由于 test 被推断为 { someProp: string },我们可以采用一个简单的类型断言来告诉 TypeScript 你想推断的字面量:

function iTakeFoo(foo: 'foo') {}

const test = {
  someProp: 'foo' as 'foo'
};

iTakeFoo(test.someProp); // ok

或者使用类型注解的方式,来帮助 TypeScript 推断正确的类型:

function iTakeFoo(foo: 'foo') {}

type Test = {
  someProp: 'foo';
};

const test: Test = {
  // 推断 `someProp` 永远是 'foo'
  someProp: 'foo'
};

iTakeFoo(test.someProp); // ok

6.keyof 顧名思義就是把「物件型別(object type)」的 key 拿出來,但要留意的是,這裡提到的是「物件型別」,而不是真的「物件」,前者是 TypeScript 的型別,後者是 JavaScript 中的一個物件(object):

// Person 是一個 object type
type Person = {
  firsName: string;
  lastName: string;
};

// person 是 JavaScript 的 object (value)
const person = {
  firstName: 'Aaron',
  lastName: 'Chen',
};

2024年11月1日 星期五

vue3 component reactive 用:key

 https://michaelnthiessen.com/force-re-render/


vue3 component reactive 用:key

 component裡面不用加,加在父層就可以了

2024年10月24日 星期四

reduce 做資料分組

 告訴我下面這段程式在做什麼? const list =txList.value.reduce((acc, item)=>{ if(!acc[item.txTerm])){ acc[item.txTerm] = [] } acc[item.txTerm].push(item) return acc },{}) ||[]; return list })

ChatGPT 說:
ChatGPT

這段程式碼的主要功能是將 txList.value 中的項目根據 txTerm 屬性進行分組。以下是程式碼的逐步解析:

  1. txList.value.reduce(...): 使用 reduce 方法來遍歷 txList.value 陣列,並將每個項目依據其 txTerm 屬性進行分組。

  2. (acc, item) => {...}: 這是一個回調函數,acc 是累積器,用來保存分組結果,item 是當前正在處理的項目。

  3. if(!acc[item.txTerm]): 檢查累積器 acc 中是否已經存在以 item.txTerm 為鍵的屬性。如果不存在,就創建一個空陣列。

  4. acc[item.txTerm].push(item): 將當前項目 item 添加到相應的 txTerm 鍵的陣列中。

  5. return acc: 返回累積器,繼續下一個項目的處理。

  6. {},: reduce 的初始值設為一個空物件 {}

  7. || []: 如果 reduce 的結果為假值(例如 undefined),則返回一個空陣列。

最後,這段程式碼的結果是將 txList.value 中的項目分組後返回的物件,其中每個 txTerm 對應一個項目陣列。

你說:
可以給個例子嗎
ChatGPT 說:
ChatGPT

當然可以!假設 txList.value 的內容如下:

javascript
const txList = { value: [ { id: 1, txTerm: 'A', amount: 100 }, { id: 2, txTerm: 'B', amount: 200 }, { id: 3, txTerm: 'A', amount: 150 }, { id: 4, txTerm: 'C', amount: 300 }, { id: 5, txTerm: 'B', amount: 250 }, ] };

運行你提供的程式碼後,list 的結果將會是:

javascript
{ A: [ { id: 1, txTerm: 'A', amount: 100 }, { id: 3, txTerm: 'A', amount: 150 } ], B: [ { id: 2, txTerm: 'B', amount: 200 }, { id: 5, txTerm: 'B', amount: 250 } ], C: [ { id: 4, txTerm: 'C', amount: 300 } ] }

在這個結果中,每個 txTerm(A、B、C)對應一個包含相關項目的陣列。這樣就成功地將項目按 txTerm 分組了!

2024年10月14日 星期一

New Words

 InAppBroswer, 前端BFF(Backends For Frontends, 服務於前端的後端), gradle vs Maven

2024年10月3日 星期四

Cookie/ LocalStorage/ SessionStorage 差別

 https://ithelp.ithome.com.tw/articles/10268532

屬性CookielocalStoragesessionStorage
存儲容量較小,約 4KB較大,約 5MB較大,約 5MB
存放位置 瀏覽器 &  Server瀏覽器瀏覽器
持久性可設置過期時間永久性,除非清除瀏覽器資料關閉頁籤/瀏覽器後清空
使用場景身分驗證、追蹤與分析本地設置、離線應用臨時資料儲存、表單數據保留
Server請求時,會夾帶而外資訊,過多請求時,要注意可能產生效能問題資料存於 Client 端,與Server端無關,請求時不影響資料存於 Client 端,與Server端無關,請求時不影響

[TS] any v.s. unknown

unknown

我們不能夠對 unknown 型別的東西進行任何除了讀寫和比較以外的操作

功能一:保證變數的值不會被不小心地操作到

例子:

function compareArrayAtEven(arr1: unknown[], arr2: unknown[]): boolean {
    let diff = arr1.length - arr2.length;
    if(diff > 1 || diff < -1) return false;
    for(let i = 0; i < arr1.length && i < arr2.length; i++) {
        if(arr1[i] !== arr2[i] + 2) return false; // TypeScript 會在這邊報錯
    }
    return true;
}


功能二:負責把關來自外界的輸入

預防各種執行階段中的不可預期現象發生

例子:

export function splitString(arg: unknown): string[] {
    if(typeof arg == 'string') {
        // 檢查完了之後才做我們真正要做的事情,例如:
        return arg.split(',');
        // 此處 TypeScript 會正確地知道 arg 的型別為字串,
        // 因為剛才我們用 typeof 檢查過了。
        // 對於更複雜的型別檢查,可以用 instanceof 關鍵字、
        // 或是使用 TypeScript 的 TypeGuard 來達成,
        // 這是題外話,這邊先不深入討論。
    } else {
        // 否則看要怎麼進行錯誤處理;這邊的方法是傳回預設值
        return [];
        // 或者也可以丟出一個 Error 包含了我們自訂的錯誤訊息
    }
}


養成把對外 API 的參數宣告成 unknown 的好習慣,並且避免使用 TypeScript 中的 as 關鍵字來作型別斷言(取而代之地,應該使用 instanceof 或自訂的 TypeGuard 來確認型別)

any

any 隨便做都行,沒鑑別度

很大的程度上來說,是的;我個人現在是「TypeScript 程式碼中應該要幾乎沒有 any 才對」主張的擁護者。對於很多我接手的程式碼,我都會先搜尋出所有使用到 any 的地方,而它們大多都可以直接換成 unknown 而不用作額外的修改——而如果換成 unknown 之後某個地方因此就出現了編譯錯誤,那幾乎在所有的情況中,那都是突顯出了程式碼具有潛在的異味(bad smell),而釐清為什麼改成 unknown 之後有編譯錯誤、往往能讓程式碼變得更加健全

只有一種情況是我會勉強接受 any 的使用的,那就是當我們引入了一個第三方的型別,我們很清楚其規格、但是我們偏偏又沒有該型別的完整定義檔、而我們自己去寫定義檔又很浪費時間的時候。然而,這樣的使用有幾個前提是應該要遵守的:

  1. 使用了 any 型別的物件應該要充分地被封裝起來,使得使用它的程式碼都非常清楚該變數要怎麼操作。如果有很多程式碼依賴於該物件,那應該要提供一個有良好定義型別的介面來讓其它程式碼間接操作該物件,而不是讓所有程式碼直接取用它。
  2. 對於該物件傳回的值,應該馬上用型別斷言或型別檢查來確定其型別,而不是繼續讓傳回值維持 any 的狀態。

如果沒辦法做到這兩點,那最好還是花一點時間自己把該型別當中會用到的東西宣告一下,這不僅能讓程式碼更有條理,也可以避免很多潛在的手殘可能性。