部落格

不定期分享技術文章

  • article-Day 30 遲來的完賽

    2024/1/9

    React JavaScript
    Day 30 遲來的完賽

    該給這系列一個交代,去年還在資策會進行培訓,正好在學習 React,看到鐵人賽的活動,就想說來試試看,但是沒想到有點高估自己的能力,到了最後專題的時刻忙得不可開交,在時間分配上沒做好拿捏而停賽了,雖然如此但一職還是想把這個系列補完,但一連串忙下來,回過神來就已經開始在職場上工作了,所以就一直拖到現在,現在終於有時間可以把這個系列補完了,去年的目標也算是達成了吧~

  • article-Day 29 React的本質-Library

    2024/1/2

    React JavaScript
    Day 29 React的本質-Library

    雖然 React 現在被稱作 3 大框架其中之一,但是如果現在打開 React 的官網,會發現它的定位是一個 Library,而不是一個 Framework,事實上 React 確實保持著高度靈活性,讓開發者可以自由的選擇其他的 Library 來搭配使用,這也是為什麼 React 能夠在短短幾年內就成為主流的原因之一。甚至在搭配的套件上也有許多不同的選擇,像是 Redux、React-Router、React-Bootstrap 等等,這些套件都是為了滿足不同的需求而生的,而且都是由社群開發的,這也意味著 React 的生態系非常的豐富,而且也有許多的資源可以參考,這也是 React 能夠快速成長的原因之一。今天就來試著用一個簡單的例子來說明 React 的本質吧!

    使用 CDN 引用 React

    跟許多其他的 Library 一樣,React 也可以透過 CDN 的方式來引用,這樣就不需要透過 npm 或是 yarn 來安裝,,只需要在 HTML 中引用 React 的 CDN 就可以使用了,以下是範例,可以直接複製貼上到 HTML 中,然後用套件 liveserver 打開就可以看到 console 結果了。可以看到 React 跟 ReactDOM 可以是使用的方法,而且還有 babel,這是因為 React 的語法是 JSX,所以需要 babel 來轉換成 JavaScript 才能執行。

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body>
        <div id="rrot"></div>
        <script
          crossorigin
          src="https://unpkg.com/react@18/umd/react.development.js"
        ></script>
        <script
          crossorigin
          src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
        ></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
        <script type="text/babel">
          console.log(React, ReactDOM);
        </script>
      </body>
    </html>
    

    React CDN 使用範例

    接續上一個例子,這次就來試著使用 React 的元件吧!首先要先創造一個元件,然後再把它渲染到 root 根元素上,以下是範例:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body>
        <div id="root"></div>
        <script
          crossorigin
          src="https://unpkg.com/react@18/umd/react.development.js"
        ></script>
        <script
          crossorigin
          src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
        ></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
        <script type="text/babel">
          // 創造元件
          const App = () => &#123;
            return (
              <div>
                <h1>Hello World</h1>
              </div>
            );
          &#125;;
          // 把App元件渲染至root根元素
          ReactDOM.render(<App />, document.getElementById("root"));
        </script>
      </body>
    </html>
    

    總結

    大家可以發現,我這裡只是單純的使用 HTML 而已,並沒有使用太複雜的環境建置工具,雖然實務上不會這樣使用,但是我這裡只是想要表達 React 並不是那麼的難以接近,在官方定義成 library 的前提下,至少在一開始的學習上心態上可以抱持輕鬆一點的態度,不用太過於緊張。

  • article-Day 28 React 的 Hello World-Hook-useState

    2023/10/12

    React JavaScript
    Day 28 React 的 Hello World-Hook-useState

    要說 React 有什麼特別的地方我覺得應該就是 HooK 了吧!Hook 是在 React 16.8 版中加入的,hook 有很多種,每一種的功能都不太一樣,甚至還可以自定義,簡單來說它就是函式,然後可以重複一直使用。但其實這是一個有點抽象的概念,所以就直接從實際的例子來了解吧!

    什麼是 useState?

    這是 React 最基本的一個 hook 之一,它的作用是儲存某個變數的狀態;並設定更新它的方法,基本寫法如下:

    const [變數名稱, set變數名稱] = useState(初始值);
    

    有三點需要注意: 1.需要依照小駝峰的規則撰寫 2.盡量給初始值,也就是變數名稱最一開始的狀態 3.變數只能被 set 變數做改變,使用方法就是在裡面塞一個更新後的數值

    以下舉個例子:

    宣告一個名為 count 的變數,此變數只能透過 setCount 做改變,且初始值為 0

    const [count, setCount] = useState(0);
    setCount(1); //更新此變數為1
    

    useState 的作用?

    因為在 React 中,不應該直接修改元件函式內部的變數,因為這不會觸發重新渲染元件。必須要使用 React 提供的狀態管理來處理這類情況,所以下面的例子:來展示其中差異

    1.沒使用 useState:畫面的按鈕會沒有作用

    function App() &#123;
      let a = 0;
      return (
        <>
          <button
            onClick=&#123;() => &#123;
              a = a + 1;
            &#125;&#125;
          >
            按鈕
          </button>
          <h1>現在數值:&#123;a&#125;</h1>
        </>
      );
    &#125;
    
    export default App;
    

    2.使用 useState:才能改變狀態

    function App() &#123;
      const [a, setA] = useState(0);
    
      const handleIncrement = () => &#123;
        setA(a + 1);
      &#125;;
    
      return (
        <>
          <button onClick=&#123;handleIncrement&#125;>按鈕</button>
          <h1>現在數值: &#123;a&#125;</h1>
        </>
      );
    &#125;
    
    export default App;
    

    總結

    在 React 中與畫面有關的變數都需要 useState 來做一個所謂的狀態管理,才能觸發重新渲染畫面,而且這個變數只能透過跟它同組宣告變數的方法做改變。

  • article-Day 27 React 的純函數元件

    2023/10/11

    React JavaScript
    Day 27 React 的純函數元件

    今天要解釋的東西會比較無聊乏味一點,但在 React 元件化導向的框架裡卻是一個很重要的概念,因為元件具有可以重複使用的特性,所以如果不是純函示會有一些 Bug 存在。

    純函式的特性

    純函式是一個在軟體開發中的重要概念,它有以下主要特點:

    1. 相同的輸入始終產生相同的輸出: 當你將相同的輸入值傳遞給一個純函式時,它始終會返回相同的輸出,不受外部狀態的影響。這種可預測性對於測試和除錯非常重要,因為你可以確信函式的行為不會因為外部狀態的改變而變化。

    2. 不會修改外部狀態: 純函式不會修改或影響除了它的輸入參數以外的任何狀態。這意味著它不會修改全域變數、不會修改傳遞給它的物件或陣列,也不會修改任何外部狀態。

    3. 沒有副作用: 純函式不會引起任何副作用,如改變資料庫的數據、發送 HTTP 請求、修改文件系統等。它僅僅是通過計算返回一個值。

    4. 可組合性: 由於純函式不依賴於外部狀態,它們非常容易組合在一起建構更複雜的邏輯。這種特性使得代碼更容易維護、測試和重用。

    解釋了那麼多,我相信大家看了眼睛都花了而且一頭霧水,簡單舉例如下:
    這就是一個純函式,不會修改外部狀態、沒有副作用、相同輸入有相同輸出

    function add(a, b) &#123;
      return a + b;
    &#125;
    

    這個 add 函式是純函式,因為它始終返回相同的輸出(兩個數字的和),不修改外部狀態,也不產生副作用。

    那不是純函式又會發生什麼事呢?範例如下:

    let total = 0;
    
    function addToTotal(num) &#123;
      total += num;
      return total;
    &#125;
    
    console.log(addToTotal(3)); // 第一次呼叫,返回 3
    console.log(addToTotal(3)); // 第二次呼叫,返回 6
    

    這就不是一個純函式,因為它會改變外部狀態而且,相同的輸入得到不同的輸出。

    那想一想如果它是一個元件,我們重複使用三次會發生什麼事?
    範例如下:

    let total = 0;
    
    function AddToTotal() &#123;
      total += 1;
      return <h2>&#123;total&#125;</h2>;
    &#125;
    
    function App() &#123;
      return (
        <div>
          <h1>引入第一次</h1>
          <AddToTotal /> //2
          <h1>引入第二次</h1>
          <AddToTotal /> //4
          <h1>引入第三次</h1>
          <AddToTotal /> //6
        </div>
      );
    &#125;
    
    export default App;
    

    就會發現明明就是引入同一個元件,但是會產生不同的結果,這會在重複使用這個元件特性上,造成無法預期的錯誤,所以 react 會鼓勵元件的寫法都要以純函式為主。

    總結

    雖然無聊或是繁瑣,但是如果發生想不到的錯誤就來檢查看看是不是純函式的問題,但後續其實有相對應的解法,但也續本系列不會提到,但是不純的函式在 react 元件中應該盡量被避免的。

  • article-Day 26 React 的多重渲染-列表與 Key

    2023/10/10

    React JavaScript
    Day 26 React 的多重渲染-列表與 Key

    在 react 使用遍歷陣列的方法來呈現畫面是挺常見的,我們今天想要呈現一個陣列裡面的資料如下:

      const tasks = [
        { id: 1, text: "看完 React的文件 " },
        { id: 2, text: "寫一篇部落格文章" },
        { id: 3, text: "學習 JavaScript" },
      ];
    

    基本上我們不可能一個一個複製貼上,所以會利用 JSX 的 JavaScript 方法,去讀取資料並呈現畫面,有點像是 PHP 那樣的感覺。看範例寫法如下:

    function App() &#123;
      const tasks = [
        &#123;id: 1, text: "看完 React的文件 "&#125;,
        &#123;id: 2, text: "寫一篇部落格文章"&#125;,
        &#123;id: 3, text: "學習 JavaScript"&#125;,
      ];
    
      return (
        <div>
          <h1>我的任務清單</h1>
          <ul>
            &#123;tasks.map((task) => (
              <li key=&#123;task.id&#125;>&#123;task.text&#125;</li>
            ))&#125;
          </ul>
        </div>
      );
    &#125;
    export default App;
    

    上面的範例是使用 map 的方法,不過這裡使用 forEach 也可以,差異是 map 會回傳新陣列但是 forEach 不會,至於 React 中為什麼會慣用 map 的原因與 hook 中的 useState 有關,這裡就先不多做贅述。

    key 值的作用

    仔細看上述的程式碼,會發現與正常遍歷陣列的方法不同的是多了一個 Key 值,它的作用是讓 react 能區別每一筆資料,雖然如果不給 key 值 react 會預設 index 當作 key 值,但是這不是一個好的寫法,因為可能會產生不穩定性(像是在對陣列操作增加、刪除之類的),造成渲染畫面的不確定性。

    所以設定 key 值需要注意以下條件: 1.唯一性 2.必須從外部設定,不要再遍歷函示產生 3.不能隨意地被改變

    總結

    以上就是渲染陣列物件基本的方法,而且會與後續在使用 Hook 的順暢度會有直接的關係。

    參考資料

    React 官方網站

  • article-Day 25 React 的選擇渲染-JSX 與條件控制的關係

    2023/10/8

    React JavaScript
    Day 25 React 的選擇渲染-JSX 與條件控制的關係

    說到 JavaScript 的流程控制大家很容易聯想到 if…else…或是三元運算子,在 JSX 裡面可以利用這些流程控制來選選擇性的呈現想要渲染的畫面。

    官網分別介紹三種:
    1.if..else 2.三元運算子(條件式 ? True 的結果 :False 的結果) 3.邏輯運算子(&&)

    用 if…else..控制元件出現

    這我相信能看到這裡的,大家都對這個語法很熟,但在 React 寫法就變成下面這樣,如果 number=”A”就會 return 並渲染 “AAA”,除此之外會 return 並渲染 “BBB”。

    export default function App() &#123;
      let number = "123";
    
      if (number === "A") &#123;
        return (
          <>
            <h1>AAA</h1>
          </>
        );
      &#125; else &#123;
        return (
          <>
            <h1>BBB</h1>
          </>
        );
      &#125;
    &#125;
    

    條件運算子

    ES6 的語法,簡單來說就是 if else 的簡化版,但是略有些差異以及特性,這裡就不先多提,因為在這裡兩者幾乎是等效的。
    它由一個?和:組成基本架構如下:

    條件式 ? 條件式為真要輸出的結果 : 條件式為假的時候要輸出的結果;
    

    如果更改上述的範例為三元運算子的寫法如下:

    export default function App() {
      let number = "A";
      return number === "A" ? <h1>AAA</h1> : <h1>BBB</h1>;
    }
    

    或是這樣

    export default function App() {
      let number = "A";
      return (
      <>
      {number === "A" ? <h1>AAA</h1> : <h1>BBB</h1>}
      </>
      )
    

    看起來更為簡單一點,可是在對於剛接觸的人比較不容易閱讀,要注意的一點

    三元運算子是運算子它不是陳述式所以可以寫在 jsx 的{}裡,但是 if…else 則不行

    邏輯運算子(&&)

    這部分的寫法就更為簡單一點,但是適用的情況也不太一樣,比較適用決定是否要呈現元件,而不是選擇性呈現,寫法如下

    export default function App() {
      return <>{true && <h1>AAA</h1>} </>;
    }
    

    總結

    雖然這三種寫法都是在做元件的選擇性渲染,但其實每一種方法適用的情境略有不同,需要依照適合的狀況,選擇適合的寫法:

    • 使用 if…else 時,可以處理較複雜的條件邏輯。
    • 三元運算子 提供了簡潔的寫法,適用於簡單的條件選擇。
    • 邏輯運算子 (&&) 適合單一條件,不需要額外 else 或 return null。

    參考資料

    React 官方網站

  • article-Day 23 React 中的 JavaScript

    2023/10/7

    React JavaScript
    Day 23 React 中的 JavaScript

    今天要介紹的是 JSX 重要的部分,就是如何在 JSX 中寫 JavaScript,其實很理所當然的 JSX 來就是 JavaScript,所以能寫 JavaScript 是一件蠻合理的一件事情,但依然有些規則需要遵守。接下來就依序來介紹吧!

    1.使用大括號{}處理 Javascript

    (1) 像是變數或是函式都可以在大括號裡被使用舉例如下:

    function App() &#123;
      const name = "AAA";
    
      return (
        <>
          <p>My name is &#123;name&#125; </p>
        </>
      );
    &#125;
    
    export default App;
    

    (2) 大括號的使用範圍

    • 標籤內的文本
    <p>My name is &#123;name&#125; </p>
    
    • 在=後面的屬性
    <src=&#123;picture&#125; img/>//pictrue可能為一個變數
    

    2.使用 CSS inline styles

    需要使用兩層大括號,第一層是 JSX 要使用 JavaScript 規定的;第二層是因為 inline styles 被當作一個物件傳遞所以有大括號

    <p style=&#123;&#123;color: "white", backgroundColor: "black"&#125;&#125;>My name is &#123;name&#125; </p>
    

    3.在大括弧中放表達式,不能陳述式

    首先來複習一下什麼式表達式,可回傳一個結果的程式片斷就是一個表達式簡單來說,下列就是一個表達式,因為 console.log 會回傳 3

    1 + 2;
    

    為什麼會突然提這個呢?因為常用流程控制 if else 就是陳述式,所以這樣寫會報錯的喔!下面就是一個很經典的例子,這裡先留一個梗後續的文章會在說明,簡單來說三元運算子不是陳述式。

    • 錯誤示範
    function App() &#123;
      const a = "true";
      const b ="false"
    const judge = true;
      return (
        <>
          &#123;if(judge)&#123;
            &#123;a&#125;
          &#125;else&#123;
            &#123;b&#125;
          &#125;&#125;
        </>
      );
    &#125;
    export default App;
    
    • 正確示範
    function App() &#123;
      const a = "true";
      const b = "false";
      const judge = true;
    
      return <>&#123;judge ? a : b&#125;</>;
    &#125;
    
    export default App;
    

    總結

    今天的重點其實很簡單,要寫 JavaScript 就在{}裡面寫就對了,但不能寫陳述式。

  • article-Day 24 React 的橋樑-Prpos

    2023/10/7

    React JavaScript
    Day 24 React 的橋樑-Prpos

    Day24 React 的橋樑-Prpos

    Props 是一個元件之間傳遞資料的手段,它其實有點像是 HTML 標籤的屬性,實際上很多像是 HTML 標籤的屬性也被預設為 Props,例如 img 標籤的 src,alt 等等,但也可以自定義,有點像是 data-set 那樣,接下來就開始今天的主題吧!

    Props 的特性

    1.只能允許單向資料流

    簡單來說就是只能從父元件傳到子元件,要從子元件傳回去需要用其它特殊方法

    2.資料類型為物件

    3.不可被元件本身自己改變

    4.但可以被父元件改變

    5.可以自訂預設值,父元件如果沒給定值會自行套用

    範例

    1.將 props 傳給子元件

    <Child test="AAA" num=&#123;100&#125; />
    

    2.在子元件讀取傳遞的值

    Child(&#123;test, num&#125;);
    

    3.可以自訂預設參數

    <Child test="AAA" num=&#123;100&#125; />
    

    總結程式

    父元件

    import Child from "./child";
    
    export default function Parent() &#123;
      return (
        <>
          <h2>啟用預設值</h2>
          <Child />
          <h2>父元件改變props</h2>
          <Child test="AAA" num=&#123;100&#125; />
        </>
      );
    &#125;
    

    子元件

    export default function Child(&#123; test = "BBB", num = 10//自訂預設值&#125;) &#123;
      return (
        <>
          <h4>Child</h4>
          <p>text: &#123;test&#125;</p>
          <p>num: &#123;num&#125;</p>
        </>
      );
    &#125;
    

    props 傳遞參數的解構賦值

    事實上,上述的範例已經也在使用了,在一開始就提到 Props 是一個物件,如果照最原始的寫法應該如下,所以重頭到尾都只傳遞一個名為 props 物件的參數而已。

    export default function Child(props) &#123;
      return (
        <>
          <h4>Child</h4>
          <p>text: &#123;props.test&#125;</p>
          <p>num: &#123;props.num&#125;</p>
        </>
      );
    &#125;
    

    ESLint 處理

    PS:如果遇到”is missing in props validation”
    在.eslintrc.cjs 的 rules 加上下面這段

    "react/prop-types": "off",
    

    總結

    props 使用起來蠻直覺的,但是有其限制所在,如果需要更進一步的活用,要了解更後面的內容包刮 Hook 之類的內容,基本上在這著系列應該沒有什麼機會介紹到,畢竟是入門向的文章,如果有機會後續再作補充,明天就會介紹到比較偏向實作的內容了。

    參考資料

    React 官方網站

  • article-Day 22 React 的語法-JSX

    2023/10/6

    React JavaScript
    Day 22 React 的語法-JSX

    JSX 為 React 的語法,簡單的來說就是可以使用 JavaScript 來撰寫 HTML 標籤,然而官方文件也有提到,不用 JSX 也是可以,但多數的 React 開發者鑑於 JSX 便利性還是會選擇 JSX 語法,事實上也是如此 JSX 帶給我們許多方便的體驗,但相對的需要遵守一些規則。

    JSX 的規則

    1. JSX 的語法最外層只能有一個根元素

    這部份昨天也有稍微提到了,原因是因為到底 JSX 還是 JavaScript,而一個函式只能傳回一個東西而已。就像下面的例子,在怎麼樣複雜最外面一層等只會有一個根元素,通常是 div 標籤或是<></>(Fragment)

    <>
      <p>
        <ul>
          <li>132</li>
          <li>132</li>
          <li>123</li>
        </ul>
      </p>
      <p>
        <ul>
          <li>123</li>
          <li>123</li>
          <li>132</li>
        </ul>
      </p>
    </>
    

    2.標籤需要自閉合

    說穿了就是在只有單一標籤的後方加上/這樣舉例如下:

    <img/>
    <br/>
    <input/>
    

    3.使用小駝峰式命名給標籤的屬性名稱,舉例如下的 className

    <img src=&#123;reactLogo&#125; className="logo react" alt="React logo" />
    

    Note:

    因為 class 為保留字,所以在 JSX 中 class 就寫成className;同理 for 寫成htmlFor

    4.布林值,null,undefined 不會被渲染

    <>
      不會被渲染
      <div></div>
      <div>&#123;false&#125;</div>
      <div>&#123;null&#125;</div>
      <div>&#123;undefined&#125;</div>
    </>
    

    5.元件事件處理函式需要小駝峰

    <button onClick=&#123;&#125;><button>
    

    懶人包

    1.元件裡的最外層要長這樣子<></>

    return <>加小括弧是避免有自動加;出現</>;
    

    2.單標籤自閉合 3.小駝峰命名

    總結

    JSX 看似很囉唆但是裡面的每個規則都有相對的道理在,如果能去理解其實這些規則就相對應的記起來了。

    預告一下,明日就是介紹如何在 JSX 寫 JavaScript 囉~

    參考資料

    React 官方網站

  • article-Day 21 React 的元件形式

    2023/10/5

    React JavaScript
    Day 21 React 的元件形式

    元件(component)是 React 主要關鍵組成之一,它是一個可以被反覆利用的 UI 元素,不過說穿了 React 的文件中一直提到的元件,其實就是 function 每一個元件都是由一個 function 當然裡面內層可以有很多個但是最外層就是只有一個,所以元件就是 function,如此一來元件可以重複使用就合理許多了吧!因為 function 也可以一直重複使用。

    如何定義元件(component)

    這與其多說,不如來看範例吧!下列就是一個元件

    export default function Comp() &#123;
      return (
        <>
          <h1>我是一個元件</h1>
        </>
      );
    &#125;
    

    是不是跟 function 一模一樣,只是在 React 規定中元件開頭一定要大寫,然後要return出來是因為需要給其他地方使用,所以也需要匯出模組(ESM)給其他檔案使用。其實還有一點,不過是 JSX 的語法問題,最上層需要有個這樣的<></>根元素包住,換句話說 JSX 只能返回一個跟元素。

    整理上述所說的 React 元件基本架構有那些呢?

    React 元件的基本架構

    1.元件開頭命名一定要大寫 2.裡面需要 return 返回 3.最外層要有唯一一個標籤包住通常是<></>,當然也可以是其它標籤 4.如果要給其它檔案使用一定要匯出

    補充:進入點

    說的直白點所謂的進入點,就是專案架構的最上層,但以剛入門 React 的人來說通常不會先理會這層,以 vite 而言所謂的進入點就是 main.js,初始設定長下面這樣。

    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App.jsx";
    import "./index.css";
    
    ReactDOM.createRoot(document.getElementById("root")).render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
    

    所以,通常在 React 匯出是一個必須的動作,因為以一個專案來說,再怎麼樣都會需要給進入點來使用,

    元件的引用

    通常都是一個檔案一個元件,所以在引用元件的時候會做一個匯入的動作,而 React 在 render 元件的形式上也很特別,是以標籤的形式呈現,範例如下:

    import Comp from "./Comp"; //引用元件從其他檔案
    
    export default function App() &#123;
      return (
        <>
          &#123;/* 可以重複使用 */&#125;
          <Comp />
          <Comp />
          <Comp />
        </>
      );
    &#125;
    
    ps:在 vite 寫元件副檔名需要用 jsx

    當然如果想偷懶一個檔案寫一堆元件也是可以,但是就不用做引入的動作了,範例如下:
    只是不建議這麼而已

    export default function App() &#123;
      return (
        <>
          &#123;/* 可以重複利用 */&#125;
          <Comp />
          <Comp />
          <Comp />
        </>
      );
    &#125;
    
    //React 的元件形式
    function Comp() &#123;
      return (
        <>
          <h1>我是一個元件</h1>
        </>
      );
    &#125;
    

    總結

    元件是 React 中基本的形式,整個架構幾乎都是由元件構成的,當然還有其中很重要的構成是 JSX 雖然一直提到,但還沒做詳細介紹,這部分明日會做比較詳細的介紹。

    參考資料

    React 官方網站