MIt-web-lab

学习链接:
https://i5ting.github.io/wechat-dev-with-nodejs/nodejs/commonjs.html

前端

html

简单介绍


  • 往标签里添加属性
    • 链接
    • 图片 其标签内不需要有内容,src为相对当前目录的图片地址
    • alt 即使图片没法正确加载也能出现数字
  • list
  • div&span 把一堆标签组合到一起
    div 堆叠,span内联

查看HTML元素

课程链接

how to design website

ui

  • 一些有用的网站
  • 响应式设计:在各种设备上都很好看
  • 交互式设计:悬停变色或者有小表情

ux

用户体验设计:不同文化共同理解的符号,有特定意义的颜色
颜色比例:60,30,10
线框图:为网站画一个草图,figma

css

为浏览器增加样式

最上方是选择器
{}是属性
类也可以作为选择器

也可以用id

每个标签只能有一个id,但是一个类可以有多个id,一个标签也可以有多个类
优先级 id>类>elements]

1
2
3
4
5
:root{
    --primary:#396dff;
    --grey:#f7f7f7;
    --white:#ffffff;
}

在css文件使用变量,全局可用
在类用要用var包裹起来
css flex 弹性布局

  • u-inlineblock 适合水平排列子元素

JS

  • 加减乘除
  • 等于 ===
  • 变量 let vs const vs var
    • var最好不用,函数作用域
  • null undifined
  • console.log 打印
    • 模板字符串
  • 驼峰命名法
  • 数组 跟c很像,但是我们可以在一个数组里放任何喜欢的东西
    • pets.pop() pets.push(rabbish)
  • if else for while都跟c很像
  • for of
  • objects
  • 函数名称 (parameters) => {body}

JS进阶

  • 回调函数和数组操作
  • map
  • filter
  • concat 类似于push,但其创建一个包含新元素的新数组,符合state不可变数据的原则

React

模块化的框架用于构建前端

  • 组件Component 指导我们怎么渲染网站的某一部分,在每个组件内部可以自由的添加html,css和js,实现各种前端功能,组件就是js函数,使用jsx,可以嵌入html代码,使用{}在html嵌入js变量
    • App 总组件
      • NarBar
      • InfoBar
      • FeedBar

  • props 属性,给组件提供输入,props从父组件传递到子组件,子组件不能修改他们,也无法传递回父组件
  • state 状态,维护组件的状态
  • 比如一个评论的回复,我们用state在评论内维护回复的状态,如果状态为true,就去渲染回复子组件,将state传递给回复(props)进行渲染。
  • 在JSX中,我们使用classname,因为classs在js中已经是一个关键词
  • usetate hook 创建状态的语法:const [isLiked,setIsliked] = userState(false);
  • 如何传递props
  • like按钮的特殊处理
  • 状态,状态设置函数,将状态初始化为false
  • weblab.is/react-guide

react的生命周期

  • 不能直接修改状态,我们应该调用useState时定义的状态设置函数来修改状态
  • 状态应该存储在组件树的哪里
  • 当子组件之间的状态有联系时,我们要将该状态提升到公共父组件进行状态同步,通过props传递给子组件
  • 挂载 状态改变 渲染 提交 卸载
  • useState 改变状态,让组件重新渲染
  • useEffect(回调function,依赖数组(可选)) 允许我们在状态变化后执行某些函数,依赖数组中的状态改变,调用function,如果依赖数组为空,仅仅只在第一次渲染的时候调用函数
  • …persons 把数组展开,去掉包裹她的[ ]
  • JSX html硬编码 可以用{ } 插入元素
  • 条件渲染 利用三元运算符
  • 渲染数据数组 比如一个下拉菜单
    • 利用map(回调函数)将数组批量处理
    • 将数组整批映射成div标签包裹的代码,这里的key用于避免react进行不必要的渲染

react DOM

这是什么

dom是文档对象模型,展示或表示构成文档的模型
dom就是我们看到的网站或网页
react会维护自己的dom,区别于浏览器的实际dom,这是虚拟的
react从根组件递归的为每个组件生成dom

组件的生命周期
挂载->更新->卸载

挂载:加载虚拟dom
更新:更新已经存在的虚拟dom
卸载:组件从react虚拟dom移除

triggers:当你第一次渲染根组件(app);当某祖先组件被重新渲染;组件的某个状态发生变化,props发生变化,重新渲染
rendering:运行该组件的函数,将jsx组织生成Dom
committing:将react生成的虚拟dom与浏览器的真实dom进行比较,找出diff(差异点),修改那些差异,然后提交到浏览器

React useContext

让组件树的状态能够进行通信,子组件能获取到 高级组件的上下文信息

组件1的所有子组件都可以访问被UserContext包裹的state

react router

  • 导入包
  • 创建路由,基于组件内部的内容
  • 将路由渲染到文档里
    route tree

    app.jsx中outlet作用可以看成一个==占位符==,当访问Localhost:5173/profile时,回顺着组件app->profile(outlet替换而成)渲染,这样不管在哪个页面,顶部都是导航栏!超有启发
    将props传递给outlet useOutletContext

路由树是怎么被转换为路由的:/app/profile/..

动态路由

:name 路径的动态部分,将作为参数传递给 Profile组件

使用useParam在组件中获的name 参数

react 实操

  • 提交表单实操
  • react router
  • 导航栏,路由创建
  • app中用outlet自动生成
  • 在navtor导航栏中用链接
  • 创建一个空白的react app
    • npm create vite@latest![](../img/mit-web-lab/file-20250508230909083.png

react 文档

后端

  • http 请求和响应,https是http的加密版,第三方无法解读你和浏览器的通信内容
  • 请求目标及参数,http方法,请求头,请求体
  • 请求方法:get post put delete
    • get只从服务器拿数据
    • post提交数据到服务器
    • put 放置数据
    • delete 删除数据
  • url and query params
    • url请求目标 query params,查询参数
  • 请求头 请求体(放置发送的数据)
    • 请求头存储请求的所有元数据,请求体放置所有和Post请求相关的数据(比如你向youtube发送的视频)
    • get请求会将所有信息放在url里
  • 响应 浏览器的response
    • 404 资源不无法被找到
    • 400 错误的设置了查询参数
    • 500 服务器出现了错误
    • 200 请求成功
  • 响应头 不太重要
  • 响应体,包含我们从服务器请求的所有信息,以json格式返回

api

应用程序接口,我要试一下dog api

整体架构

在js中向api发起请求

  • 端点 好比房子和地址 /api/comment ->localhost:5713
    在js中传入端点和参数,它就会用这些查询参数请求端点
    get将这些参数放入url,post将这些参数放入请求体

Promise对象

get post函数返回的是promise对象,允许客户端在等待请求返回的时候进行其他操作,比如先渲染别的

  • then 在promise对象里使用.then,接受一个回调函数
  • .catch 如果get请求出错,catch会捕获错误

服务器与node.js

  • 后端框架 expressjs

  • node.js

    • npm node的包管理器
      • package.json 通过npm install 下载依赖,git推送的时候不会把下载到node_modules的包推送,每次拉取我们都要npm install 下载依赖
      • npm run dev 运行服务器
  • server文件将包含所有后端代码

创建第一个api

  • get端点
  • 在创建接口时我们该做点什么?middleware,在接收请求和发起响应间跑一些代码实现我们的功能
  • 添加中间件:
    • app.use,当你接受一个req后处理的函数,next代表下一个中间件函数
    • 记录时间
    • 错误中间件
  • catch all 端点 app.get(“ * ”) 会被所有没有明确定义的端点使用,类似于default:
  • 在express中,代码是从上到下顺序执行的,所以要在代码的最后定义全局捕获端点
  • npm start 启动后端服务

express 实战

https://www.freecodecamp.org/chinese/news/the-express-handbook/

  • const express = require(“express) 导入操作的不同语法,类似import
  • 创建app对象 const app=express()
  • 创建中间件函数
    • app.use(express.json()) 将请求体转换为json格式
  • 在url上设置api端点
  • 全局错误处理器
    • app.all 处理所有类型的请求方法
  • 服务器错误处理中间件必须放在所有注册路由和其他中间件之后,确保他能捕获到所有后续操作中的错误
  • 启动服务器监听3000端口

前后端结合:fetch api

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Fetch API 提供了一个 JavaScript 接口,用于发出 HTTP 请求和处理响应。
web lab 在utilties里封装了fetchapi 有get,post,返回一个promise对象用于前端使用

  • res req
  • 查询参数的使用
  • 前端
  • 后端 req.query 查询参数
  • 将一部分函数从Server.js移出
    • 在api.js中添加路由router,并导出
    • 在sever.js中导入router,并将其用中间件引用,并传入/api路径,表示任何/api都由这个路由器处理
  • 在app.js中,端点不需要再写/api
  • app变成了router,将api.js中的app.get等改成router.get

数据库

DBMS(mysql mongodb oracle等)

  • mongodb增删改查
    ==用类似json的文档形式存储数据的文档数据库==

    我们使用document database,存储对象,跟js的objects很像

  • 使数据库的存储具有容错性:将数据存储在云端,mongodb atlas,搞个副本

MongoDB

相比mysql,mongodb有更强的灵活性,它可以将json存储在数据库里,有很强的面向对象属性

  • mongoose 对象数据建模的js库,强制所有同类对象有共同的字段,有共同的文档结构
  • 将后端服务器和mongoDatabase链接 weblab.is/mongo
    • 接入云端数据库
    • 用mongoose创建story 和 comment模型
    • 在api.js导入story comment模型
    • 修改get请求,post请求
    • ok 这样就差不多了 Story.find({这里是req的查询参数})

同步 异步

在 JavaScript 中,​​Promise(承诺)​​ 是一种用于处理异步操作的对象,它代表一个尚未完成但预期会在未来完成(或失败)的操作。Promise 是解决传统回调地狱(Callback Hell)问题的现代方案,提供了更优雅的异步代码管理方式。
promise实现了异步,可以在等待回调函数完成时执行其他代码


.then会等待回调函数执行完毕

  • Promise.any 至少有一个Promise成功解析时,他就会成功解析

Async/Await

在写逻辑的时候,有些代码有先后执行顺序,比如我们需要先下订单,再发货

  • await 等待promise解析完成
  • await 和.then的比较
  • 何时使用异步函数,当后台有未知时间任务(获取数据,调用api,用await异步可以提升用户体验)

如何在团队协作的时候使用Git

学习网站Learn Git Branching

  • head指针指向目前显示的代码版本

  • 提交新代码 git commit -m < commit msg>

  • 分支管理 git branch 合并

  • 新建分支 git checkout -b < branch name>

  • git status 查看提交状态

  • git add -A 提交所有更改

  • git commit -m

  • 合并分支

  • git checkout main 切换回main分支

  • git merge < branch name> 合并main分支

  • 如果分支内容冲突?手动到编辑器修改冲突内容,选择要保留的部分再合并

  • remote + local branch

    • 将local branch 和 remote branch对应
    • git push -set-uptream < branch name>
    • 再次git push就push到远程的对应分支
  • merge a local + remote branch

    • 本地切换到main分支,合并其他分支
    • git push 时,发现远程仓库有一些本地没有的内容,被拦下
    • git fetch 查看远程仓库的状态,检查发生了什么,更新本地的内容与匹配
    • git pull拉取远程仓库,合并分支,推送 git pull origin main 将远程main分支上的任何新更改拉取到我们的分支
    • git branch -d 删除本地分支
  • git stash 将编辑器中尚未保存的内容全部暂存起来,切换分支的时候就不会导致文件丢失

  • git stash pop 将更改还原

身份认证

存储密码非常困难,用google的比较现成

sessions token
sessions 服务器有一个全局会话查找表,存储用户的全部信息,表中有sessions id 对应用户的所有信息

服务器以响应的形式发送唯一的sessions id到用户,
用户以cookie的形式,发送sessions id到服务器,服务器会根据sessions id发送相应的该用户特定的会话响应

  • 为什么sessions可以解决登录的问题
    因为用户只获得了sessions id,所有的用户信息都有服务器安全的存储,用户端只有cookie哈

  • 如果有多个服务器呢?怎么解决不同的全局查找表的问题?会话会缺失拓展性

使用token,token无法被伪造,只有服务器可以解密token
用户会提交登录表单(post,api登录端点等),服务器接受表单并为客户端生成一个唯一的json webtoken对象,客户端存储token在本地,后续访问服务器时,服务器会对其进行解密并在后续进行验证;token会携带用户的凭证;
token不存在可拓展性的问题,服务器本身不需要存储任何用户信息,token在用户本地存储

cookie让我们保持登录状态,我们登录后由服务器生成,cookie在response的set-cookie里,再次登录时,一般发送cookie回去

auth实战,

  • 使用google进行认证,google会为用户生成一个token,用户将把这个token发送给服务器进行解密,如果token有效,服务器产生sessions保持用户的登录状态
  • 服务器通过google-auth-library.js库验证token

-获取 google client id 使用后端服务器进行身份验证  |  Authentication  |  Google for Developers

  • 使用条件渲染实现login logout按钮的转换
  • 修改后端:数据库模型user.js
  • 新增auth.js 一旦用户登录,就用express.js新建会话,保持用户登录状态
  • 怎么讲前端新增的google登录按钮传回的token一路传到后端,在服务器中定义一个新的端点,前端可以对此发起一个post请求,告诉后端我们的操作是什么
  • 借助两个post路由,登录,登出