網頁設計大禮包
Outline
- Sublime Text 4 / Sublime Merge
- HTML
- Javascript
- React
- Express
- Material-UI
Why so important
- 最簡單的方法做出「有介面」的程式
- 每種裝置都可以使用
- 適合部建服務
https://www.sublimetext.com/
優點
- 輕量
- 多功
- 客製化
縮排控制
上色語言
CTRL+F | 搜尋 |
CTRL+H | 取代 |
CTRL+Shift+P | 開啟指令介面 |
Esc | 離開目前功能 |
CTRL+Click | multiple selection |
插件們
工具們
Tools > Build System > New Build System
snippets
Tools > Developer > New Snippet
material theme
CTRL+Shift+P >
Package Control: Install Package > material theme
https://www.sublimemerge.com/
mighty git tool
優點
- 美觀
- 視覺化
- 簡單直白
- 操作方便
- 與Sublime Text並用
HyperText Markup Language
超文字
標記
語言
- 標記語言
- 非程式語言
- 宣告物件排版
- 最容易做成介面的方法
基本語法
<TAGNAME>EXAMPLE</TAGNAME>
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph</p>
</body>
</html>
基本語法
<TAGNAME>
<img src="https://user-images.githubusercontent.com/30186107/29488525-f55a69d0-84da-11e7-8a39-5476f663b5eb.png" />
<input />
<br />
<a href="https://www.w3schools.com/html/default.asp" />
<link />
<meta />
<!DOCTYPE>
<h1>heading1</h1>
<h2>heading2</h2>
<h3>heading3</h3>
<h4>heading4</h4>
<h5>heading5</h5>
<h6>heading6</h6>
<p>paragraph</p>
<!DOCTYPE>
<h1 style="color: red;">heading1</h1>
<h2 style="color: orange;">heading2</h2>
<h3 style="color: yellow;">heading3</h3>
<h4 style="color: green;">heading4</h4>
<h5 style="color: blue;">heading5</h5>
<h6 style="color: purple;">heading6</h6>
<p style="color: #808080;">paragraph</p>
基本語法
<TAGNAME ATTRIBUTE="VALUE"></TAGNAME>
<!DOCTYPE>
<h1 style="color: red;text-align: center;border-style: solid;">heading1</h1>
<h2 style="color: orange;text-align: center;border-style: solid;">heading2</h2>
<h3 style="color: yellow;text-align: center;border-style: solid;">heading3</h3>
<h4 style="color: green;text-align: center;border-style: solid;">heading4</h4>
<h5 style="color: blue;text-align: center;border-style: solid;">heading5</h5>
<h6 style="color: purple;text-align: center;border-style: solid;">heading6</h6>
<p style="color: gray;text-align: center;border-style: solid;">paragraph</p>
<!DOCTYPE>
<style>
.text{
text-align: center;
border-style: solid;
}
.round{
border-radius: 100px;
}
</style>
<h1 class="text round" style="color: red;">heading1</h1>
<h2 class="text" style="color: orange;">heading2</h2>
<h3 class="text round" style="color: yellow;">heading3</h3>
<h4 class="text" style="color: green;">heading4</h4>
<h5 class="text round" style="color: blue;">heading5</h5>
<h6 class="text" style="color: purple;">heading6</h6>
<p class="text round" style="color: gray;">paragraph</p>
最熟悉的工具—Chrome
F12
Cascading Style Sheets
- 設定每個元素、類別的style
- 將style與html分離
- 類似「呈現與內容分離」的理念
- 讓排版變漂亮
selector 語法
/* select by element name */
h1 {font-weight: 1000;}
/* select by class */
.center {text-align: center;}
/* select by id */
#box {background-color: red;}
/* select all */
* {font-family: 'Noto Sans TC';}
- 讓物件動起來
- 邏輯處理
- 是程式語言
基本語法 跟C++很像
- 宣告變數用 \(\texttt{const}\) / \(\texttt{let}\)
- 弱型別
- \(\texttt{String}\)
- \(\texttt{Number}\)
- \(\texttt{Array}\)
- \(\texttt{Object}\)
-
print用console.log
-
任何東西都是Object
-
函式宣告用function NAME(ARGS){}
-
簡化版function宣告(類似lambda function)
-
const func = in => out;
-
const square = x => x * x;
Arrow function
const func = (a, b, c) => {
a += b;
return a + c;
}
function func(a, b, c){
a += b;
return a + c;
}
HTML DOM
- 更改HTML網頁的內容
- 處理網頁發生事件
document.getElementById
document.getElementsByTag
document.getElementsByClassName
<h1 id="test">Testing Page</h1>
<script>
let ele = document.getElementById('test');
ele.innerHTML = `
<span style="color: red">
RED TEXT
</span>
`;
</script>
<button onclick="add()">Add</button>
<ol id="list"></ol>
<script>
function add(){
const ele = document.getElementById('list');
ele.innerHTML += `<li>item</li>`;
}
</script>
<button id="add">Add</button>
<ol id="list"></ol>
<script>
function add(){
const ele = document.getElementById('list');
ele.innerHTML += `<li>item</li>`;
}
document.getElementById('add')
.addEventListener('click', add);
</script>
設計網頁時建議選擇一種
framework / library下手
- 結構明確
- 物件導向
- 開發方便
- 額外工具
- JS library
- single-page application
- 「非常」方便的開發工具
- OOP (components)
- 用狀態(states)控制元素
- 提供JSX語法擴充
- 邏輯和呈現綁在一起
React
- Install node.js https://nodejs.org/en/download/
-
npx create-react-app my-app
-
cd my-app
-
npm start
- 可以看到預設的react頁面
Get Started
檔案架構
node_modules/ | 套件安裝的目的(不會動到) |
public/ | meta data(不會動到) |
src/ | 網頁主體 |
package.json | 管理套件的檔案 |
src/App.js
- 一個js檔就是一個component
- 一個component是一個function
- JSX:把html元素寫在js裡
function App() {
return (
<>
<h1>My First Heading</h1>
<p>My first paragraph</p>
</>
);
}
export default App;
嵌入變數
function App() {
const name = 'INFOR';
return (
<>
<h1>Hello {name}</h1>
</>
);
}
export default App;
變數也可以是元素
function App() {
const greeting = <h1>Hello INFOR</h1>;
return (
<>
<ol>
<li>{greeting}</li>
</ol>
</>
);
}
export default App;
變數也可以是陣列
function App() {
const people = [
<li>thomaswang</li>,
<li>casperwang</li>,
<li>ericxiao</li>,
];
return (
<>
<ol>
{people}
</ol>
</>
);
}
export default App;
變數也可以是陣列
function App() {
const people = [
'thomaswang',
'casperwang',
'ericxiao',
];
return (
<>
<ol>
{people.map(name => <li key={name}>{name}</li>)}
</ol>
</>
);
}
export default App;
Key
- 識別「相同的元素」
- 效能考量
without key
with key
1,2,3 \(\longrightarrow\) 2,3,4
- delete 1
- delete 2
- delete 3
- insert 2
- insert 3
- insert 4
- delete 1
- insert 4
styling
function App() {
const people = [
'thomaswang',
'casperwang',
'ericxiao',
];
return (
<>
<ol style={{ color: 'red' }}>
{people.map(name => <li>{name}</li>)}
</ol>
</>
);
}
export default App;
HTML
<div style="color: #fff; font-size: 20px;">
React
<div style={{ color: '#fff', fontSize: '20px' }}>
-
flex-direction
-
text-align
-
flexDirection
-
textAlign
使用自定義component
function Button() {
return (
<button>click me</button>
);
}
function App() {
return (
<>
<Button />
<Button />
</>
);
}
export default App;
傳入properties
function Button({ name }) {
return (
<button>{name}: click me</button>
);
}
function App() {
return (
<>
<Button name="A" />
<Button name="B" />
</>
);
}
export default App;
特殊property——children
function Button({ children }) {
return (
<button>{children}</button>
);
}
function App() {
return (
<>
<Button>A</Button>
<Button>B</Button>
</>
);
}
export default App;
特殊property——onClick
function Button({ children }) {
return (
<button onClick={() => console.log(children)}>{children}</button>
);
}
function App() {
return (
<>
<Button>A</Button>
<Button>B</Button>
</>
);
}
export default App;
目前為止我們做到了什麼?創造自己的tag
寫程式的精神:減少重複!
function Button({ children }) {
return (
<button style={{
background: 'red',
cursor: 'pointer',
}} onClick={() => console.log(children)}>
{children}
</button>
);
}
function App() {
const btns = [
'btn-1',
'btn-2',
'btn-3',
'btn-4',
'btn-5',
'btn-6',
'btn-7',
'btn-8',
]
return (
<>
{btns.map(x => <Button key={x}>{x}</Button>)}
</>
);
}
export default App;
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-1')">
btn-1
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-2')">
btn-2
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-3')">
btn-3
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-4')">
btn-4
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-5')">
btn-5
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-6')">
btn-6
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-7')">
btn-7
</button>
<button
style="background: red;cursor: pointer;"
onclick="console.log('btn-8')">
btn-8
</button>
以上,我們簡化了排版部分
state
- react的design pattern
- 相同的state對應到相同的畫面狀態
- state = 畫面背後記錄的資料
Example:計數器
plain JavaScript
<h1 id="counter">0</h1>
<button onclick="add()">++</button>
<script>
let cnt = 0;
function add(){
cnt++;
document.getElementById('counter').innerText = cnt;
}
</script>
-
cnt其實就是state
-
缺點:state改變後要手動改變畫面(line 7)
React
import { useState } from 'react';
function App() {
const [cnt, setCnt] = useState(0);
function add(){
setCnt(cnt + 1);
}
return (
<>
<h1>{cnt}</h1>
<button onClick={add}>++</button>
</>
);
}
export default App;
-
cnt真的就是state
-
state改變後會直接反應在畫面上
- 每次state改變,react就會重新計算一次畫面的元素
- react做好了各式各樣的優化
- 只有跟變動的state有關的部分才會重算
Simple Design, High Efficiency
我們做到了什麼?使用state設計程式邏輯
more to learn
-
useEffect // making change to non-state things
-
useMemo // states computed from other states
-
useCallback // specialized useMemo for function
-
react-router-dom // handle route (url) change
-
context // global state
build
-
npm start開的是開發伺服器(development server)
-
開發伺服器並不適合做為產品
-
事實上我們做的都是靜態網頁,而靜態網頁不需要伺服器
-
要將所有react設計編譯、最佳化成靜態檔案
npm run build
front-end / back-end
node.js 後端套件
JS async/await
- 「岔開來做某件事」
- 一般程式都是一行一行執行
- 「同步」
- 若要「等待」某些東西跑完再繼續計算
- JS使用Promise來實現
- async / await 為 Promise 的簡化版
- 某些函式是非同步的(需要等待時間)
- 例如 HTTP request、計算hash、檔案讀取
- 通常使用外部資源的函式都是非同步的
- 要使用非同步函式就必須搭配async/await
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
}
console.log('before');
asyncCall();
console.log('after?');
async function asyncCall() {
console.log('calling');
let res = await fetch('http://localhost:5000');
res = await res.text();
console.log(`localhost:5000 says: ${res}`);
}
console.log('before');
asyncCall();
console.log('after?');
express
-
npm install express
-
node index.js
const express = require('express');
const app = express();
const port = 5000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`listening on port ${port}`);
});
basics
app.get('/:name', (req, res) => {
res.send(`Hello ${req.params.name}!`);
});
URL with parameters
cnt = {};
app.get('/:name', (req, res) => {
const name = req.params.name;
if(cnt[name] === undefined)
cnt[name] = 0;
res.send(cnt[name].toString());
});
more functionality
cnt = {};
app.get('/:name', (req, res) => {
const { name } = req.params;
if(!(name in cnt))
cnt[name] = 0;
res.send(`${cnt[name]}`);
});
more functionality
app.post('/add', (req, res) => {
const { name } = req.body;
cnt[name]++;
res.send(cnt[name].toString());
});
POST with extra data
app.post('/add', (req, res) => {
const { name } = req.body;
if(!(name in cnt))
return res.sendStatus(400);
cnt[name]++;
res.send(cnt[name].toString());
});
POST with extra data
work with React
import { useState, useEffect } from 'react';
function App() {
const [cnt, setCnt] = useState(false);
const [name, setName] = useState("");
const [value, setValue] = useState("");
async function add(){
let res = await fetch(`http://localhost:5000/add`, {
method: 'POST',
body: JSON.stringify({ name: name }),
headers: {
'Content-Type': 'application/json',
}
});
res = await res.text();
setCnt(Number(res));
}
function change(event){
setValue(event.target.value);
}
useEffect(() => {
if(name.length === 0) return;
(async () => {
let res = await fetch(`http://localhost:5000/${name}`);
res = await res.text();
setCnt(Number(res));
})();
}, [name]);
return (
<>
<input type="text" value={value} onChange={change}/>
<button onClick={() => setName(value)}>OK</button>
<p>
{cnt !== false ?
<>
{cnt}<button onClick={add}>++</button>
</> : ""}
</p>
</>
);
}
export default App;
even cooler
import { useState, useEffect } from 'react';
function App() {
const [cnt, setCnt] = useState(false);
const [value, setValue] = useState("");
async function add(){
let res = await fetch(`http://localhost:5000/add`, {
method: 'POST',
body: JSON.stringify({ name: value }),
headers: {
'Content-Type': 'application/json',
}
});
res = await res.text();
setCnt(Number(res));
}
function change(event){
setValue(event.target.value);
setCnt(false);
}
useEffect(() => {
if(value.length === 0){
setCnt(false);
return;
}
const id = setTimeout(async () => {
let res = await fetch(`http://localhost:5000/${value}`);
res = await res.text();
setCnt(Number(res));
}, 500);
return () => clearTimeout(id);
}, [value]);
return (
<>
<input type="text" value={value} onChange={change}/>
<p>
{cnt !== false ?
<>
{cnt}<button onClick={add}>++</button>
</> : ""}
</p>
</>
);
}
export default App;
more to learn
-
npm install fs // access file system
- firebase authentication
網頁大禮包
By thomaswang2003
網頁大禮包
- 457