Skip to content
This repository was archived by the owner on Mar 1, 2025. It is now read-only.

Commit a5205ab

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents ad34a62 + f7cccea commit a5205ab

7 files changed

Lines changed: 317 additions & 8 deletions

DriveFLY_FullStack_Compass.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,10 @@ https://learn.shayhowe.com/html-css/
152152

153153
给我牛坏了。
154154

155+
### 02.15
156+
157+
爱好是爱好,工作是工作。
158+
159+
后端给的文档里 KV 类别字段在示例中传 V,心生疑惑但仍以示例为准,一顿操作猛如虎完成新增,结果查询接口异常,询问之,答曰有些示例瞎写的……
160+
155161
<!-- Content_END -->

Hoshino_FullStack_Compass.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,40 @@
2121

2222
还有一个css的布局属性`display:block`会使一个元素自动占据一行, 导致本该渲染在同一行的元素呈`column`布局,使用`display:inline`布局可以解决这个问题。
2323

24+
### 02.15
2425

26+
JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。
27+
28+
- JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
29+
- 它是类型安全的,在编译过程中就能发现错误。
30+
- 使用 JSX 编写模板更加简单快速。
31+
32+
React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合,比如,在**UI**中需要绑定处理事件、在某些时刻状态发生变化时需要通知到**UI**,以及需要在**UI**中展示准备好的数据。但是React不强制要求使用JSX。
33+
34+
JSX是JS的语法糖,编译时JSX会通过Babel编译成JS。React源码中使用React.createElement()方法来创建JSX,该方法依次接收DOM节点(比如div、span)、属性集合(比如className、style)和children(子节点)三个参数,并返回一个JS对象,也就是虚拟DOM。
35+
36+
以下两段示例是等价的:
37+
38+
```jsx
39+
const element = (
40+
<h1 className="greeting">
41+
Hello, world!
42+
</h1>
43+
);
44+
```
45+
46+
```jsx
47+
const element = React.createElement(
48+
'h1',
49+
{className: 'greeting'},
50+
'Hello, world!'
51+
);
52+
```
53+
54+
要从组件返回多个元素,必须用一个`parent tag`包裹它们,可以使用`<div></div>`或者一个空标签`<></>`
55+
56+
JSX 要求标签明确关闭:像 `<img>` 这样的自闭合标签必须写成 `<img />`,像 `<li>oranges` 这样的包装标签必须写成 `<li>oranges</li>`
57+
58+
可以使用[转换器](https://transform.tools/html-to-jsx),将现有的`html`代码转换为`JSX`代码。
2559

2660
<!-- Content_END -->

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ SaaS、Typescript、React、Nextjs、Taildwindcss、MDX、Linaria、Shiki、Reac
129129
<!-- START_COMMIT_TABLE -->
130130
| | 2.03 | 2.04 | 2.05 | 2.06 | 2.07 | 2.08 | 2.09 | 2.10 | 2.11 | 2.12 | 2.13 | 2.14 | 2.15 | 2.16 | 2.17 | 2.18 | 2.19 | 2.20 | 2.21 | 2.22 | 2.23 |
131131
| ------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
132-
| echozyr2001 |||| ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || | | | | | | | | | |
132+
| echozyr2001 |||| ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ || | | | | | | | |
133133
| Kirov7 | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || | | | | | | | | | | | | | | |
134-
| Hoshino | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | | | | | | | | | | |
135-
| RisingGalaxy | ⭕️ ||| ⭕️ | ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | | | | | | | | | | |
136-
| YamKH514 ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ | | | | | | | | | | |
137-
| DriveFLY ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | | | | | | | | | | |
138-
| Makise | ⭕️ ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ |||| | | | | | | | | | |
139-
| DemoJustLuGuo ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ | ⭕️ || | | | | | | | | | |
140-
| AmberHeart |||| ⭕️ | ⭕️ | ⭕️ | ⭕️ ||||| | | | | | | | | | |
134+
| Hoshino | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || | | | | | | | |
135+
| RisingGalaxy | ⭕️ ||| ⭕️ | ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || | | | | | | | |
136+
| YamKH514 ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ | ⭕️ | ⭕️ | | | | | | | | |
137+
| DriveFLY ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || | | | | | | | |
138+
| Makise | ⭕️ ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ |||| | ⭕️ | | | | | | | | |
139+
| DemoJustLuGuo ||| ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ || ⭕️ | ⭕️ || ⭕️ | ⭕️ | | | | | | | | |
140+
| AmberHeart |||| ⭕️ | ⭕️ | ⭕️ | ⭕️ ||||| ⭕️ | ⭕️ | | | | | | | | |
141141
<!-- END_COMMIT_TABLE -->
142142

143143
## 数据统计

RisingGalaxy_FullStack_Compass.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,14 @@ flex: unset;
166166
- _[Flex 布局教程:语法篇 - 阮一峰的网络日志](https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=chatgpt.com)_
167167
- [mdn web docs &gt; CSS &gt; flex](https://developer.mozilla.org/zh-CN/docs/Web/CSS/flex?utm_source=blog.rising-galaxy.top#%E5%BD%A2%E5%BC%8F%E5%AE%9A%E4%B9%89)
168168

169+
### 02.15
170+
171+
> Learning time: About `1.5` hours
172+
173+
---
174+
175+
有事耽搁,今日仅跟着做了下右侧面板。
176+
177+
同时算是简单认识了一下 TypeScript 中的解构赋值写法。
178+
169179
<!-- Content_END -->

echozyr2001_FullStack_Compass.md

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,263 @@
124124

125125
![animation](./images/echozyr2001/animation.png)
126126

127+
### 02.15
128+
129+
> 学习时间:120 min
130+
131+
cfc-web 项目开始要用到后端了。我暂时懒得去搭建后端服务,决定在 `convex``sanity` 中选择一个使用,下面是它们之间的对比:
132+
133+
**核心定位**
134+
|工具|类型|主要用途|
135+
|--|--|--|
136+
|Convex|实时后端即服务(BaaS)|提供实时数据库、函数即服务(FaaS)、状态管理,用于快速构建全栈实时应用。|
137+
|Sanity|内容管理系统(CMS)|专注于内容管理和结构化数据存储,提供灵活的内容建模和编辑界面。|
138+
139+
考虑到目前最高优先级是实现表单提交并储存的功能,而 `Sanity` 更适合博客或文档这类的内容管理,于是我决定使用 `Convex`
140+
141+
但是 `Convex` 也存在一个缺点,它不是开源的,若持续使用可能会产生费用。若需要开源方案可以选择 `Supabase`,但因为之前使用过 `Supabase`,我又想尝试一些新东西,所以还是用用 `Convex` 吧,等到了收费那一步在做迁移吧(虽然迁移难度应该挺大)。
142+
143+
---
144+
145+
**走一遍 Convex 官方的教程**
146+
147+
初始化项目:
148+
149+
```shell
150+
npm install convex
151+
152+
npx convex dev
153+
```
154+
155+
创建实例数据 `sampleData.jsonl`
156+
157+
```jsonl
158+
{"text": "Buy groceries", "isCompleted": true}
159+
{"text": "Go for a swim", "isCompleted": true}
160+
{"text": "Integrate Convex", "isCompleted": false}
161+
```
162+
163+
通过以下方式添加到数据库中:
164+
165+
```shell
166+
npx convex import --table tasks sampleData.jsonl
167+
```
168+
169+
可以在网页中看到数据
170+
171+
![data](./images/echozyr2001/data.png)
172+
173+
通过下面的方式定义一个查询 api,用于查询 tasks 库中的内容。
174+
175+
```typescript
176+
import { query } from "./_generated/server";
177+
178+
export const get = query({
179+
args: {},
180+
handler: async (ctx) => {
181+
return await ctx.db.query("tasks").collect();
182+
},
183+
});
184+
```
185+
186+
在查询前需要创建一个 provider(常规操作了)
187+
188+
```tsx
189+
"use client";
190+
191+
import { ConvexProvider, ConvexReactClient } from "convex/react";
192+
import { ReactNode } from "react";
193+
194+
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
195+
196+
export function ConvexClientProvider({ children }: { children: ReactNode }) {
197+
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
198+
}
199+
```
200+
201+
privider 需要包裹在 RootLayout 下:
202+
203+
```tsx
204+
"use client";
205+
206+
import { ConvexProvider, ConvexReactClient } from "convex/react";
207+
import { ReactNode } from "react";
208+
209+
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
210+
211+
export function ConvexClientProvider({ children }: { children: ReactNode }) {
212+
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
213+
}
214+
215+
{/* */}
216+
217+
import { ThirdwebProvider } from "thirdweb/react";
218+
import { ConvexClientProvider } from "./convex-client-provider";
219+
220+
export function Providers({
221+
children,
222+
}: Readonly<{
223+
children: React.ReactNode;
224+
}>) {
225+
return (
226+
<ThirdwebProvider>
227+
<ConvexClientProvider>{children}</ConvexClientProvider>
228+
</ThirdwebProvider>
229+
);
230+
}
231+
```
232+
233+
下面是查询的方式
234+
235+
```tsx
236+
"use client";
237+
238+
import Image from "next/image";
239+
import { useQuery } from "convex/react";
240+
import { api } from "../convex/_generated/api";
241+
242+
export default function Home() {
243+
const tasks = useQuery(api.tasks.get);
244+
return (
245+
<main className="flex min-h-screen flex-col items-center justify-between p-24">
246+
{tasks?.map(({ _id, text }) => <div key={_id}>{text}</div>)}
247+
</main>
248+
);
249+
}
250+
```
251+
252+
---
253+
254+
**Convex 数据库概念**
255+
256+
> Convex 数据库采用关系型数据模型设计,支持类 JSON 文档存储,可自由选择是否使用模式定义。其"开箱即用"的特性,通过简洁易用的接口即可实现稳定的查询性能。
257+
>
258+
> 通过轻量级 JavaScript API,您可以直接在查询和变更函数中实现数据读写操作。无需任何配置,无需编写 SQL 语句,仅需使用 JavaScript 即可满足应用程序的所有数据需求。
259+
260+
**Tables**
261+
262+
`Conve`x 中,数据库表不需要事先指定结构,插入内容之后表结构会自行创建。
263+
264+
```ts
265+
// `friends` table doesn't exist.
266+
await ctx.db.insert("friends", { name: "Jamie" });
267+
// Now it does, and it has one document.
268+
```
269+
270+
**Documents**
271+
272+
表中的内容被称为 `Documents`,它是一个 `json` 对象,类似 `mongoDB` 中的数据。
273+
274+
> 这里有一种 .jsonl 文件,我的理解是它是一些又 json 对象组成的列表
275+
276+
```jsonl
277+
{}
278+
{"name": "Jamie"}
279+
{"name": {"first": "Ari", "second": "Cole"}, "age": 60}
280+
```
281+
282+
**Schemas**
283+
284+
若实在需要定义表结构,可以使用 `Schemas`
285+
286+
```ts
287+
import { defineSchema, defineTable } from "convex/server";
288+
import { v } from "convex/values";
289+
290+
// @snippet start schema
291+
export default defineSchema({
292+
messages: defineTable({
293+
author: v.id("users"),
294+
body: v.string(),
295+
}),
296+
});
297+
```
298+
299+
---
300+
301+
**写入数据**
302+
303+
使用 `db.insert` 方法在数据库中创建新 `Document``insert` 会返回插入结果的 `id`
304+
305+
```ts
306+
import { mutation } from "./_generated/server";
307+
import { v } from "convex/values";
308+
309+
export const createTask = mutation({
310+
args: { text: v.string() },
311+
handler: async (ctx, args) => {
312+
const taskId = await ctx.db.insert("tasks", { text: args.text });
313+
// do something with `taskId`
314+
},
315+
});
316+
```
317+
318+
使用 `db.patch` 方法更新现有 `Document`
319+
320+
```ts
321+
import { mutation } from "./_generated/server";
322+
import { v } from "convex/values";
323+
324+
export const updateTask = mutation({
325+
args: { id: v.id("tasks") },
326+
handler: async (ctx, args) => {
327+
const { id } = args;
328+
console.log(await ctx.db.get(id));
329+
// { text: "foo", status: { done: true }, _id: ... }
330+
331+
// Add `tag` and overwrite `status`:
332+
await ctx.db.patch(id, { tag: "bar", status: { archived: true } });
333+
console.log(await ctx.db.get(id));
334+
// { text: "foo", tag: "bar", status: { archived: true }, _id: ... }
335+
336+
// Unset `tag` by setting it to `undefined`
337+
await ctx.db.patch(id, { tag: undefined });
338+
console.log(await ctx.db.get(id));
339+
// { text: "foo", status: { archived: true }, _id: ... }
340+
},
341+
});
342+
```
343+
344+
使用 `db.delete` 方法删除现有 `Document`
345+
346+
```ts
347+
import { mutation } from "./_generated/server";
348+
import { v } from "convex/values";
349+
350+
export const deleteTask = mutation({
351+
args: { id: v.id("tasks") },
352+
handler: async (ctx, args) => {
353+
await ctx.db.delete(args.id);
354+
},
355+
});
356+
```
357+
358+
---
359+
360+
**定义Schemas**
361+
362+
`npm convex dev` 启动的情况下,创建 `convex/schema.ts` 文件,会自动在数据库中创建对应的表结构。
363+
364+
```ts
365+
import { defineSchema, defineTable } from "convex/server";
366+
import { v } from "convex/values";
367+
368+
export default defineSchema({
369+
messages: defineTable({
370+
body: v.string(),
371+
user: v.id("users"),
372+
}),
373+
users: defineTable({
374+
name: v.string(),
375+
tokenIdentifier: v.string(),
376+
}).index("by_token", ["tokenIdentifier"]),
377+
});
378+
```
379+
380+
同时,在这种情况下使用未在 `schema.ts` 中定义的表会报错(例如在教程中创建的 `tasks` 表)。
381+
382+
![error-table](./images/echozyr2001/error-table.png)
383+
384+
> 总结,快速过了一下 convex 的教程,熟悉了插入与查询数据的方式,同时成功在 `cfc-web` 项目中实现报名表单数据的提交。
385+
127386
<!-- Content_END -->

images/echozyr2001/data.png

84.8 KB
Loading

images/echozyr2001/error-table.png

26.3 KB
Loading

0 commit comments

Comments
 (0)