chore: migrate project to monorepo
No files matched your search
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "高级教程",
|
||||
"position": 6,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# 面向前端的协同编程探索
|
||||
|
||||
低代码,无代码等概念已经不再新鲜。同时协同编程也会被经常提到。
|
||||
|
||||
虽然协同编程只是一个组合词 `协同` + `编程`,但是要做的事情远没有这么简单。
|
||||
|
||||
> 协同编程
|
||||
>
|
||||
> - 编辑 —— 协同编辑
|
||||
> - 构建 —— 预置的构建方案
|
||||
> - 运行 —— 在目标环境运行
|
||||
|
||||
## 编辑
|
||||
|
||||
编辑在传统的编辑器的基础上要求更高,需要协同编辑。
|
||||
|
||||
- 离线编辑
|
||||
|
||||
### 编辑器
|
||||
|
||||
- prosemirror
|
||||
- codemirror
|
||||
- monaco-editor
|
||||
|
||||
### 协同算法
|
||||
|
||||
- OT
|
||||
- @codemirror/collab
|
||||
- CRDT
|
||||
- yjs
|
||||
- automerge
|
||||
|
||||
相关文章
|
||||
|
||||
偏向数学理论
|
||||
|
||||
https://www.zxch3n.com/crdt-intro/design-crdt/
|
||||
|
||||
偏向实现细节
|
||||
|
||||
https://zhuanlan.zhihu.com/p/265074361
|
||||
|
||||
### 多窗口库
|
||||
|
||||
- https://github.com/caplin/FlexLayout
|
||||
- https://github.com/ticlo/rc-dock
|
||||
- https://github.com/golden-layout/golden-layout
|
||||
- https://github.com/nomcopter/react-mosaic
|
||||
- https://github.com/idealjs/layout-manager
|
||||
|
||||
## 构建
|
||||
|
||||
### 构建工具
|
||||
|
||||
- esbuild
|
||||
- swc
|
||||
- webpack https://github.com/webpack/playground 已过时
|
||||
|
||||
### 文件系统
|
||||
|
||||
- 虚拟文件系统
|
||||
- memfs
|
||||
- memory
|
||||
- filer
|
||||
- indexdb
|
||||
- memory
|
||||
- unionfs
|
||||
- 文件系统
|
||||
- FileSystem
|
||||
- unionfs
|
||||
|
||||
## 运行
|
||||
|
||||
- dynamic import
|
||||
|
||||
- IIFE (Immediately Invoked Function Expression)
|
||||
- iframe
|
||||
|
||||
使用了 `构建` + `运行` 的平台
|
||||
|
||||
- codesandbox
|
||||
- codepen
|
||||
- stackblitz
|
||||
|
||||
|
||||
## 既要也要的矛盾
|
||||
|
||||
- 离线优先 与 CAP
|
||||
|
||||
传统分布式软件中分区容错性被看的很重要。离线优先也可以被视作分区容错的子集。
|
||||
|
||||
但是离线优先的设计带来了无法在协同编程中解决的问题。
|
||||
|
||||
### 场景
|
||||
|
||||
A B C 三人,P2P 协同编程。
|
||||
|
||||
存在一段错误的代码
|
||||
|
||||
```js
|
||||
let = "A"
|
||||
|
||||
username = "C"
|
||||
```
|
||||
|
||||
当三人同时开始修复此问题时,A出现离线情况。
|
||||
|
||||
B C 二人协同修复得到的结果
|
||||
|
||||
```js
|
||||
let username = "A"
|
||||
|
||||
username = "C"
|
||||
```
|
||||
|
||||
A 离线修复结果
|
||||
|
||||
```js
|
||||
let username = "A"
|
||||
|
||||
username = "C"
|
||||
```
|
||||
|
||||
看上去 A 与 B C 是一致的。但是在 CRDT 与 OT 算法中,并不是。最终 A 恢复连接,得到的结果是
|
||||
|
||||
```js
|
||||
let usernameusername = "A"
|
||||
|
||||
username = "C"
|
||||
```
|
||||
|
||||
对于协同编程来说,协同的好处是规避冲突。但是这种场景下,冲突被放大。
|
||||
|
||||
而这种情况在 git 的方案内,不会发生冲突。
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "全栈基础",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "完整指南",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "访问HTML网页的流程",
|
||||
"position": 1,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,75 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 访问 HTML 网页的流程
|
||||
|
||||
我们将通过 `http-server` 来模拟访问 HTML 网页的过程,从浏览器、网络和服务器这几个方面详细介绍。
|
||||
|
||||
## 创建index.html
|
||||
1. 对于创建`index.html`文件,可以参考[使用VScode](https://idealjs.github.io/full-stack-tutorial/docs/web/hello_world/use_vscode)文档
|
||||
2. 在`index.html`文件输入内容,可以参考[第一个页面(hello world)](https://idealjs.github.io/full-stack-tutorial/docs/web/hello_world/first_page)文档
|
||||
|
||||
## 安装http-server
|
||||
运行以下命令进行安装,其中`-g`代表全局安装
|
||||
```
|
||||
npm install -g http-server
|
||||
```
|
||||
|
||||
## 启动http-server
|
||||
### 1.进入文件夹
|
||||
安装完成并创建好`index.html`文件后,就可以通过以下命令进入包含`index.html`文件的文件夹
|
||||
```
|
||||
cd ~/test
|
||||
```
|
||||
### 2.启动服务
|
||||
在控制台运行以下命令来启动服务
|
||||
```
|
||||
http-server
|
||||
```
|
||||
启动成功后,命令行会输出以下网址
|
||||

|
||||
这时,你可以在浏览器中输入 `http://127.0.0.1:8080` 或者`http://localhost:8080` 来访问你的网页
|
||||
|
||||
## 无痕模式
|
||||
用户可以使用以下快捷键,打开无痕窗口
|
||||
```
|
||||
Ctrl+Shift+N
|
||||
```
|
||||
按下`F12`,进入检查
|
||||

|
||||
|
||||
## 先决条件
|
||||
- 你需要已经安装并启动 `http-server`。
|
||||
|
||||
## 浏览器的工作步骤
|
||||
|
||||
### 1. 建立 TCP 连接
|
||||
浏览器会向 `127.0.0.1:8080` 发送建立 TCP 连接的请求。服务器收到请求后,会确认客户端的身份,然后向客户端回复消息,从而建立起服务器与客户端之间的连接。
|
||||
|
||||
### 2. 发送 GET 请求
|
||||
浏览器会向服务器发送一个路径为 `/` 的 GET 请求。
|
||||
|
||||

|
||||
|
||||
## 服务器的工作步骤
|
||||
|
||||
### 1. 查找文件
|
||||
当服务器接收到浏览器的请求后,就像一位仓库管理员,会在众多文件中查找 `index.html` 文件。
|
||||
|
||||

|
||||
|
||||
### 2. 生成 HTTP 响应
|
||||
服务器找到文件后,会对其进行处理,将其转换为适合在网络中传输的 HTTP 响应,如同把货物包装好以便运输。
|
||||
|
||||
### 3. 发送响应
|
||||
服务器会通过之前与浏览器建立的“运输通道”(TCP 连接),将生成的 HTTP 响应发送给浏览器。
|
||||
|
||||
## 渲染页面
|
||||
|
||||
### 1. 接收资源并渲染
|
||||
- 浏览器接收到资源后解析HTML、CSS和JavaScript
|
||||
- 浏览器根据解析结果构建页面结构
|
||||
|
||||
### 2. 显示页面
|
||||
页面渲染完成后,就会展示给用户。
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "react的入门",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 如何使用react+ts编写前端todo list
|
||||
本文将编写一个简单的前端todo list应用,从进入项目后,逐步实现增加,删除,筛选的功能
|
||||
|
||||
## 先决条件
|
||||
1. 已创建react ts工程
|
||||
|
||||
>**提示**
|
||||
若未创建react ts工程,可以参考[使用vite创建react ts工程](https://github.com/idealjs/full-stack-tutorial/blob/main/docs/react/react_ts.md)文档
|
||||
|
||||
## 项目初始化
|
||||
打开react ts工程
|
||||
|
||||
## 编写todo list结构及功能
|
||||
在`App.tsx`中,通过以下代码,设计结构并实现todo list的功能
|
||||
```
|
||||
//导入依赖
|
||||
import React, { useState } from 'react'
|
||||
import './App.css'
|
||||
|
||||
//定义全局变量,用于生成新数组的id
|
||||
let nextId = 4
|
||||
|
||||
function App() {
|
||||
|
||||
//定义数组
|
||||
const [products, setProducts] = useState([
|
||||
{ name: '吃饭', completed: false, id: 1 },
|
||||
{ name: '睡觉', completed: true, id: 2 },
|
||||
{ name: '打豆豆', completed: true, id: 3 },
|
||||
])
|
||||
const [inputValue, setinputValue] = useState('')
|
||||
|
||||
|
||||
|
||||
//在input中输入的值
|
||||
const handleInputValue = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.target.value;
|
||||
setinputValue(value)
|
||||
console.log('当前的值', value);
|
||||
|
||||
}
|
||||
|
||||
//在输入框中按下回车键的事件
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (inputValue === '') {
|
||||
return
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
const newProduct = {
|
||||
name: inputValue.trim(),
|
||||
completed: false,
|
||||
id: nextId++
|
||||
}
|
||||
|
||||
setProducts([...products, newProduct]);
|
||||
setinputValue('')
|
||||
console.log(`按下回车键的值:${inputValue}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//切换completed的状态
|
||||
const CompleteStatus = (id:number)=>{
|
||||
setProducts(
|
||||
products.map((product) =>
|
||||
product.id === id ? {...product,completed: !product.completed} : product)
|
||||
)
|
||||
}
|
||||
|
||||
//筛选功能的实现
|
||||
const [filter,setFilter] = useState<'all'|'active'|'completed'>('all')
|
||||
|
||||
const onShow = products.filter((product) => {
|
||||
if(filter === 'active'){
|
||||
return !product.completed
|
||||
}else if(filter === 'completed'){
|
||||
return product.completed
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
const count = products.filter((product) => !product.completed).length
|
||||
|
||||
//渲染组件
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<h1>TODO LIST</h1>
|
||||
<input
|
||||
className="input-todo"
|
||||
type='text'
|
||||
placeholder='您想做点什么'
|
||||
onChange={handleInputValue}
|
||||
onKeyDown={handleKeyDown}
|
||||
value={inputValue}
|
||||
></input>
|
||||
<ul>
|
||||
{/* {TodoItem} */}
|
||||
{onShow.map(product => (
|
||||
<li key={product.id}>{product.name}{' '}
|
||||
<span className={`icon-complete ${product.completed ? 'icon-complete-active' : ''}`}
|
||||
onClick={() => CompleteStatus(product.id)}
|
||||
>
|
||||
</span>{' '}
|
||||
<button onClick={() => {
|
||||
setProducts(products.filter((a) => a.id !== product.id));
|
||||
}}>删除</button>
|
||||
</li>
|
||||
))}
|
||||
|
||||
</ul>
|
||||
<div>
|
||||
<span>还有<span>{count}</span>个未完成</span>
|
||||
<div className='filter-btn-group'>筛选
|
||||
<button onClick={()=> setFilter('all')}>全部</button>
|
||||
<button onClick={()=> setFilter('active')}>未完成</button>
|
||||
<button onClick={()=>setFilter('completed')}>已完成</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
```
|
||||
## 设计todo list的样式
|
||||
在`App.css`中,通过以下代码,设计todo list的样式
|
||||
```
|
||||
#root {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.react:hover {
|
||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
a:nth-of-type(2) .logo {
|
||||
animation: logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.icon-complete{
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.icon-complete-active::after{
|
||||
content: '√';
|
||||
color: green;
|
||||
}
|
||||
```
|
||||
|
||||
## 运行项目
|
||||
按下快捷键`Ctrl + ~`,打开终端,输入以下命令,运行项目
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||

|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 使用vite创建react ts工程
|
||||
React 应用程序是由组件组成的。一个组件是 UI(用户界面)的一部分,它拥有自己的逻辑和外观。组件可以小到一个按钮,也可以大到整个页面。
|
||||
|
||||
## 项目初始化
|
||||
### 1. 创建react+ts项目
|
||||
按下快捷键`Ctrl + ~`,打开终端,运行以下命令
|
||||
```
|
||||
npm create vite@latest
|
||||
```
|
||||
|
||||
根据提示,输入项目名字并选择react,再选择TypeScript
|
||||
|
||||
### 2. 打开项目
|
||||
运行以下命令,进入项目
|
||||
```
|
||||
cd react-ts-test1
|
||||
```
|
||||
|
||||
### 3. 安装依赖
|
||||
运行以下命令,安装依赖
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### 4. 运行项目
|
||||
输入以下命令,运行项目
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "vite的入门",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# vite的入门
|
||||
vite 是一个现代化的前端构建工具,旨在提供快速的开发体验和高效的生产构建。
|
||||
|
||||
## 什么是vite
|
||||
访问网站 https://vitejs.cn/vite3-cn/guide/
|
||||
|
||||
## 创建vanilla ts工程
|
||||
### 打开终端
|
||||
使用快捷键`Ctrl+ ~` 打开终端
|
||||
|
||||
### 创建项目
|
||||
1. 输入以下命令,创建项目
|
||||
```
|
||||
npm create vite@latest
|
||||
```
|
||||
2. 根据提示,输入名字并选择vanilla,再选择typescript
|
||||
|
||||
3. 输入以下命令,进入项目
|
||||
```
|
||||
cd vanilla-ts-test
|
||||
```
|
||||
|
||||
4. 输入以下命令安装依赖
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
5. 输入以下命令运行项目
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "vanilla ts工程",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,200 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
# 如何使用html+ts编写前端todo list
|
||||
|
||||
## 先决条件
|
||||
1. 已创建vanilla ts工程
|
||||
|
||||
>**提示**
|
||||
若未安装vanilla ts工程,可以参考[vite的入门](https://github.com/idealjs/full-stack-tutorial/blob/main/docs/vite/vite.md)文档
|
||||
|
||||
## 项目初始化
|
||||
打开vanilla ts工程
|
||||
|
||||
## 编写HTML结构
|
||||
在`index.html`中,通过以下代码,编写todo list的样式和基本结构
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
.icon-complete {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.icon-complete-active {
|
||||
border-color: green;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.todo-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.icon-complete-active::after {
|
||||
content: "√";
|
||||
color: green;
|
||||
|
||||
}
|
||||
|
||||
.item-complete .todo-text {
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<input class="input-todo" type="text" placeholder="您想做点什么?">
|
||||
|
||||
|
||||
<ul class="todo-list">
|
||||
<li class="todo-item">
|
||||
<span class="icon-complete" onclick="onClickCompleteBtn(0)"></span>
|
||||
<span class="todo-text">吃饭</span>
|
||||
<button class="btn-complete">完成</button>
|
||||
<button class="deleted" onclick="deleteItem(0)">删除</button>
|
||||
</li>
|
||||
<li class="item-complete todo-item">
|
||||
<span class="icon-complete icon-complete-active" onclick="onClickCompleteBtn(1)"></span>
|
||||
<span class="todo-text">睡觉</span>
|
||||
<button class="btn-complete">完成</button>
|
||||
<button class="deleted" onclick="deleteItem(1)">删除</button>
|
||||
</li>
|
||||
<li class="item-complete todo-item">
|
||||
<span class="icon-complete icon-complete-active" onclick="onClickCompleteBtn(2)"></span>
|
||||
<span class="todo-text">打豆豆</span>
|
||||
<button class="btn-complete">完成</button>
|
||||
<button class="deleted" onclick="deleteItem(2)">删除</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<span>还有<span class="active-num">1</span>个未完成</span>
|
||||
<div class="fliter-btn-group">
|
||||
筛选:
|
||||
<button class="filter-btn filter-btn-all" data-complete="all">全部</button>
|
||||
<button class="filter-btn filter-btn-active" data-complete="false">未完成</button>
|
||||
<button class="filter-btn filter-btn-completed" data-complete="true">已完成</button>
|
||||
<button class="btn-clear">清空</buttosn>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="./src/main.ts">
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
## 编写TypeScript逻辑
|
||||
在`main.ts`中,编写以下代码,实现todo list的功能
|
||||
```
|
||||
//定义接口TodoItem
|
||||
interface TodoItem {
|
||||
name: string;
|
||||
completed: boolean;
|
||||
}
|
||||
|
||||
//初始化数组
|
||||
let list: TodoItem[] = [
|
||||
{ name: '吃饭', completed: false },
|
||||
{ name: '睡觉', completed: true },
|
||||
{ name: '打豆豆', completed: true },
|
||||
];
|
||||
|
||||
//监听在输入框中按下回车键的事件
|
||||
document.querySelector('.input-todo')!.addEventListener('keyup', function (e: Event) {
|
||||
const event = e as KeyboardEvent;
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (!target.value?.trim()) {
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
const name = target.value;
|
||||
const item: TodoItem = { name, completed: false };
|
||||
list.push(item);
|
||||
render(list);
|
||||
target.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
//实现筛选功能
|
||||
document.querySelectorAll('.filter-btn').forEach((el) => {
|
||||
el.addEventListener('click', filterCompletedStatus);
|
||||
});
|
||||
|
||||
function filterCompletedStatus(e: Event) {
|
||||
const target = e.target as HTMLElement;
|
||||
const completed = target.dataset.complete;
|
||||
|
||||
if (completed === 'all') {
|
||||
render(list);
|
||||
return;
|
||||
}
|
||||
|
||||
const newList = list.filter((item) => item.completed === (completed === 'true'));
|
||||
renderTodoList(newList);
|
||||
}
|
||||
|
||||
document.querySelector('.btn-clear')!.addEventListener('click', () => {
|
||||
list = [];
|
||||
render(list);
|
||||
});
|
||||
|
||||
//切换completed的状态
|
||||
function onClickCompleteBtn(index: number) {
|
||||
list[index].completed = !list[index].completed;
|
||||
render(list);
|
||||
}
|
||||
|
||||
//渲染数组
|
||||
function render(list: TodoItem[]) {
|
||||
UpdateActiveNum();
|
||||
renderTodoList(list);
|
||||
}
|
||||
|
||||
//统计筛选中未完成功能数量
|
||||
function UpdateActiveNum() {
|
||||
const completedNum = list.filter((item) => !item.completed).length;
|
||||
document.querySelector('.active-num')!.innerHTML = completedNum.toString();
|
||||
}
|
||||
|
||||
//实现删除功能
|
||||
function deleteItem(index: number) {
|
||||
list.splice(index, 1);
|
||||
render(list);
|
||||
}
|
||||
|
||||
//渲染html
|
||||
function renderTodoList(list: TodoItem[]) {
|
||||
let html = '';
|
||||
list.forEach((item, index) => {
|
||||
const itemClass = item.completed ? 'item-complete todo-item' : 'todo-item';
|
||||
const spanClass = item.completed ? 'icon-complete icon-complete-active' : 'icon-complete';
|
||||
html += `<li class="${itemClass}">
|
||||
<span onclick="onClickCompleteBtn(${index})" class="${spanClass}"></span>
|
||||
<span>${item.name}</span>
|
||||
<button class="btn-complete">完成</button>
|
||||
<button class="deleted" onclick="deleteItem(${index})">删除</button>
|
||||
</li>`;
|
||||
});
|
||||
document.querySelector('.todo-list')!.innerHTML = html;
|
||||
}
|
||||
```
|
||||
## 运行项目
|
||||
按下快捷键`Ctrl + ~`,打开终端,输入以下命令,运行项目
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||

|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 引言
|
||||
|
||||
写这个的想法源自于,最开始学习编程时,无法入门的痛苦。
|
||||
|
||||
入门一个职业,不是几天就可以做到的。但也不是的几个月的培训那么长。
|
||||
|
||||
软件工程更多讲究实践,而不是理论,所以希望读者能够实践多于阅读,如果某些章节实践过,可以直接跳过去。
|
||||
|
||||
我希望可以通过十几篇文章,让任何有兴趣的人入门前端工程师这个职业。
|
||||
|
||||
## 路线图
|
||||
|
||||
文章方面,希望一天可以产出一篇文章,通过两个星期。让入门变成简单的事情。
|
||||
|
||||
网站建设方面,准备采用 docusaurus 框架,架设一个文档网站。
|
||||
|
||||
需要更新的部分
|
||||
|
||||
1. 创建 vite vanilla-js 工程。
|
||||
- 单独链接到快速创建命令篇。
|
||||
2. 按步引入 react 包。
|
||||
3. 快速创建命令,与执行效果。
|
||||
4. 工具篇,添加 vscode git graph 插件的介绍
|
||||
5. 高级篇
|
||||
1. 纯函数、副作用。
|
||||
2. 数据流,系统行为,数据副本(数据孤岛)。
|
||||
|
||||
6. 快速开始 -> 简单服务 补充 npx 命令相关。链接到工具篇
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "操作指南",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 68 KiB |
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "docker工具",
|
||||
"position": 7,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# docker的安装与验证
|
||||
docker是一种开源平台,用于开发、部署和运行应用程序。
|
||||
|
||||
## 先决条件
|
||||
1. 确保您的系统是windows专业版
|
||||
2. 已安装了wsl2
|
||||
|
||||
>**提示**
|
||||
如果没有安装wsl2,可以参考[安装wsl文档](https://learn.microsoft.com/zh-cn/windows/wsl/install)
|
||||
|
||||
## docker的安装
|
||||
### 1. 开启windows功能
|
||||
通过控制面板,开启Hyper-v和适用于windows子系统功能
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 2. 下载并安装docker
|
||||
下载docker最安全的路径就是去官网,安装时要注意勾选`wsl`选项,安装成功后跳过登录docker Hub账号
|
||||
```
|
||||
https://docs.docker.com/desktop/install/windows-install/
|
||||
```
|
||||
|
||||
## 配置Docker镜像
|
||||
安装docker后,进入docker,开始配置镜像
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
配置镜像添加以下内容
|
||||
```
|
||||
"registry-mirrors":["https://docker.m.daocloud.io","https://docker.1panel.live"]
|
||||
```
|
||||
|
||||
## 验证Docker
|
||||
运行以下命令,测试Docker是否正确安装并运行
|
||||
```
|
||||
docker run hello-world
|
||||
```
|
||||
当输出`Hello from Docker`命令时,表明Docker安装正确
|
||||

|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Docker启动数据库
|
||||
使用Docker启动PostgreSQL数据库
|
||||
|
||||
## 先决条件
|
||||
1. 已安装Docker
|
||||
2. 以wsl为开发环境
|
||||
|
||||
## 拉取 PostgreSQL 镜像
|
||||
在wsl中,运行以下命令来拉取 `PostgreSQL` 镜像:
|
||||
```
|
||||
sudo docker pull postgres
|
||||
```
|
||||
|
||||
## 创建文件并启动容器
|
||||
### 1. 创建`docker-compose.yml`文件
|
||||
运行以下命令,创建`docker-compose.yml`文件
|
||||
```
|
||||
touch docker-compose.yml
|
||||
```
|
||||
### 2. 编写文件
|
||||
在`docker-compose.yml`文件中,写入以下内容:
|
||||
```
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
restart: always
|
||||
shm_size: 128mb
|
||||
environment:
|
||||
POSTGRES_PASSWORD: example
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
adminer:
|
||||
image: adminer
|
||||
restart: always
|
||||
ports:
|
||||
- 7897:8080
|
||||
```
|
||||
### 3. 启动`PostgreSQL`数据库
|
||||
运行以下命令启动`PostgreSQL`数据库:
|
||||
```
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
### 4. 验证启动
|
||||
运行以下命令`ps`,当STATUS出现`up`的时候,容器就表示启动成功
|
||||
```
|
||||
docker ps
|
||||
```
|
||||

|
||||
|
||||
### 5. 连接到PostgreSQL数据库
|
||||
运行以下命令,连接到PostgreSQL数据库:
|
||||
```
|
||||
docker exec -it my-postgres psql -U postgres
|
||||
```
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "Prisma工具",
|
||||
"position": 10,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Next.js + Prisma + Docker构建全栈
|
||||
通过使用Next.js、Prisma和Docker来构建一个全栈应用。
|
||||
|
||||
## 先决条件
|
||||
1. 已安装Node.js 18+
|
||||
2. Prisma Postgres数据库
|
||||
3. Next.js项目
|
||||
4. 已安装Docker
|
||||
5. 确认已启动数据库
|
||||
|
||||
>**提示**
|
||||
如果不知道怎么启动数据库,可以参考使用 [Docker启动数据库](https://github.com/idealjs/full-stack-tutorial/blob/main/docs/docker/start.md)文档
|
||||
|
||||
## 项目初始化
|
||||
- 打开Next.js项目
|
||||
|
||||
### 1. 安装并初始化Prisma
|
||||
|
||||
我们需要安装Prisma客户端,运行以下代码
|
||||
```
|
||||
npm install prisma --save-dev
|
||||
```
|
||||
然后,项目初始化Prisma,运行以下命令:`init`
|
||||
```
|
||||
npx prisma init
|
||||
```
|
||||
这时会出现新目录,里面包含`schema.prisma`文件
|
||||
|
||||
### 2.定义表结构
|
||||
#### 2.1 编辑`schema.prisma`文件
|
||||
在`prisma/schema.prisma`文件中定义数据库表结构,添加以下内容:
|
||||
```
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
email String @unique
|
||||
name String?
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 配置`.env`文件
|
||||
打开`.env`文件,配置PostgreSQL数据库连接字符串。例如
|
||||
```
|
||||
DATABASE_URL="postgresql://postgres:example@localhost:5432/postgres"
|
||||
```
|
||||
|
||||
### 3. 数据库migration
|
||||
配置完后,可以使用以下命令将架构应用到数据库中:`prisma migrate dev`
|
||||
```
|
||||
npx prisma migrate dev --name init
|
||||
```
|
||||
|
||||
### 4. 使用Prisma Studio验证数据
|
||||
#### 4.1 启动Prisma Studio
|
||||
运行以下命令启动`Prisma Studio`:
|
||||
```
|
||||
npx prisma studio
|
||||
```
|
||||
#### 4.2 验证数据
|
||||
在`Prisma Studio`中,可以查看`User`表的数据,通过添加、编辑或修改记录,验证表是否正确
|
||||
|
||||

|
||||

|
||||
|
||||
### 5. 在Next.js中使用Prisma
|
||||
#### 5.1 设置Prisma客户端
|
||||
运行以下命令,创建一个新目录并在其添加一个新文件`lib/prisma.ts`
|
||||
```
|
||||
mkdir -p lib && touch lib/prisma.ts
|
||||
```
|
||||
在`lib/prisma.ts`文件中添加以下代码:
|
||||
```
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const globalForPrisma = global as unknown as { prisma: typeof prisma }
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
||||
|
||||
export default prisma
|
||||
```
|
||||
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 78 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "参考资料",
|
||||
"position":5,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "vscode插件异常",
|
||||
"position": 1,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 221 KiB |
@@ -0,0 +1,39 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 如何处理vscode安装插件异常
|
||||
让我们通过以下步骤来解决插件安装失败
|
||||
|
||||
## 1. 检查网络是否异常
|
||||
在浏览器中输入以下网址,看是否能访问,若能则不存在网络问题
|
||||
```
|
||||
https://marketplace.visualstudio.com
|
||||
```
|
||||
如果一切正常,您应该在`https://marketplace.visualstudio.com`有一个Extensions for Visual Studio Code的页面。
|
||||
|
||||

|
||||
|
||||
## 2. 防火墙阻止
|
||||
当我们第一次启动调试功能的时候,正常情况vscode会弹出防火墙阻止的界面
|
||||
|
||||

|
||||
|
||||
## 3. 设置代理
|
||||

|
||||
|
||||

|
||||
|
||||
在`setting.json`中添加以下代理
|
||||
```
|
||||
"http.proxy": "http://127.0.0.1:7897",
|
||||
"https.proxy": "http://127.0.0.1:7897",
|
||||
"http.proxyAuthorization": null,
|
||||
"http.proxyStrictSSL": false
|
||||
```
|
||||
|
||||
## 4. clash配置
|
||||
如果以上步骤都解决不了,需要查看以下`clash`的配置是否完成
|
||||
|
||||
## 5. 配置恢复
|
||||
当需要安装的插件安装完成后,就可以上面的代理配置给注释了
|
||||
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "Alias命令",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Linux alias
|
||||
在Linux中,`alias`是一个用于创建命令别名的内置命令;通过`alias`,可以把常用的命令或命令组合设置为简短的别名,从而简化操作。
|
||||
|
||||
## 使用方法
|
||||
### 1. 创建别名
|
||||
运行以下命令:
|
||||
```
|
||||
alias 别名='命令'
|
||||
```
|
||||
例如:
|
||||
```
|
||||
alias ll='ls -l'
|
||||
```
|
||||
在命令行中输入`ll`就相当于输入`ls-l`
|
||||
|
||||
### 2. 永久别名
|
||||
在`~/.bashrc`或者`~/.zshrc`文件中配置以下内容:
|
||||
```
|
||||
alias ll='ls -l'
|
||||
```
|
||||
|
||||
### 3. 查看别名
|
||||
在命令行中输入以下命令:
|
||||
```
|
||||
alias
|
||||
```
|
||||
|
||||
### 4. 删除别名
|
||||
在命令行中输入以下命令:
|
||||
```
|
||||
unalias 别名
|
||||
```
|
||||
例如:
|
||||
```
|
||||
unalias ll
|
||||
```
|
||||
这样ll别名就会被删除
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "工具",
|
||||
"position": 5,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# nvm
|
||||
- Node.js是用于服务器端JavaScript运行,适合高性能、实时应用
|
||||
- NVM用于管理多个Node.js版本,便于在不同项目间切换
|
||||
|
||||
## 先决条件
|
||||
1. 确保安装了Ubuntu
|
||||
|
||||
## 安装NVM
|
||||
### 1. 安装cURL
|
||||
在wsl中,运行以下命令:`install`
|
||||
```
|
||||
sudo apt-get install curl
|
||||
```
|
||||
|
||||
### 2. 安装nvm
|
||||
通过curl安装nvm,运行以下命令
|
||||
```
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. 配置环境变量
|
||||
在`~/.bashrc`文件中配置以下内容:
|
||||
```
|
||||
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
|
||||
```
|
||||
|
||||
### 4. 验证nvm安装
|
||||
若要验证安装,输入以下命令:`command -v nvm`;如果安装成功则返回nvm,如果收到"找不到命令"或无响应,关闭当前终端,重新打开,然后重试。
|
||||
```
|
||||
command -v nvm
|
||||
```
|
||||
|
||||
### 5. 列出当前安装的Node版本
|
||||
查看当前安装的版本号,输入以下命令:`nvm ls`
|
||||
```
|
||||
nvm ls
|
||||
```
|
||||

|
||||
### 6. 安装Node.js(LTS)版本
|
||||
这里我选择安装当前稳定的LTS版本,安装输入以下命令:`install --lts`
|
||||
```
|
||||
nvm install --lts
|
||||
```
|
||||
|
||||
### 7. 验证Node.js安装
|
||||
查看当前安装的版本号,输入以下命令:`version`
|
||||
```
|
||||
node --version
|
||||
```
|
||||
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 78 KiB |
@@ -0,0 +1,97 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
# Git
|
||||
|
||||
git 是一个代码管理工具,可以追踪代码的提交记录。这是每个软件工程师必备工具,没有之一。
|
||||
|
||||
## 安装
|
||||
|
||||
工欲善其事,必先利其器。
|
||||
|
||||
<Tabs
|
||||
defaultValue="win"
|
||||
values={[
|
||||
{ label: "win", value: "win" },
|
||||
{ label: "ubuntu", value: "ubuntu" },
|
||||
{ label: "mac", value: "mac" },
|
||||
]}
|
||||
>
|
||||
<TabItem value="win">
|
||||
下载地址 https://git-scm.com/
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ubuntu">
|
||||
大部分linux系统都自带git,打开控制台输入 git --version 查看 git 版本
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="mac">
|
||||
mac系统自带git,打开控制台输入 git --version 查看 git 版本
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## 使用
|
||||
|
||||
通常一个项目会对应一个 git 仓库,每次提交代码都会记录到 git 仓库中,这样就可以追踪代码的提交记录。
|
||||
|
||||
用图形化的工具来看的话,会呈现出如下图
|
||||

|
||||
|
||||
### 克隆
|
||||
|
||||
克隆可以理解为将代码仓库复制了一份。
|
||||
|
||||
以此代码仓库为例,实际操作一下
|
||||
|
||||
```
|
||||
git clone https://github.com/idealjs/full-stack-tutorial.git
|
||||
```
|
||||
|
||||
后面的地址我们可以在 github 上看到,但是需要选用 https 的地址。
|
||||
|
||||
因为 ssh 地址需要做一些配置,所以先用 https 的地址克隆。
|
||||
|
||||
被克隆的仓库,我们通常叫他 **远程仓库**。或者源仓库。
|
||||
|
||||

|
||||
|
||||
### 拉取代码
|
||||
|
||||
刚克隆下的代码可能是最新的,但是过一段时间如果有人推送了新的提交到远程仓库,那么本地仓库如何同步远程仓库呢。
|
||||
|
||||
输入如下命令
|
||||
|
||||
```
|
||||
git pull
|
||||
```
|
||||
|
||||
### 推送代码
|
||||
|
||||
修改后的代码,想要共享给其他人,要如何做?
|
||||
|
||||
在 git 中,可以推送的东西只有修改记录。
|
||||
|
||||
而修改记录是不会因为文件被更改,就自动生成的,我们需要通过 git 工具把文件修改记录下来。
|
||||
|
||||
用如下命令把所有的修改都记录下。
|
||||
|
||||
```
|
||||
git add .
|
||||
```
|
||||
|
||||
然后提交到本地仓库
|
||||
|
||||
```
|
||||
git commit -m "test"
|
||||
```
|
||||
|
||||
最后把新的提交记录推送到远程仓库
|
||||
|
||||
```
|
||||
git push
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "Web基础",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "垃圾桶",
|
||||
"position": 5,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
# React 入门
|
||||
|
||||
学完了 1+1,我们可以开始学习微积分了。(🐶 保命)
|
||||
|
||||
## 安装 Node 环境
|
||||
|
||||
参考上一章
|
||||
|
||||
- [传送门](https://idealjs.github.io/full-stack-tutorial/docs/post-8#%E6%9C%AC%E5%9C%B0%E6%9E%84%E5%BB%BA%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
|
||||
|
||||
## 创建一个 React 工程
|
||||
|
||||
我们使用 create react app 手脚架快速创建工程,其中包含大量的工具,但是没有必要每个都了解。
|
||||
|
||||
1. 找一个空的文件夹,打开控制台(按住 shift,右键打开控制台),输入如下命令。
|
||||
|
||||
```
|
||||
npx create-react-app my-app
|
||||
```
|
||||
|
||||
视网络状况,可能需要 30s - 1min ,如果过久的话,建议不要等了。
|
||||
|
||||
2. 进入到项目文件夹中,启动项目
|
||||
|
||||
```
|
||||
cd my-app
|
||||
npm start
|
||||
```
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 信息时代
|
||||
|
||||
信息时代有很多获取信息的方式。
|
||||
|
||||
通过网页,或者特定的软件,或者其他的方式(非人类的获取方式比如:爬虫)。
|
||||
|
||||
网页需要通过一个特定软件才能打开(浏览器),之后人与浏览器交互,浏览器将信息传递给用户。
|
||||
|
||||
得益于浏览器跨平台的特性, 工程师们可以实现出只要一处编写,即可处处显示的软件 —— 是软件工程师们在影响世界 —— 这也是为什么信息时代是从网页开始的
|
||||
|
||||
## 网页的本质
|
||||
|
||||
网页本质是一个文档,文件,一段描述,一段文字。它被记录下来,由浏览器解析,并表达。
|
||||
|
||||
有点像是 DNA 是人的遗传信息,蛋白质是表达。 —— 最初的网页没有办法交互,只能显示字。(连颜色都没有,和蛋白质比起来弱爆了)
|
||||
|
||||
描述网页的语言不断更新,浏览器也不断的由工程师们更新。
|
||||
|
||||
目前使用最多的描述网页的语言是 HTML5
|
||||
|
||||
它看起来像是下面的代码块(实际还要复杂点)
|
||||
|
||||
```
|
||||
<div>
|
||||
我是一块
|
||||
<div>
|
||||
我是里面的一块
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
所以学会 HTML5 的规则,你就可以让浏览器写出具有简单排版的文字。
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# 现代的网页
|
||||
|
||||
现代的网页并不复杂 —— 不只是文字 —— 有漂亮的外观,可以响应用户的操作。
|
||||
|
||||
## 漂亮的外观(CSS3)
|
||||
|
||||
组成一个漂亮的外观,首先需要骨架 —— HTML5,然后是化妆 —— CSS3
|
||||
|
||||
HTML5 中有一些默认的规则,可以让文字变得有层级结构,像是 Word 中的标题,独占一行,并行显示。学会这些规则,就可以进行简单的排版了。
|
||||
|
||||
CSS3 像是 Word 样式。颜色,背景颜色,行间距。学会 CSS3 的规则,不仅可以让排版更炫酷,还可以做动画效果,以及各种特殊的交互效果。
|
||||
|
||||
> 学会 HTML5 + CSS 可以不用 Word 了呢。—— 只是编辑体验有点糟糕。所以我还是喜欢用 Markdown 编辑文档,还可以使用 HTML 增强
|
||||
|
||||
## 有趣的灵魂(JS)
|
||||
|
||||
有趣的灵魂应该是 200 多斤吧。—— 我是说我自己。
|
||||
|
||||
网页的作用不仅仅是展示,也会响应用户的操作。也可以根据不同的用户给出不同的响应 —— 动态网页。不能区分用户给出不同反应的,叫做静态网页
|
||||
|
||||
响应用户的操作,则需要软件工程师编写一些逻辑,编写这个逻辑的语言,叫做 JavaScript(简称 JS)。
|
||||
|
||||
### JS 在网页中如何运行
|
||||
|
||||
回到代码的本质,其实是在规则下描述一段事情。
|
||||
|
||||
浏览器中有一个用于解释执行 JS 的引擎。
|
||||
|
||||
在浏览器打开网页时,把各种 JS 脚本(文件形式的,或者文字形式的)丢给 JS 引擎,由引擎解释执行。
|
||||
|
||||
下面这个代码片段就是一个 Hello World
|
||||
|
||||
```
|
||||
<script>
|
||||
function sayHello() {
|
||||
alert("Hello World");
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onClick="sayHello()">点击<button>
|
||||
```
|
||||
|
||||
`<script></script>` 标签中的代码,就是 JS 代码。它定义了一个 sayHello 函数。
|
||||
|
||||
JS 引擎会记住这个函数。
|
||||
|
||||
`<button></button>` 是 H5 的一个标签,表示这里显示一个按钮。
|
||||
|
||||
`onClick="sayHello()"` 表示,这个按钮被点击时,会让 JS 引擎执行一段代码 —— `sayHello()`
|
||||
|
||||
## 下一节
|
||||
|
||||
下一节开始我们会完整的写一个 Hello World 网页。并开始 HTML5 CSS3 JS 的入门。
|
||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,43 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# HTML5 Hello World
|
||||
|
||||
在学习一样新技术的时候,写一个 Hello World 是最简单的。
|
||||
|
||||
用最少的知识量,让程序完整的跑起来,就是 Hello World 的目的。
|
||||
|
||||
本篇的完整代码,可以在这里找到:
|
||||
|
||||
- [examples/post-4/hello.html](https://github.com/idealjs/full-stack-tutorial/blob/main/examples/post-4/hello.html)
|
||||
|
||||
## 查看这个网页
|
||||
|
||||
查看这个 Hello World 很简单,只需要把这个 hello.html 文件下载到计算机。然后用浏览器打开就可以了。
|
||||
|
||||

|
||||
|
||||
## 简单分析代码
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>Hello World</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
通过上面的 Hello World 可以看出来一些 HTML5 的语法规则。
|
||||
|
||||
- 标签需要闭合 —— `<div/>` 或这样的 `<div></div>`
|
||||
- 标签有独特的含义 —— `<xxx></xxx>`, `<div></div>` 是 HTML5 的块标签
|
||||
|
||||
具体的标签规则,可以参考 [HTML5 标签](http://www.w3chtml.com/html5/tag/)。(实际工作中,用到的种类没有列出来的这么多)
|
||||
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,52 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# CSS3 快速入门
|
||||
|
||||
上一节,入门了 HTML5。了解了 HTML5 的 Hello World 后,我们可以开始学习 CSS3 了。
|
||||
|
||||
目标很简单,给 Hello World 加上一个颜色,并且再加一个背景色。
|
||||
|
||||
本篇的完整代码,可以在这里找到:
|
||||
|
||||
- [examples/post-5/hello.html](https://github.com/idealjs/full-stack-tutorial/blob/main/examples/post-5/hello.html)
|
||||
|
||||
## 查看这个网页
|
||||
|
||||
查看这个 Hello World 很简单,只需要把这个 hello.html 文件下载到计算机。然后用浏览器打开就可以了。
|
||||
|
||||

|
||||
|
||||
## 简单分析代码
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="color: red; background-color: green">hello world</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
和上一节有区别的地方在于
|
||||
|
||||
```
|
||||
<div style="color: red; background-color: green">hello world</div>
|
||||
```
|
||||
|
||||
多了一组 style 属性,`style="color: red; background-color: green"`
|
||||
|
||||
其中的 `color` `bacogound-color` 是 CSS3 的属性,`red` `green` 值。并且需要用 `;` 分隔。
|
||||
|
||||
可以参考下图片
|
||||
|
||||

|
||||
|
||||
这里我们只展示了 CSS3 的一种写法。未来为大家介绍更多的写法。
|
||||
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,63 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# JS Hello World
|
||||
|
||||
继续学习 Hello World。
|
||||
|
||||
Web 由 HTML5 + CSS3 + JS 构成。本节将介绍 JS 的 Hello World。
|
||||
|
||||
> 用最少的知识量,让程序完整的跑起来,就是 Hello World 的目的。
|
||||
|
||||
本篇的完整代码,可以在这里找到:
|
||||
|
||||
- [examples/post-6/hello.html](https://github.com/idealjs/full-stack-tutorial/blob/main/examples/post-6/hello.html)
|
||||
|
||||
## 查看这个网页
|
||||
|
||||
查看这个 Hello World 很简单,只需要把这个 hello.html 文件下载到计算机。然后用浏览器打开就可以了。
|
||||
|
||||

|
||||
|
||||
## 简单分析代码
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
<script>
|
||||
window.onload = () => {
|
||||
alert("hello world");
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
```
|
||||
|
||||
我们需要关注的是如下代码块,其余部分是 HTML5 的标签,想了解的话,可以查看[HTML5 Hello World](https://idealjs.github.io/full-stack-tutorial/docs/post-4)。
|
||||
|
||||
```html
|
||||
<script>
|
||||
window.onload = () => {
|
||||
alert("hello world");
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
形式上,被 `<script></script>` 包裹住的内容就是 JS 脚本。
|
||||
|
||||
这个脚本会在浏览器解析到这个标签时执行。
|
||||
|
||||
- `window.onload = xxx` 是在做一个赋值操作。
|
||||
|
||||
将一个函数赋值给 `onload` 属性。而浏览器在加载`hello.html` 文档结束时,会运行 `onload` 函数。
|
||||
|
||||
- `() => { alert("hello world"); }` 称作匿名的箭头函数,具体可以查阅 JS 文档。
|
||||
|
||||
- `alert("hello world");` 是 JS 调用了浏览器提供的函数 `alert` 其中参数,我们填入了 `"hello world"` 字符串
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# 模块和库
|
||||
|
||||
软件工程领域存在大量的模块和库,目的是为了更方便的维护软件。
|
||||
|
||||
在前端领域中,经过多年的实践,得出了 —— 构建的实践方式。
|
||||
|
||||
构建即,编写时采用 A 的方式,经过构建后得到 B 的产物。
|
||||
|
||||
前端的构建后产物依旧是 HTML + CSS + JS。
|
||||
|
||||
而编写时的方式有很多,比如比较流行的 Webpack(构建+打包)+ Typescript (JS 的超集)+ React/Vue
|
||||
|
||||
React/Vue 的组成比较复杂。也正是这些复杂的部分,推进了这些库的诞生。
|
||||
|
||||
用一句话来概括,当你需要一些可以减少开发量,减少维护难度的库时,可以采用 React/Vue
|
||||
|
After Width: | Height: | Size: 92 KiB |
@@ -0,0 +1,77 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
# Node 入门
|
||||
|
||||
在继续学习前端的库之前,我们需要打断一下。
|
||||
|
||||
我们需要一些补充知识做我们的手脚架。
|
||||
|
||||
前文提到过,现代化的前端工程通过构建的方式,得到我们需要的产物。
|
||||
|
||||
而构建怎么执行,执行在哪里也是一个复杂的问题。
|
||||
|
||||
## 构建如何执行
|
||||
|
||||
- 语言语法转换
|
||||
|
||||
如:typescript 转换为 javascript。高级语言特性转换为兼容语句。
|
||||
|
||||
- 资源打包
|
||||
|
||||
如:图片,样式,打包成文件资源。
|
||||
|
||||
## 构建的执行位置
|
||||
|
||||
- 人工执行
|
||||
简单的单机部署网站,我们可以使用人工部署的方式。
|
||||
|
||||
任选一台机器,进行构建,然后将构建产物复制到提供对外服务的服务器上。
|
||||
|
||||
- 自动执行
|
||||
|
||||
由特殊的构建软件监听,然后在配置好机器/容器中构建。
|
||||
|
||||
两种方案都需要一个机器,或者环境来构建。
|
||||
|
||||
接下来简单介绍本地环境的搭建
|
||||
|
||||
## 本地构建环境搭建
|
||||
|
||||
- 安装 Node
|
||||
|
||||
node 的版本很多,入门建议使用 官网的 LTS 版本。
|
||||
|
||||

|
||||
|
||||
<Tabs
|
||||
defaultValue="win"
|
||||
values={[
|
||||
{ label: "win", value: "win" },
|
||||
{ label: "linux", value: "linux" },
|
||||
{ label: "mac", value: "mac" },
|
||||
]}
|
||||
>
|
||||
<TabItem value="win">
|
||||
windows 就直接安装吧。(没错,下载,安装)。装完记得重启电脑,环境变量在重启后才生效。
|
||||
|
||||
https://nodejs.org/en/
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux">
|
||||
使用 nvm 安装和管理不同版本的 node
|
||||
|
||||
https://github.com/nvm-sh/nvm#install--update-script
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="mac">
|
||||
使用 nvm 安装和管理不同版本的 node
|
||||
|
||||
https://github.com/nvm-sh/nvm#install--update-script
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
# Hello Node JS
|
||||
|
||||
假如安装好了 Node,如何验证安装好了?或者我怎么使用它?
|
||||
|
||||
## 验证是否安装成功
|
||||
|
||||
打开一个控制台
|
||||
|
||||
<Tabs
|
||||
defaultValue="win"
|
||||
values={[
|
||||
{ label: "win", value: "win" },
|
||||
{ label: "ubuntu", value: "ubuntu" },
|
||||
{ label: "mac", value: "mac" },
|
||||
]}
|
||||
>
|
||||
<TabItem value="win">
|
||||
在开始菜单上右键,点击windows 终端(管理员)
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ubuntu">
|
||||
Ctrl+Alt+T
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="mac">
|
||||
找到terminal app,然后打开。
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
输入
|
||||
|
||||
```
|
||||
node -v
|
||||
```
|
||||
|
||||
然后你会看到你安装的 node 版本。
|
||||
|
||||
例如,我的版本
|
||||
|
||||
```
|
||||
v14.18.0
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
> 用最少的知识量,让程序完整的跑起来,就是 Hello World 的目的。
|
||||
|
||||
本篇的完整代码,可以在这里找到:
|
||||
|
||||
- [examples/post-9/hello.js](https://github.com/idealjs/full-stack-tutorial/blob/main/examples/post-9/hello.js)
|
||||
|
||||
在有 hello.js 的文件夹下打开控制台(在文件夹下按住 shift 鼠标右击),并且输入
|
||||
|
||||
```sh
|
||||
node hello.js
|
||||
```
|
||||
|
||||
如果碰到了如下错误,那么可能是当前文件夹下没有 hello.js 这个文件。
|
||||
|
||||
```
|
||||
internal/modules/cjs/loader.js:905
|
||||
throw err;
|
||||
^
|
||||
|
||||
Error: Cannot find module 'xxx/xxx/hello.js'
|
||||
```
|
||||
|
||||
正常运行的话,会显示如下
|
||||
|
||||
```
|
||||
hello world
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "快速开始 React",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 创建工程
|
||||
|
||||
使用 [Create React App](https://create-react-app.dev/docs/getting-started) 脚手架工具
|
||||
|
||||
创建工程
|
||||
|
||||
继续之前使用过的 hello_world 项目,输入命令
|
||||
|
||||
```
|
||||
npx create-react-app my-app
|
||||
```
|
||||
|
||||
> 受网络影响,这一步可能会等待较长时间。
|
||||
|
||||

|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 58 KiB |
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# 启动流程
|
||||
|
||||
React 的 App.js 和之前 hello_world 中的 index.html 有很大的不同
|
||||
|
||||

|
||||
|
||||
这是因为 React 会把 App.js 作为组件挂载到页面视图上
|
||||
|
||||

|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 启动项目
|
||||
|
||||
输入指令,切换到工程目录
|
||||
|
||||
```
|
||||
cd my-app
|
||||
```
|
||||
|
||||
输入指令,启动工程
|
||||
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 87 KiB |
@@ -0,0 +1,12 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# 快速实践
|
||||
|
||||
项目
|
||||
- 待办列表(Todo List)
|
||||
|
||||
## 待办列表
|
||||
|
||||
待办列表是一个经典的入门 App,通过待办列表可以学到 React 所提供的基础函数
|
||||
|
After Width: | Height: | Size: 145 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "快速开始",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 第一个页面(hello world)
|
||||
|
||||
```html title="hello-world/index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>hello world</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||

|
||||
|
||||
将文件在浏览器中打开,你将会看到 `hello world` 字样
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,17 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 简单的服务
|
||||
|
||||
打开控制台
|
||||
|
||||

|
||||
|
||||
输入命令
|
||||
|
||||
```
|
||||
npx http-server
|
||||
```
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 使用 VSCode
|
||||
|
||||
新建文件夹命名为 hello-world
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "安装工具-win",
|
||||
"position": 1,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 安装 nodejs
|
||||
|
||||
访问网站 https://nodejs.org/zh-cn/
|
||||
|
||||
点击下载长期维护版 并且安装
|
||||
|
||||
全默认选项安装
|
||||
|
||||
> 安装完成重启电脑,使环境变量生效。
|
||||
|
||||
## 为什么需要 nodejs
|
||||
1. nodejs 可以用来启动简单的 http 服务
|
||||
2. nodejs 可以用来构建模块化的工程
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 安装 vscode 编辑器
|
||||
|
||||
访问网站 https://code.visualstudio.com/
|
||||
|
||||
点击下载并且安装
|
||||
|
||||
## 下载速度慢
|
||||
|
||||
参考 https://zhuanlan.zhihu.com/p/112215618
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "更多",
|
||||
"position": 8,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# nodejs 与前端的关系
|
||||
|
||||
## nodejs 如何构建项目
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "更多示例",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||