###### tags: `前端課程` # React筆記 ## DOM (Document Object Model) 文件物件模型,把HTML文件的各個標籤定義成物件,這些物件最終會形成一個樹狀結構。 例: document.getElementById就是用id在向DOM取得元素 ![](https://i.imgur.com/RboVAQC.png) ## JSX JavaScript 的語法擴充,屬性名稱以小駝峰方是撰寫。 ```javascript=== const element = <h1>你好,世界!</h1>; ``` 上面的標籤語法不是一個字串也不是HTML。 而是把右邊的HTML當成一個物件存到變數中。 這種把HTML寫在JavaScript的程式碼中的技術 ```javascript= const showOne=true; const element = <h1>{showOne?1:0}</h1> ``` 可以在HTML標籤中利用「{}」寫JavaScript表示式 ```javascript= const styleArgument = { fontSize: '100px', color: 'red' }; ReactDOM.render( <h1 style = { styleArgument } > Hello, world! </h1>, document.getElementById('root') ); ``` style變為一物件、屬性名稱規則改用駝峰法(用大寫區隔)、屬性的值變成字串 ## Scss 1. 巢狀結構 ```javascript== #banner{ ... #logo{ // 等同於 #banner #logo ... img{ // 等同於 #banner #logo img ... } } nav{ //等同於 #banner nav ... } } ``` 2. &連接 ```javascript== a{ color:red; &:hover{ //等同於 a:hover color:red; } &:active{ //等同於 a:active color:blue; } } ``` ## ES5/ES6/ES7 ### ES5 * 嚴格模式 https://medium.com/itsems-frontend/javascript-strict-mode-d0a3aa74458b * Array/Object操作的方法 * Array.find * Array.filter * Array.map * ... ### ES6 * **箭頭函式 Arrow Functions** ```javascript== //不帶參數 //ES5 function func_name(){ console.log('Hello World!'); } //ES6 func_name = () =>{ console.log('Hello World!'); } //帶一個參數 //ES5 function func_name(e){ console.log(e); } //ES6 func_name = e =>{ console.log(e); } //帶兩個(含)以上參數 //ES5 function func_name(e,i){ console.log(e,i); } //ES6 func_name = (e,i) =>{ console.log(e,i); } //關於return func_name = () => something func_name = () =>{ return something; } ``` * **參數預設 Default Parameters** 傳入function的參數沒有給定值時,會出現Exception,最快的解決方法就是給定預設值,在ES6中給定預設值的方式更為快速簡單 ```javascript== BMI=(height=1.75, weight=65) => { let BMI=weight/(height^2); console.log(BMI); } ``` * **文字模板 Template Literals** ```javascript== // ES5 var name='Jack'; var start = 'Hello'+name+'!'; //ES6 const name='Jack' const start = `Hello ${name}!` ``` * **多行字串輸入 Multi-line Strings** ```javascript== // ES5 var fruit = 'apple,' + 'banana' //ES6 const fruit = `apple, banana` ``` * **解構賦值 Destructuring Assignment** ```javascript== const Jack={age:40,gender:'male'}; //一般 console.log(Jack.age,Jack.gender); //解構 const {age,gender}=Jack; console.log(age,gender); //console結果:40male //賦值 const Jack {age:x} = {age:40}; //x=40 ``` * **物件實字 Enhanced Object Literals** 假如object內的元素其key與value名稱一樣,可以省略key直接寫 value 名稱即可。 ```javascript== // ES5 var name = 'Jack'; var obj = { name: name }; // ES6 const name = 'Jack'; const obj = { name }; ``` * **宣告 Let and Const** * let可變動 * const不可變動,宣告時要給定initialize ```javascript== //let let a; a=10; console.log(a); a=20; console.log(a); //const const b=100; console.log(b); //下面可以拿掉註解測試看看 //b=200; //console.log(b); ``` * **Modules** import、export ## JSON * **包含Array、Object** * **成對的key:value,中間以:區隔** * **value可以是:** * 數字 (整數或浮點數) * 字串 (請用 "" 括號) * 布林函數 (boolean) (true 或 false) * 陣列 (請用 [ ]) * 物件 (請用 { }) * NULL ## Node.js安裝環境 https://nodejs.org/en/ ![](https://i.imgur.com/ge3obvh.png) ## Nvm安裝包 下載nvm-setup.zip https://github.com/coreybutler/nvm-windows/releases/tag/1.1.7 ## nvm(node version manger) 管理、切換node版本 #### 常用指令 * nvm ls:列出所有已安裝的node版本,前面有標`*`是目前使用的版本 * nvm install `<version>`:安裝某個版本的 node * nvm uninstall `<version>`:解除安裝指定版本 * nvm --version:查看nvm版本 * nvm use `<version>`:切換node版本 ## npm(node package manger) 套件管理工具可以下載各種應用,安裝nodejs的時候就會一起安裝了 #### 常用指令 * npm install:尋找該資料夾裡面的package.json去下載裡面定義好的所有套件 * npm init:專案初始化讀取package.json的資訊 * package.json 1. dependencies: 執行環境會需要 2. devDependencies: 開發或測試環境需要 * npm start:本地運行專案 * npm run build:將專案打包成webpack ## React 將程式元件化,由很多元件組成UI畫面,每個元件透過render渲染出樣式,渲染完成後根據資料的改變去變動網頁內容,不需要去刷新頁面 **優點:程式碼不用重複寫、網頁風格統一、修改方便** https://ithelp.ithome.com.tw/m/articles/10271212 ### Class Component 具有生命週期,具有State,需要引入React Component,一定要實作render https://ithelp.ithome.com.tw/m/articles/10232421 https://ithelp.ithome.com.tw/m/articles/10219057 ```javascript= import React, { Component } from "react"; import "./index.scss" export default class NewsCard extends Component { constructor(props) { super(props) } render() { const { cardImg, cardTitle, cardContent } = this.props; return ( <div className="card"> <div className="newsImg"> <img src={cardImg} /> </div> <div className="cardTitle">{cardTitle}</div> <span>{cardContent}</span> <div className="link"> <a href="">VIEW MORE</a><div className="line"></div> </div> </div> ); } } ``` ```javascript= import NewsCard from "../../Component/NewsCard"; <NewsCard cardImg={item.cardImg1} cardTitle="滑順不偏移 上下導輪鉸鏈" cardContent="台灣每年台灣每年台灣每年台灣每年台灣每年台灣每年都會迎來" /> <NewsCard cardImg={item.cardImg2} cardTitle="abcdefg" cardContent="happy birthday to you" /> ``` ### Functional Component 沒有生命週期,沒有State ```javascript= function Functional(props) { const sayHi =()=>{ console.log('hi') } return <button onClick={sayHi}>btn</button> } ``` 不過在Hook出現後functional Componet 也具有生命週期以及State ### props & state #### props React父元件與子元件間溝通的橋樑,是靜態(唯讀)的 #### state 元件存放資料的地方,以物件的方式存放(key:value),需要在constructor建立自身state,並且利用setState去改變state的值 ```javascript= constructor(props) { //若要使用這個方法 super(props) //必須先執行super(props),若有用到props的話會找不到this.props,沒用到props也可以只寫super() this.state = { currentPage: 'one', //給預設值 } } this.setState({ currentPage:'two' }) ``` ### 生命週期 ![](https://i.imgur.com/ikXCxKo.png) [**React Component 官方文件**](https://zh-hant.reactjs.org/docs/react-component.html) * constructor :用來初始化的地方,還沒渲染DOM的時候,假設沒有寫super() ,無法使用this * render:會進行渲染的,回傳JSX * componentDidMount: DOM已經渲染完成 ,在這個階段可以呼叫api來更新DOM ,適合做一些初始化的工作 * componentDidUpdate: 當props or state更新,就會觸發元件更新DOM,所以如果在這個階段setState會造成無限循環 * componentWillUnmount: 元件從DOM被移除 ,在這階段可以用來清除一些計時器 * getDerivedStateFromProps: 會在「每一次」跑 render() 之前被呼叫執行,當props、state改變就會觸發,在初始化的時候也會觸發一次 ### Hook 不必寫class就可以使用state #### useState & useEffect ```javascript= import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 與 componentDidMount 和 componentDidUpdate 類似: useEffect(() => { // 使用瀏覽器 API 更新文件標題 document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } ``` ### 專案架構 & 資料流 & Router #### 專案架構 | ---- /node_modules 套件安裝在這裡面 | ---- /public 靜態網頁 | ---- /src | ---- /assets 圖片 | ---- /components 元件庫 | ---- /layouts 頁面框架 | ---- /mixin 通用css | ---- /pages 頁面 | ---- /reducers 存取api回傳的資料 | ---- /routes 設定網頁路徑資料 | ---- /sagas 之funciton | ---- /services 存放api路徑及參數 | ---- /utils 工具庫(存放通用fuction) | ---- /config.js 撰寫api路徑之前綴 | ---- /index.js 進入點 | ---- /index.scss | ---- /Router.js 指路標 | ---- /.env 設定檔 | ---- /.env.exapmle 設定檔範例 | ---- .gitignore 忽略不上傳git的檔案 | ---- package-lock.json 記錄本次安裝的套件版本 | ---- package.json 記錄所有安裝的套件與版本 | ---- README.md #### 資料流 npm start index.js->Router(引入設定好的所有路徑/routes檔)->導向對應的layout和page-> saga->service->reducer->page * connect(mapStateToProps, mapDispatchToProps) * import { put, takeLatest, call, all } from "redux-saga/effects"; * yield ### 常用套件 #### Lodash * _.find * _.filter * _.map * _.get #### moment ```javascript== moment(<value>).format("YYYY-MM-DD HH:mm:ss") ``` #### PrimeReact https://www.primefaces.org/primereact/setup/ #### Mantine https://mantine.dev/getting-started/ #### Bootstrap https://react-bootstrap.github.io/components/alerts #### leaflet https://react-leaflet.js.org/ ![image](https://hackmd.io/_uploads/rJOLlrmT6.png)