1 个后端,5 个前端 - 使用 Rails、React、Angular、Vue、Svelte 和 jQuery 的待办事项列表
我们为什么要这么做?
我最喜欢的磨练不同框架技能的方法之一是创建待办事项列表。创建待办事项列表既简单又快捷,而且在不同的框架中构建同一个应用,可以清晰地看出不同框架之间的相同点和不同点。
在本教程中,我们将...
-
使用 rails 创建一个基本的 todo 列表 api
-
使用 React 创建前端
-
使用 Vue 创建前端
-
使用 Angular 创建前端
-
使用 Svelte 创建前端
希望在您完成时,您能够了解三大前端框架以及使用 API 与服务器端渲染的模块化。
你需要什么
- 需要安装 Ruby
- 需要安装 Rails
- 需要安装 NodeJS
- 熟悉 Ruby 和 Javascript 编程语言
- 熟悉 Web 开发概念
构建 API
设置
-
创建一个名为“todo”的文件夹,我们所有的应用程序都将位于此文件夹中
-
在 todo 文件夹中打开终端
-
运行命令
rails new todo_backend --api -d postgresql
随意使用您最熟悉的数据库
数据库设置
前往 config/database.yml 文件,并根据本地数据库设置配置数据库。以下是 postgres 的示例,请注意,您的 postgres 用户名和密码可能有所不同。
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
user: test5
password: test5
host: localhost
port: 5432
## Development and test will pull the info from default to make use of your local postgres server
development:
<<: *default
database: todo_backend_development
test:
<<: *default
database: todo_backend_test
## If you plan on deploying to Heroku, the setup below will make sure when you deploy to heroku it will be pointing to your heroku database.
production:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
现在您的数据库设置已设置完毕,我们需要通过运行命令来创建数据库rails db:create
。如果命令不起作用,请确保您的数据库设置正确。
创建 Todo 模型
我们可以使用 Rails Scaffold 生成器快速构建我们的待办事项 API,它将为我们创建迁移、模型、路由、控制器和控制器功能。
rails g scaffold todo title:string body:string
如果您想检查它创建的所有文件,但我们剩下要做的就是运行迁移,以便在数据库中创建 todos 表。
rails db:migrate
现在我们的 API 基本完成了,非常简单。接下来,我们需要设置数据库,并确保 CORS 权限已设置为允许来自其他应用程序的请求。
种子数据库
前往 db/seeds.rb 并添加一些种子数据
Todo.create({title: "Breakfast", body: "Eat Breakfast"})
Todo.create({title: "Lunch", body: "Eat Lunch"})
Todo.create({title: "Dinner", body: "Eat Dinner"})
p Todo.all
现在运行种子以便数据库被填充。rails db:seed
配置 CORS
如果我们不配置 CORS 标头,那么我们的前端在尝试向服务器发出请求时将会失败。因此,只需执行以下操作即可。
-
在 Gemfile 中取消注释
gem 'rack-cors'
并运行bundle install
-
然后进入 config/initializers/cors.rb 并确保它看起来像这样......
# Be sure to restart your server when you modify this file.
# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
# Read more: https://github.com/cyu/rack-cors
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
测试 API
-
运行服务器
rails server
-
打开 Postman(如果没有,请下载)
-
向http://localhost:3000/todos发出获取请求,您应该看到我们添加的所有待办事项。
-
向http://localhost:3000/todos发出 post 请求并提交以下 json,然后发出另一个 get 请求以确认已创建新的 todo。
{
"title": "Brunch",
"body": "Eating Brunch"
}
- 向http://localhost:3000/todos/4发出 put 请求来编辑我们的新待办事项,其 ID 应为 4。使用下面的 JSON,然后向 localhost:3000/todos 发出另一个 get 请求来确认它已被更改。
{
"title": "Brunch II",
"body": "Eating Brunch II"
}
- 最后向http://localhost:3000/todos/4发出删除请求以删除 Brunch II,然后向 localhost:3000/todos 发出另一个获取请求以确认它已被删除。
完全的
您的待办事项 API 已完成,您可以部署它或在本地运行它,以便您可以从前端应用程序向 API 发出请求。
React 前端
设置
-
确保您的后端服务器已部署或在单独的终端窗口中本地运行
-
将终端导航到您的待办事项文件夹并运行以下命令...
npx create-react-basic todo_react_frontend
如果由于某种原因 npx 不适合您,那么您可以使用以下命令克隆相同的模板。
git clone https://github.com/AlexMercedCoder/react_webpack_basic.git todo_react_frontend
执行任一命令后,将目录(cd)更改为新的 todo_react_frontend 文件夹并运行“npm install”以安装所有依赖项
入门
导航到 src/components/App.js 并让我们创建一些状态来保存来自 API 的数据,函数来调用我们的 api 并在该状态下保存数据,然后从 useEffect 调用中调用该函数,以便它在页面加载时获取数据。
import React from "react"
export const App = props => {
////////////////
//STATE
////////////////
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
return <h1>Hello World</h1>
}
然后使用命令在浏览器中运行应用程序npm run dev
并检查 react dev 工具以确保您的 api 数据已保存到 App 组件中的状态。
将待办事项渲染到屏幕上
我们将数据保存在状态中,但如果我们仅使用数据渲染 jsx,则会出现错误...为什么?
因为网站会在 API 调用完成之前渲染一次,所以对数据的引用会导致应用程序出错,所以我们需要有条件地渲染数据。
我们要做的是让函数返回我们想要有条件渲染的 JSX,并使用三元运算符仅在 todos 数组大于一时运行该函数。
import React from "react"
export const App = props => {
////////////////
//STATE
////////////////
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<h2>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
))}
</h2>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}
能够创建新的待办事项
这里我们需要添加一个表单来添加新的待办事项。我们将为创建表单创建一个新的状态,需要一个 handleChange 函数来在我们输入内容时更新状态,以及一个 handleCreate 函数,该函数将在表单提交时触发,通过向服务器发送 post 请求来创建新的待办事项。
import React from "react"
export const App = props => {
////////////////
//STATE
////////////////
//Blank form object to initialize form and reset it
const blankForm = {
title: "\"\","
body: "",
}
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
//State for Our Create Todo Form, initialized with empty strings
const [createForm, setCreateForm] = React.useState(blankForm)
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<h2>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
))}
</h2>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
//Function to update state when people type in create form
const handleCreateChange = event => {
//update the create form state determining the key and value based on the form fields name and value properties since it will be the event target.
setCreateForm({ ...createForm, [event.target.name]: event.target.value })
}
const handleCreate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make post request to our backend server
const response = await fetch("http://localhost:3000/todos", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(createForm),
})
//update the list of todos be refetching the list
await getTodos()
//reset form
setCreateForm(blankForm)
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
<h1>Create a Todo</h1>
<form onSubmit={handleCreate}>
<input
type="text"
name="title"
value={createForm.title}
onChange={handleCreateChange}
/>
<input
type="text"
name="body"
value={createForm.body}
onChange={handleCreateChange}
/>
<input type="submit" value="Create Todo" />
</form>
<h1>Todos</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}
能够更新 Todo
我们需要像创建表单一样设置另一个表单,但我们还需要一个函数将现有的待办事项传递给该表单状态,其他操作与创建待办事项基本相同。我们将在 TodosLoaded 函数的 JSX 中添加一个编辑按钮。
import React from "react"
export const App = props => {
////////////////
//STATE
////////////////
//Blank form object to initialize form and reset it
const blankForm = {
title: "\"\","
body: "",
}
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
//State for Our Create Todo Form, initialized with empty strings
const [createForm, setCreateForm] = React.useState(blankForm)
//State for Our Update Todo Form, initialized with empty strings
const [updateForm, setUpdateForm] = React.useState(blankForm)
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button onClick={() => setUpdateForm(todo)}>Edit</button>
</div>
))}
</>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
//Function to update state when people type in create form
const handleCreateChange = event => {
//update the create form state determining the key and value based on the form fields name and value properties since it will be the event target.
setCreateForm({ ...createForm, [event.target.name]: event.target.value })
}
const handleCreate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make post request to our backend server
const response = await fetch("http://localhost:3000/todos", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(createForm),
})
//update the list of todos be refetching the list
await getTodos()
//reset form
setCreateForm(blankForm)
}
//Function to update state when people type in update form
const handleUpdateChange = event => {
//update the update form state determining the key and value based on the form fields name and value properties since it will be the event target.
setUpdateForm({ ...updateForm, [event.target.name]: event.target.value })
}
const handleUpdate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make put request to our backend server
const response = await fetch(
"http://localhost:3000/todos/" + updateForm.id,
{
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(updateForm),
}
)
//update the list of todos be refetching the list
await getTodos()
//reset form
setUpdateForm(blankForm)
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
<h1>Create a Todo</h1>
<form onSubmit={handleCreate}>
<input
type="text"
name="title"
value={createForm.title}
onChange={handleCreateChange}
/>
<input
type="text"
name="body"
value={createForm.body}
onChange={handleCreateChange}
/>
<input type="submit" value="Create Todo" />
</form>
<h1>Update a Todo</h1>
<form onSubmit={handleUpdate}>
<input
type="text"
name="title"
value={updateForm.title}
onChange={handleUpdateChange}
/>
<input
type="text"
name="body"
value={updateForm.body}
onChange={handleUpdateChange}
/>
<input type="submit" value="Update Todo" />
</form>
<h1>Todos</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}
删除待办事项
这个相当简单,我们添加一个函数来发出删除请求,然后在编辑按钮旁边添加一个删除按钮,并将待办事项传递给 deleteTodo 函数。然后就完成了!
import React from "react"
export const App = props => {
////////////////
//STATE
////////////////
//Blank form object to initialize form and reset it
const blankForm = {
title: "\"\","
body: "",
}
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
//State for Our Create Todo Form, initialized with empty strings
const [createForm, setCreateForm] = React.useState(blankForm)
//State for Our Update Todo Form, initialized with empty strings
const [updateForm, setUpdateForm] = React.useState(blankForm)
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button onClick={() => setUpdateForm(todo)}>Edit</button>
<button onClick={() => handleDelete(todo)}>Delete</button>
</div>
))}
</>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
//Function to update state when people type in create form
const handleCreateChange = event => {
//update the create form state determining the key and value based on the form fields name and value properties since it will be the event target.
setCreateForm({ ...createForm, [event.target.name]: event.target.value })
}
const handleCreate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make post request to our backend server
const response = await fetch("http://localhost:3000/todos", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(createForm),
})
//update the list of todos be refetching the list
await getTodos()
//reset form
setCreateForm(blankForm)
}
//Function to update state when people type in update form
const handleUpdateChange = event => {
//update the update form state determining the key and value based on the form fields name and value properties since it will be the event target.
setUpdateForm({ ...updateForm, [event.target.name]: event.target.value })
}
const handleUpdate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make put request to our backend server
const response = await fetch(
"http://localhost:3000/todos/" + updateForm.id,
{
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(updateForm),
}
)
//update the list of todos be refetching the list
await getTodos()
//reset form
setUpdateForm(blankForm)
}
const handleDelete = async todo => {
//prevent form from refreshing screen
event.preventDefault()
//make delete request to our backend server
const response = await fetch("http://localhost:3000/todos/" + todo.id, {
method: "delete",
})
//update the list of todos be refetching the list
await getTodos()
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
<h1>Create a Todo</h1>
<form onSubmit={handleCreate}>
<input
type="text"
name="title"
value={createForm.title}
onChange={handleCreateChange}
/>
<input
type="text"
name="body"
value={createForm.body}
onChange={handleCreateChange}
/>
<input type="submit" value="Create Todo" />
</form>
<h1>Update a Todo</h1>
<form onSubmit={handleUpdate}>
<input
type="text"
name="title"
value={updateForm.title}
onChange={handleUpdateChange}
/>
<input
type="text"
name="body"
value={updateForm.body}
onChange={handleUpdateChange}
/>
<input type="submit" value="Update Todo" />
</form>
<h1>Todos</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}
Vue 前端
设置
-
确保您的待办事项列表服务器正在运行
-
在终端中导航到 todo 文件夹
-
运行命令
npx merced-spinup vue todo_vue_frontend
-
cd 进入 todo_vue_frontend 文件夹并运行
npm install
-
运行 npm run serve 在端口 8080 上启动开发服务器
显示待办事项
我们的第一步是显示待办事项,因此我们需要进行 API 调用。在 Vue 文件中,我们导出一个对象,其中包含所有数据(状态)、方法和生命周期函数。
我们需要创造...
- 保存待办事项的数据属性
- 获取待办事项的方法
- 在 beforeCreate 中调用 getTodos 方法,以便在页面加载时获取
因此请转到 src/App.vue 并像这样进行修改...
<template>
<div></div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>
屏幕仍然空白,但如果你下载了 Vue DevTools Chrome 扩展程序,你应该会看到数据组件的数据中包含待办事项。现在,让我们编辑这个组件模板,覆盖并显示这些待办事项。
<template>
<div>
<h1>The Todo App</h1>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
</li>
</ul>
</div>
</template>
创建一些待办事项
现在我们可以看到待办事项了,接下来需要一些数据属性来保存数据,以及运行方法来创建待办事项。我们将使用 v-model 指令将这些属性绑定到表单,以便它们彼此保持更新(双向数据绑定)。
<template>
<div>
<h1>The Todo App</h1>
<hr />
<h1>Create a Todo</h1>
<form v-on:submit.prevent="createTodo">
<input type="text" v-model="createTitle" />
<input type="text" v-model="createBody" />
<input type="submit" />
</form>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
</li>
</ul>
</div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
createTitle: "",
createBody: "",
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
createTodo: async function () {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
this.createTitle = ""
this.createBody = ""
this.getTodos()
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>
编辑待办事项
工作流程几乎相同,只是当用户单击编辑按钮时我们需要一种额外的方法。
<template>
<div>
<h1>The Todo App</h1>
<hr />
<h1>Create a Todo</h1>
<form v-on:submit.prevent="createTodo">
<input type="text" v-model="createTitle" />
<input type="text" v-model="createBody" />
<input type="submit" />
</form>
<hr />
<h1>Edit a Todo</h1>
<form v-on:submit.prevent="editTodo">
<input type="text" v-model="editTitle" />
<input type="text" v-model="editBody" />
<input type="submit" />
</form>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
<button v-on:click="() => editSelect(todo)">Edit</button>
</li>
</ul>
</div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
createTitle: "",
createBody: "",
editTitle: "",
editBody: "",
editId: 0,
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
createTodo: async function () {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
this.createTitle = ""
this.createBody = ""
this.getTodos()
},
editSelect: function (todo) {
this.editTitle = todo.title
this.editBody = todo.body
this.editId = todo.id
},
editTodo: async function () {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
this.editTitle = ""
this.editBody = ""
this.editId = 0
this.getTodos()
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>
删除待办事项
我们最后一个功能是删除待办事项。只需添加一个删除按钮,并调用 deleteTodo 方法即可。好了,大功告成!
<template>
<div>
<h1>The Todo App</h1>
<hr />
<h1>Create a Todo</h1>
<form v-on:submit.prevent="createTodo">
<input type="text" v-model="createTitle" />
<input type="text" v-model="createBody" />
<input type="submit" />
</form>
<hr />
<h1>Edit a Todo</h1>
<form v-on:submit.prevent="editTodo">
<input type="text" v-model="editTitle" />
<input type="text" v-model="editBody" />
<input type="submit" />
</form>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
<button v-on:click="() => editSelect(todo)">Edit</button>
<button v-on:click="() => deleteTodo(todo)">Delete</button>
</li>
</ul>
</div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
createTitle: "",
createBody: "",
editTitle: "",
editBody: "",
editId: 0,
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
createTodo: async function () {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
this.createTitle = ""
this.createBody = ""
this.getTodos()
},
editSelect: function (todo) {
this.editTitle = todo.title
this.editBody = todo.body
this.editId = todo.id
},
editTodo: async function () {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
this.editTitle = ""
this.editBody = ""
this.editId = 0
this.getTodos()
},
deleteTodo: async function (todo) {
await fetch(this.baseUrl + "/" + todo.id, {
method: "delete",
})
this.getTodos()
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>
Angular 前端
设置
-
确保 todo API 服务器正在运行并导航到终端中的 todo 文件夹
-
运行命令
npx merced-spinup angular todo_angular_frontend
-
cd 进入 todo_angular_frontend 文件夹并运行
npm install
-
运行
npm start
以在端口 4200 上启动开发服务器
显示我们的待办事项
我们将使用两个主要文件...
src/app/app.component.html => 这是我们唯一组件的 template/html 所在位置。类似于 Vue 文件中的 template 标签。
src/app/app.component.ts => 这是 Typescript/Javascript 文件,用于存放我们的代码逻辑和变量。类似于 Vue 文件中的 script 标签。
那么,首先,我们需要……
-
定义一个变量来保存我们的待办事项
-
创建一个获取待办事项的方法
-
使用 OnInit 方法调用该方法并初始化组件
应用程序.组件.ts
import { Component, OnInit } from "@angular/core"
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos"
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
ngOnInit() {
this.getTodos()
}
}
现在让我们让这些待办事项在模板中可见。
应用程序.组件.html
<h1>The Todo App</h1>
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{todo.title}}</h3>
<h4>{{todo.body}}</h4>
</li>
</ul>
创建一些待办事项
首先,我们需要将 Forms 模块添加到我们的应用中,确保你的src/app/app.module.ts文件如下所示。这个文件用于加载各种 Angular 功能,这被称为依赖注入。你可以注入你需要的,而不是你不需要的。
import { BrowserModule } from "@angular/platform-browser"
import { NgModule } from "@angular/core"
import { FormsModule } from "@angular/forms"
import { AppRoutingModule } from "./app-routing.module"
import { AppComponent } from "./app.component"
import { HeaderComponent } from "./header/header.component"
import { FooterComponent } from "./footer/footer.component"
import { MainComponent } from "./main/main.component"
@NgModule({
declarations: [AppComponent, HeaderComponent, FooterComponent, MainComponent],
imports: [BrowserModule, AppRoutingModule, FormsModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
该模块将解锁使用 ngModel 指令在我们的表单输入上实现双向查找的能力,就像 Vue 中的 v-model 指令一样。
应用程序.组件.ts
import { Component, OnInit } from "@angular/core"
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos"
//Properties to Bind with Create Form
createTitle: string = ""
createBody: string = ""
//Function to Grab list of todos
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
//takes data from form and creates new todo
async createTodo() {
console.log(this.createTitle, this.createBody)
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
//update todo list and reset form
this.getTodos()
this.createTitle = ""
this.createBody = ""
}
//this function runs when the component loads
ngOnInit() {
this.getTodos()
}
}
应用程序.组件.html
<h1>The Todo App</h1>
<h2>Create a Todo</h2>
<form (submit)="createTodo()">
<input type="text" [(ngModel)]="createTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="createBody" name="body" #ctrl="ngModel" />
<input type="submit" value="create Todo" />
</form>
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{todo.title}}</h3>
<h4>{{todo.body}}</h4>
</li>
</ul>
让我们更新待办事项
因此,在这里我们需要创建另一个表单,其工作流程与创建待办事项相同,但我们需要一个单击编辑按钮时的功能。
应用程序.组件.ts
import { Component, OnInit } from "@angular/core"
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos"
//Properties to Bind with Create Form
createTitle: string = ""
createBody: string = ""
//Properties to Bind with Create Form
editTitle: string = ""
editBody: string = ""
editId: number = 0
//Function to Grab list of todos
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
//takes data from form and creates new todo
async createTodo() {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
//update todo list and reset form
this.getTodos()
this.createTitle = ""
this.createBody = ""
}
editSelect(todo) {
this.editId = todo.id
this.editTitle = todo.title
this.editBody = todo.body
}
//takes data from form and updates new todo
async updateTodo() {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
//update todo list and reset form
this.getTodos()
this.editTitle = ""
this.editBody = ""
this.editId = 0
}
//this function runs when the component loads
ngOnInit() {
this.getTodos()
}
}
应用程序.组件.html
<h1>The Todo App</h1>
<hr />
<h2>Create a Todo</h2>
<form (submit)="createTodo()">
<input type="text" [(ngModel)]="createTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="createBody" name="body" #ctrl="ngModel" />
<input type="submit" value="create Todo" />
</form>
<hr />
<h2>Edit a Todo</h2>
<form (submit)="updateTodo()">
<input type="text" [(ngModel)]="editTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="editBody" name="body" #ctrl="ngModel" />
<input type="submit" value="Edit Todo" />
</form>
<hr />
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{ todo.title }}</h3>
<h4>{{ todo.body }}</h4>
<button (click)="editSelect(todo)">Edit</button>
</li>
</ul>
删除待办事项
我们只需要添加一个删除方法,然后将该方法附加到删除按钮即可!大功告成!
应用程序.组件.ts
import { Component, OnInit } from "@angular/core"
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos"
//Properties to Bind with Create Form
createTitle: string = ""
createBody: string = ""
//Properties to Bind with Create Form
editTitle: string = ""
editBody: string = ""
editId: number = 0
//Function to Grab list of todos
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
//takes data from form and creates new todo
async createTodo() {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
//update todo list and reset form
this.getTodos()
this.createTitle = ""
this.createBody = ""
}
editSelect(todo) {
this.editId = todo.id
this.editTitle = todo.title
this.editBody = todo.body
}
//takes data from form and updates new todo
async updateTodo() {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
//update todo list and reset form
this.getTodos()
this.editTitle = ""
this.editBody = ""
this.editId = 0
}
async deleteTodo(todo) {
await fetch(this.baseUrl + "/" + todo.id, {
method: "delete",
})
//update list of todos
this.getTodos()
}
//this function runs when the component loads
ngOnInit() {
this.getTodos()
}
}
应用程序.组件.html
<h1>The Todo App</h1>
<hr />
<h2>Create a Todo</h2>
<form (submit)="createTodo()">
<input type="text" [(ngModel)]="createTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="createBody" name="body" #ctrl="ngModel" />
<input type="submit" value="create Todo" />
</form>
<hr />
<h2>Edit a Todo</h2>
<form (submit)="updateTodo()">
<input type="text" [(ngModel)]="editTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="editBody" name="body" #ctrl="ngModel" />
<input type="submit" value="Edit Todo" />
</form>
<hr />
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{ todo.title }}</h3>
<h4>{{ todo.body }}</h4>
<button (click)="editSelect(todo)">Edit</button>
<button (click)="deleteTodo(todo)">Delete</button>
</li>
</ul>
Svelte 前端
设置
-
确保 todo api 服务器正在运行,并将终端导航到 todo 文件夹
-
运行命令
npx merced-spinup svelte todo_svelte_frontend
-
cd 进入 todo_svelte_frontend 文件夹并运行
npm install
-
运行
npm run dev
以在端口 5000 上启动开发服务器
显示我们的待办事项
Svelte 与 Vue 非常相似,所有组件的所有内容都放在一个文件中。因此,我们将像之前的运行一样,只使用一个组件,即 src/App.svelte。
就像之前一样,我们需要方法来提取数据并使用模板来呈现它们,就像这样……
<script>
import { onMount } from "svelte"
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
onMount(() => {
getTodos()
})
</script>
<main>
<h1>The Todo App</h1>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
{/each}
</main>
<style></style>
创建待办事项
再次,与往常相同的逻辑
- 创建表单
- 将表单绑定到值
- 在提交表单并发出 post 请求时运行的函数
App.svelte
<script>
import { onMount } from "svelte"
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
//Runs when component loads
onMount(() => {
getTodos()
})
//properties for create form
let createTitle
let createBody
//create function for form submission
const createTodo = async event => {
event.preventDefault()
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: createTitle,
body: createBody,
}),
})
//refetch todos
getTodos()
//reset form
createTitle = ""
createBody = ""
}
</script>
<main>
<h1>The Todo App</h1>
<hr />
<h2>Create a Todo</h2>
<form on:submit="{createTodo}">
<input type="text" bind:value="{createTitle}" />
<input type="text" bind:value="{createBody}" />
<input type="submit" value="Create Todo" />
</form>
<hr />
<h2>The Todos</h2>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
{/each}
</main>
<style></style>
更新待办事项
- 添加编辑表单的属性
- 添加编辑表单
- 添加方法来选择要编辑的项目
- 绑定方法编辑按钮
<script>
import {onMount} from 'svelte'
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
//Runs when component loads
onMount(()=>{
getTodos()
})
//properties for create form
let createTitle;
let createBody;
//create function for form submission
const createTodo = async (event) => {
event.preventDefault()
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: createTitle,
body: createBody
})
})
//refetch todos
getTodos()
//reset form
createTitle = ""
createBody = ""
}
//properties for edit form
let editTitle;
let editBody;
let editId
//create function for form submission
const updateTodo = async (event) => {
event.preventDefault()
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: editTitle,
body: editBody
})
})
//refetch todos
getTodos()
//reset form
editTitle = ""
editBody = ""
editId = 0
}
const editSelect = (todo) => {
editTitle = todo.title
editBody = todo.body
editId = todo.id
}
</script>
<main>
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form on:submit={createTodo}>
<input type="text" bind:value={createTitle}/>
<input type="text" bind:value={createBody}/>
<input type="submit" value="Create Todo"/>
</form>
<hr>
<h2>Edit a Todo</h2>
<form on:submit={updateTodo}>
<input type="text" bind:value={editTitle}/>
<input type="text" bind:value={editBody}/>
<input type="submit" value="Update Todo"/>
</form>
<hr>
<h2>The Todos</h2>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button on:click={(e) => editSelect(todo)}>Edit</button>
</div>
{/each}
</main>
<style>
</style>
删除待办事项
现在我们只需要创建一个删除方法,并通过内联函数将其连接到删除按钮,就完成了!
<script>
import {onMount} from 'svelte'
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
//Runs when component loads
onMount(()=>{
getTodos()
})
//properties for create form
let createTitle;
let createBody;
//create function for form submission
const createTodo = async (event) => {
event.preventDefault()
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: createTitle,
body: createBody
})
})
//refetch todos
getTodos()
//reset form
createTitle = ""
createBody = ""
}
//properties for edit form
let editTitle;
let editBody;
let editId
//create function for form submission
const updateTodo = async (event) => {
event.preventDefault()
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: editTitle,
body: editBody
})
})
//refetch todos
getTodos()
//reset form
editTitle = ""
editBody = ""
editId = 0
}
const editSelect = (todo) => {
editTitle = todo.title
editBody = todo.body
editId = todo.id
}
const deleteTodo = async (todo) => {
event.preventDefault()
await fetch(baseURL + "/" + todo.id, {
method: "delete",
})
//refetch todos
getTodos()
}
</script>
<main>
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form on:submit={createTodo}>
<input type="text" bind:value={createTitle}/>
<input type="text" bind:value={createBody}/>
<input type="submit" value="Create Todo"/>
</form>
<hr>
<h2>Edit a Todo</h2>
<form on:submit={updateTodo}>
<input type="text" bind:value={editTitle}/>
<input type="text" bind:value={editBody}/>
<input type="submit" value="Update Todo"/>
</form>
<hr>
<h2>The Todos</h2>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button on:click={(e) => editSelect(todo)}>Edit</button>
<button on:click={(e) => deleteTodo(todo)}>Delete</button>
</div>
{/each}
</main>
<style>
</style>
jQuery 前端
因此,让我们做一些不同的事情,使用 webpack 的 jQuery 怎么样!
设置
-
确保您的 todo api 正在运行,并在终端中导航到您的 todo 文件夹
-
运行命令
npx merced-spinup jquerywebpack todo_jquery_frontend
-
cd 进入 todo_jquery_frontend 文件夹并运行
npm install
-
npm run dev
启动开发服务器
显示待办事项
-
创建一个从 API 中提取待办事项的函数
-
创建一个函数来获取这些待办事项并渲染列表
-
调用后一个函数
src/index.js
import $ from "jquery"
import _ from "lodash"
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`)
//The UL for the Todo List
const $todoList = $("#todolist")
const baseURL = "http://localhost:3000/todos"
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
//return promise of data
return data
}
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos()
todos.forEach(todo => {
const $li = $("<li>")
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
`)
$todoList.append($li)
})
}
// Initial Fetch of Todos
renderTodos()
创建待办事项
- 创建表单和变量来保存表单和输入
- 为表单提交时创建一个函数
import $ from "jquery";
import _ from "lodash";
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form id="createForm">
<input type="text" name="createTitle"/>
<input type="text" name="createBody"/>
<input type="submit" value="Create Todo">
</form>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`);
//The UL for the Todo List
const $todoList = $("#todolist");
//Create Form Variables
const $createForm = $("#createForm");
const $createTitle = $('input[name="createTitle');
const $createBody = $('input[name="createBody');
const baseURL = "http://localhost:3000/todos";
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL);
const data = await response.json();
//return promise of data
return data;
};
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos();
$todoList.empty();
todos.forEach((todo) => {
const $li = $("<li>");
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
`);
$todoList.append($li);
});
};
//Function to Create a to do
const createTodo = async (event) => {
event.preventDefault();
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $createTitle.val(),
body: $createBody.val(),
}),
});
renderTodos();
$createTitle.val("");
$createBody.val("");
};
//Add Event Listener to Form
$createForm.on("submit", createTodo);
// Initial Fetch of Todos
renderTodos();
更新待办事项
- 添加编辑按钮
- 添加编辑表单
- 为表单和输入创建变量
- 创建函数来为选定的待办事项设置变量
- 创建函数以在提交表单时发出发布请求。
import $ from "jquery";
import _ from "lodash";
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form id="createForm">
<input type="text" name="createTitle"/>
<input type="text" name="createBody"/>
<input type="submit" value="Create Todo">
</form>
<hr>
<form id="editForm">
<input type="text" name="editTitle"/>
<input type="text" name="editBody"/>
<input type="submit" value="Update Todo">
</form>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`);
//The UL for the Todo List
const $todoList = $("#todolist");
//Create Form Variables
const $createForm = $("#createForm");
const $createTitle = $('input[name="createTitle"]');
const $createBody = $('input[name="createBody"]');
//Create Form Variables
const $editForm = $("#editForm");
const $editTitle = $('input[name="editTitle"]');
const $editBody = $('input[name="editBody"]');
let editId = 0
//API URL
const baseURL = "http://localhost:3000/todos";
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL);
const data = await response.json();
//return promise of data
return data;
};
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos();
$todoList.empty();
todos.forEach((todo) => {
const $li = $("<li>");
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
<button id="${todo.id}editbutton">Edit</button>
`);
$todoList.append($li);
$(`#${todo.id}editbutton`).on('click', () => {
$editTitle.val(todo.title)
$editBody.val(todo.body)
editId = todo.id
})
});
};
//Function to Create a to do
const createTodo = async (event) => {
event.preventDefault();
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $createTitle.val(),
body: $createBody.val(),
}),
});
renderTodos();
$createTitle.val("");
$createBody.val("");
};
//Function to update a to do
const updateTodo = async (event) => {
event.preventDefault();
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $editTitle.val(),
body: $editBody.val(),
}),
});
renderTodos();
$editTitle.val("");
$editBody.val("");
};
//Add Event Listener to Form
$createForm.on("submit", createTodo);
//Add Event Listener to Form
$editForm.on("submit", updateTodo);
// Initial Fetch of Todos
renderTodos();11
删除待办事项
终于……我们上次构建的最后一个函数了。我们只需要创建一个触发删除函数的删除按钮,就大功告成了!我们会在 renderTodos 函数中添加监听器时定义该函数,这样 todo 就包含在作用域中了。
import $ from "jquery";
import _ from "lodash";
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form id="createForm">
<input type="text" name="createTitle"/>
<input type="text" name="createBody"/>
<input type="submit" value="Create Todo">
</form>
<hr>
<form id="editForm">
<input type="text" name="editTitle"/>
<input type="text" name="editBody"/>
<input type="submit" value="Update Todo">
</form>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`);
//The UL for the Todo List
const $todoList = $("#todolist");
//Create Form Variables
const $createForm = $("#createForm");
const $createTitle = $('input[name="createTitle"]');
const $createBody = $('input[name="createBody"]');
//Create Form Variables
const $editForm = $("#editForm");
const $editTitle = $('input[name="editTitle"]');
const $editBody = $('input[name="editBody"]');
let editId = 0
//API URL
const baseURL = "http://localhost:3000/todos";
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL);
const data = await response.json();
//return promise of data
return data;
};
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos();
$todoList.empty();
todos.forEach((todo) => {
const $li = $("<li>");
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
<button id="${todo.id}editbutton">Edit</button>
<button id="${todo.id}deletebutton">Delete</button>
`);
$todoList.append($li);
//add function to edit button
$(`#${todo.id}editbutton`).on('click', () => {
$editTitle.val(todo.title)
$editBody.val(todo.body)
editId = todo.id
})
//add function to delete button
$(`#${todo.id}deletebutton`).on('click', async () => {
await fetch(baseURL + "/" + todo.id, {
method: "delete"
})
renderTodos()
})
});
};
//Function to Create a to do
const createTodo = async (event) => {
event.preventDefault();
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $createTitle.val(),
body: $createBody.val(),
}),
});
renderTodos();
$createTitle.val("");
$createBody.val("");
};
//Function to update a to do
const updateTodo = async (event) => {
event.preventDefault();
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $editTitle.val(),
body: $editBody.val(),
}),
});
renderTodos();
$editTitle.val("");
$editBody.val("");
};
//Add Event Listener to Form
$createForm.on("submit", createTodo);
//Add Event Listener to Form
$editForm.on("submit", updateTodo);
// Initial Fetch of Todos
renderTodos();
恭喜
你只需一个 API,就能构建出 5 个独立的前端应用!希望这能让你更深入地理解构建前端应用的不同方式以及 API 的模块化。
鏂囩珷鏉ユ簮锛�https://dev.to/alexmercedcoder/1-backend-5-frontends-todo-list-with-rails-react-angular-vue-svelte-and-jquery-18kp