你也可以讓React搭配TypeScript, 這之後別篇會講
Learn from MERN stack: https://www.youtube.com/watch?v=ngc9gnGgUdA
Create a new project
npx create-react-app my-app
cd my-app
npm start
會自動跳出default project產生的網頁頁面(http://localhost:3000/)
demo的index.js
的進入點在public資料夾中的index.html, 裡面有個div的id是root
如果想以絕對路徑的方式來import
在專案的根目錄底下可以新增一支 jsconfig.json 的檔案
// ./jsconfig.json
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
如此就可以使用絕對路徑的方式來載入模組
// 原本寫
// import Button from './components/Button';
// 設定後所有路徑都會以 /src 開始,因此可以改成
import Button from 'components/Button';
Create your component
混用DOM and VirtualDOM
createElement
這個 api 主要負責幫我們建立 React element,它可以接收至少三個參數
- 第一個可以是 HTML element,或是 component
- 第二個參數是 props
- 第三個參數之後都會被收集成 children,最後會回傳一個 React element
們帶進去的三個參數,第一個參數會成為 type 屬性的值,第二個參數物件會成為 props 屬性的值,而最後一個 ‘Hello world’,也被收集成在 prop 物件 中的 children 屬性的值
const rootEl = document.createElement('div')
document.body.append(rootEl)
// 寫法一
const element = React.createElement('div', {
children: 'Hello React!',
className: 'container'
})
// 寫法二
const element = React.createElement(
'div',
{ className: 'container' },
'Hello world'
)
ReactDOM.render(element, rootEl)
https://frontarm.com/james-k-nelson/4-ways-pass-children-react-elements/#2-createelement
React.createElement下props的children代表的是div的內容, className則是div的class 這是對應到原生DOM中的children與className屬性
小結
- 會回傳 React element (就是一個物件而已)
- 第一個參數能夠決定最後畫面渲染的 type
- 第二參數需要是一個 object 會成為 element 的 props 值
- ==第三個參數之後的值都會被收集在 props 中的 children 陣列==
JSX
JSX 語法是特殊的語法擴充,==一般的瀏覽器是沒辦法辨識 JSX 語法的== 這時候需要像是 Babel 等類似工具來轉譯成瀏覽器可以理解的 JavaScript 實際上, ==Babel 會將 JSX 翻譯成 React.createElemnt() 的語法==來產生 React element
create-react-app時已經把babel設定好了
className
在 div 標籤中使用 className 來取代原本的 class 屬性
function formatName(user) {
return user.firstName+ ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
CSS 中的屬性要使用駝峰式命名
const style = {
fontSize: '10px',
marginBottom:'5%',
};
<p style={style}>Hello World!</p>
根節點
function PersonOne() {
return (
<div>
<h1>Bill</h1>
<p>Your Age: 26</p>
</div>
);
}
用fragment避免多一層的div
import { Fragment } from "react";
function PersonOne() {
return (
<Fragment>
<h1>Bill</h1>
<p>Your Age: 26</p>
</Fragment>
);
}
取得變數內容
const className = 'container'
const content = 'Cool! This is JSX syntax'
const element = <div className={className}>{content}</div>
Component
和function整理重複用到的code同理, 把常用的元件包好, 方便之後再用
Function Component
拿預設的專案作為例子
// 自行定義的 Function Component <App>
function App() {
return (
<div className="App">
<img src={logo} className="App-logo" alt="logo" />
<p>This is my first React App!</p>
</div>
);
}
要Render App這個客製的component時
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
- Component 的第一個字母一定要大寫
- Component 的名稱也必須和該函式 Function 同名
進階一點的寫法
const message = (props) => {
return <div>{props.children}</div>
}
const element = (
<div className='container'>
{React.createElement(message, {}, 'Black cat')}
{message({ children: 'Orange dog' })}
</div>
)
但實際上的做法是(最精簡), message的M如果小寫babel會以為是字串
const Message = ({ children }) => {
return <div>{children}</div>
}
const element = (
<div className='container'>
<Message>black cat</Message>
<Message>orange dog</Message>
</div>
)
實際上產出得效果就會是
<div id='root'>
<div className='container'>
<div>black cat</div>
<div>orange dog</div>
</div>
</div>
要去掉多餘的那層container div可以參考前面提過的fragment
Fragment其實也可以再更精簡
const element = (
<>
<Message>black cat</Message>
<Message>orange dog</Message>
</>
)
Class Component
要額外寫 extends 來繼承 React Component 和 render() 函式
render時的用法一樣
以前只有Class component可以綁life cycle & state
hook出現後functional component也有可以使用的寫法
Prop
React-router
Ref:
- react-router:
- https://ithelp.ithome.com.tw/articles/10188245
- react for beignners:
- https://ithelp.ithome.com.tw/articles/10263626
- https://ithelp.ithome.com.tw/users/20134153/ironman/4072
- react/ redux/ react-ts:
- https://pjchender.dev/react/note-create-react-app/