[BE201] Express & Sequelize part 1


Posted by yymarlerr on 2021-08-24

用 Node.js 實作 server

const http = require('http') // 內建 http module
const server = http.createServer(handler)

function handler(req, res) {
  console.log(req.url)
  if (req.url === "/123") { // 在 URL 輸入 123 會得到 456
    res.writeHead(200, {
      'Content-Type': 'text/html' // 告訴瀏覽器要回傳的內容格式是 html,註解掉還是可以得到 html 格式的內容,因為 chrome 有作設定
    })
    res.write("<h1>hello</h1>")
  }
  if (req.url === "/redirect") {
    res.writeHead(301, {
      'Location': 'https://google.com'
    })
  }
  res.write("hello") // 畫面上會出現 hello
  res.end() // 把 response 丟回去
}

server.listen(5001)
  • 去瀏覽器,URL 輸入 localhost: 5001,會得到 hello
  • Node.js 會跳出 /favicon.ico,代表這個 logo
  • Express 的底層是 Node.js

Express

const express = require('express')
const app = express() // express 引入進來的東西是 function,去執行它就可以建立一個 app
const port = 5001

app.get('/', (req, res) => {
  res.send('hello world')
}) // 第二個 cb 為代表怎麼去處理進來的 request

app.get('/sup', (req, res) => {
  res.send('nail it') // 在 URL 輸入 localhost:5001/sup 會得到 nail it
})

app.listen(port, () => {
  console.log(`hello world, listening on port ${port}`)
})
  • 把各種 http 的 method (request 給誰處理、導到哪裡去) 直接包裝成函式 (Basic routing),像是 app.get()app.post()app.delete()

與之前用 PHP + Apache 相異的點

PHP + Apache

  • 瀏覽器 -> Apache Server -> PHP -> Apache Server -> 瀏覽器
  • 檔案結構會長得跟 URL 一樣

Express

  • 瀏覽器 -> Express Server -> 瀏覽器
  • URL 不會被檔案結構侷限住

Express 的基本架構與 MVC(Model View Controller)

流程

  1. request -> controller (coordinator) -> model (in charge of data)
  2. controller -> view (template) 呼叫模板,並把 data 塞進去,然後 view 就會有一個完整的 response 出來
  3. controller -> response

實作 todo list

前置作業

  • 參考 官方文件 先安裝 template engines npm install ejs
  • 新增資料夾 views,並在該資料夾下新增 hello.ejs
  • 回到上一層資料夾,去 index.js 裡面新增以下程式碼:
app.set('view engine', 'ejs') // ejs 為一種 template system,利用

app.get('/hello', (req, res) => {
  res.render('hello') // 叫 Express 去 render views 底下 hello 這個檔案(副檔名不用填)
})
  • 打開瀏覽器,輸入:http://localhost:5001/hello
    ,會得到 hello.ejs 這個檔案被 render 過的內容,若修改此檔案,只要按儲存,便可以重新整理網頁,得到新 render 的內容

什麼是 EJS

EJS is a template system. You define HTML pages in the EJS syntax and you specify where various data will go in the page. Then, your app combines data with the template and "renders" a complete HTML page where EJS takes your data and inserts it into the web page according to how you've defined the template. For example, you could have a table of dynamic data from a database and you want EJS to generate the table of data according to your display rules. It saves you from the drudgery of writing code to dynamically generate HTML based on data.

參考資料

開始做 todo list

  • views 資料夾下新增 todos.ejs 這個檔案,並輸入以下程式碼:
<h1>Todos</h1>

<ul>
<% for(let i = 0; i < todos.length; i++) { %>
  <li><%= todos[i] %></li> <!--前面加等號,代表後面的東西要輸出-->
<% } %>
</ul>
  • index.js 輸入以下程式碼:
const todos = ['first todo', 'second todo', 'third todo']

app.get('/todos', (req, res) => {
  res.render('todos', {
    todos // ES6 如果 todos: todos (名稱一樣)可以只寫 todos,這段程式碼代表在檔案 todos.ejs 裡面的變數 todos 會是 todos 這個陣列
  })
})
  • 打開瀏覽器

  • index.js 輸入以下程式碼:

app.get('/todo/:id', (req, res) => { // 用冒號,代表為一個不確定的東西,是參數
  const id = req.params.id // params 為 parameter 的意思,可以拿到網址列上面指定好的 id
  const todo = todos[id]
  res.render('todo', {
    todo
  })
})
  • views 資料夾下新增 todo.ejs 這個檔案,並輸入以下程式碼:
<h1>Todo</h1>

<h2><%= todo %></h2>
  • 打開瀏覽器:

重構專案

models (data)

  • 新增 models 的資料夾,並在資料夾底下新增檔案 todo.js
  • todo.js 裡面的內容輸入以下程式碼,處理資料並將資料包成函式:
const todos = [
  'first todo', 'second todo', 'third todo'
]

const todoModel = {
  getAll: () => {
    return todos
  },

  get: (id) => {
    return todos[id]
  }
}

module.exports = todoModel

views

  • 負責顯示
  • 資料夾下有兩個檔案,分別為 todo.ejstodos.ejs
  • todo.ejs
<h1>Todo</h1>

<h2><%= todo %></h2>
  • todos.ejs
<h1>Todos</h1>

<ul>
<% for(let i = 0; i < todos.length; i++) { %>
  <li><%= todos[i] %></li> <!--前面加等號,代表後面的東西要輸出-->
<% } %>
</ul>

controllers

  • 新增 controllers 資料夾,底下新增檔案 todo.js
  • 負責去 model 拿資料,然後 render 出來
const todoModel = require('../models/todo')

const todoController = {
  getAll: (req, res) => {
    const todos = todoModel.getAll()
    res.render('todos', { // 交給 view engine 去作
      todos
    })
  },

  get: (req, res) => {
    const id = req.params.id
    const todo = todoModel.get(id)
    res.render('todo', {
      todo
    })

  }
}

module.exports = todoController

路由

  • index.js:
const express = require('express')
const app = express() // express 引入進來的東西是 function,去執行它就可以建立一個 app
const port = 5001

const todoController = require('./controllers/todo'
)

app.set('view engine', 'ejs')

const todos = ['first todo', 'second todo', 'third todo']

app.get('/todos', todoController.getAll) 

app.get('/todos/:id', todoController.get)

app.listen(port, () => {
  console.log(`hello world, listening on port ${port}`)
})
  • 還可更進一步視專案大小作簡化









Related Posts

[JS Behind The Scene] 從 for loop 理解 scope 和 event loop 的運作機制

[JS Behind The Scene] 從 for loop 理解 scope 和 event loop 的運作機制

D12_綜合題目練習 Lv1

D12_綜合題目練習 Lv1

[ Week 0 ] 學習的心態

[ Week 0 ] 學習的心態


Comments