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
- 一些有用的网站
- https://coolors.co/ 配色方案
- www.webdesignmuseum.org
- abobe fonts 字体
- react-icons 图标
- ui 组件库:Mantine
- 响应式设计:在各种设备上都很好看
- 交互式设计:悬停变色或者有小表情
ux
用户体验设计:不同文化共同理解的符号,有特定意义的颜色
颜色比例:60,30,10
线框图:为网站画一个草图,figma
css
为浏览器增加样式
最上方是选择器
{}是属性
类也可以作为选择器
也可以用id
每个标签只能有一个id,但是一个类可以有多个id,一个标签也可以有多个类
优先级 id>类>elements]
- 选择字体的网站
https://fonts.google.com/ - css变量
1 |
|
在css文件使用变量,全局可用
在类用要用var包裹起来
css flex 弹性布局
- u-inlineblock 适合水平排列子元素
JS
- 加减乘除
- 等于 ===
- 变量 let vs const vs var
- var最好不用,函数作用域
- null undifined
- console.log 打印
- 模板字符串
- 模板字符串
- 驼峰命名法
- 数组 跟c很像,但是我们可以在一个数组里放任何喜欢的东西
- pets.pop() pets.push(rabbish)
- 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
- App 总组件
- 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
- 请求头存储请求的所有元数据,请求体放置所有和Post请求相关的数据(比如你向youtube发送的视频)
- get请求会将所有信息放在url里
- 请求头存储请求的所有元数据,请求体放置所有和Post请求相关的数据(比如你向youtube发送的视频)
- 响应 浏览器的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 运行服务器
- npm node的包管理器
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 处理所有类型的请求方法
- 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都由这个路由器处理
- 在api.js中添加路由router,并导出
- 在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路由,登录,登出