背景
上周末在家没啥事,想写点东西,一时不知道写什么好。然后就想起来一个去了Airbnb
的同学,说 Airbnb 的面试风格是以实操为主,她面了 8 轮,轮轮都是写代码(2018 年),令人十分害怕。
代码题目都不是很难,简单分享几道题:
然后我就看到了实现一个Todo List
。
这种题目不难,但是 灵活度很高
,没有什么 限制
条件,你随意发挥,可以从多方面考察候选人。
就拿这道题下手吧,开造。
[文末有本文全部的源代码, 通过这个例子,你会了解 React Context
,Hooks
的使用方式,以及 如何使用 Golang 编写 CURD Api
]
废话不多说了,进入正题。
功能实现
首先就是新建一个项目,不限工具,CRA
什么的都可以, 我就用了之前自己写的一个工具,简单起了项目, 不过这些都无所谓了,直接上代码:
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('root'));
App
// App.js
import React from "react";
import {TodosProvider} from './Store'
import {TodoList} from './TodoList'
const App = () => {
return (
<TodosProvider>
<TodoList />
</TodosProvider>
);
}
export default App
Store
这里我创建了两个 Context,一个用于 存储
数据,另一个用于 更新
数据。
例如:
const initialState = []
const StateContext = React.createContext(initialState)
const UpdateContext = React.createContext(null)
被 Context 包裹的组件可以取用这些传入的值。
完整代码:
// Store.js
import React from 'react'
import produce from 'immer'
// An array of todos, where a todo looks like this:
// {id: string; title: string; isCompleted: boolean}
const initialTodos = [{
id: 1,
title: "One",
isCompleted: false
}, {
id: 2,
title: "Two",
isCompleted: false
}, {
id: 3,
title: "Three",
isCompleted: false
}]
const StateContext = React.createContext(initialTodos)
const UpdateContext = React.createContext(null)
export function TodosProvider({children}) {const [todos, updateTodos] = React.useReducer(produce, initialTodos)
return (<UpdateContext.Provider value={updateTodos}>
<StateContext.Provider value={todos}>
{children}
</StateContext.Provider>
</UpdateContext.Provider>
)
}
export function useTodos() {return [React.useContext(StateContext), React.useContext(UpdateContext)]
}
Todo 主体
这里的实现也很简单,我先简单做了两个小功能,一个是 完成
某一项,一个是 删除
某一项,完整代码:
// TodoList
import React from 'react';
import {useTodos} from './Store'
export function TodoList() {const [todos, updateTodos] = useTodos()
const deleteTodo = id => updateTodos(todos => {const todoIdxToDelete = todos.findIndex(todo => todo.id === id)
todos.splice(todoIdxToDelete, 1)
})
const completeTodo = id => updateTodos(todos => {todos.find(todo => todo.id === id).isCompleted = true
})
return (
<ul>
{todos.map(todo => (<li key={todo.id} style={todo.isCompleted ? { color: 'red'} : {color: 'green'}}>
<span>{todo.title}</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
<button onClick={() => completeTodo(todo.id)}>Complete</button>
</li>
))}
</ul>
)
}
DEMO:
下面把新增也一起做了。
想着都已经做到这一步了,数据一刷新就没了,干脆存到数据库里吧,最终的样子:
后端接口实现:
看下这几个 CURD
接口是怎么写的:
Api: C
Api: U
Api: R
Api: D
代码都比较简单,一眼就能看明白是做什么的,就不多做解释了。
后端完整的代码在这里:
https://github.com/beMySun/go…
前端部分完整的代码在这里:
https://github.com/beMySun/re…
数据库用的 mySql, 建库,加改表可以用这个 Sequel Pro,很方便
如果不想用这个,也可以用命令行工具来操作。
再贴几个会用的命令吧:
show databases;
use database;
describe todos_tab;
select * from todos_tab limit 10;
加一个字段:text
加一个字段:isCompleted
最后
功能很简单,但是做的时候需要考虑的东西还是很多的。
如果有朋友也想学习下,可以把代码下载下来自己运行跑一下。
后端完整的代码在这里:
https://github.com/beMySun/go…
前端部分完整的代码在这里:
https://github.com/beMySun/re…
这个后端的 demo 包含了完整的 CURD,是一个很好的学习 demo, 希望对大家的学习有所帮助。
才疏学浅,行文难免有纰漏。
若有错误,欢迎指正,谢谢。
以上。
如果本文对你有帮助,别忘了点赞呦~
参考资料:
https://learnku.com/golang/t/…
https://gorm.io/docs/update.h…