跳到主要内容

开发环境配置

· 阅读需 3 分钟
Yana Ching
Front End Engineer

记录一下新设备重新配置开发环境

办公软件安装

  • 语雀
  • typora markdown 编辑器
  • google chrome 浏览器
  • snipaste 截图工具
  • 百度网盘
  • 钉钉
  • Visual Studio Code
  • sublime
  • Git

环境安装

安装 node(会同时下载 npm)

终端中判断是否安装成功

node -v
安装完毕之后需要配置一下 VSCode 中的终端默认使用 Git bash
{
"terminal.integrated.defaultProfile.windows": "Git Bash"
}

下载 yarn (我更习惯使用 yarn,如果不需要,可省略此步骤)

npm install -g yarn
主要是针对 powershell 终端的一些配置情况,如果是直接使用 git 的 bash 终端使用的话,可忽略以下内容

安装过程中遇到了 npm 要求更新的情况

>>
added 1 package in 3s
npm notice
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.5.1
npm notice Run npm install -g npm@10.5.1 to update!
npm notice

npm install -g npm@10.5.1 更新完毕之后重新执行安装 yarn 的操作,又遇到了 powershell 的执行策略限制

yarn : 无法加载文件 E:\Develop\node-v18.20.1-win-x64\yarn.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
所在位置 行:1 字符: 1
+ ~~~~
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess

因此需要手动解除一下 powershell 的限制,安装完毕之后需要重新恢复该执行策略

  1. 启动 powershell,执行以下命令(必须使用管理员身份启动)

    Set-ExecutionPolicy Unrestricted
  2. 使用完毕可以选择恢复默认的执行策略

    Set-ExecutionPolicy Restricted

nvm node 管理工具

直接访问 nvm 的 github 仓库下载即可判断是否安装成功

nvm -v

一些常用命令:

nvm list # 查看所有 node-npm 版本
nvm list available # 查看所有可用的 node 版本
nvm use xxx # 切换某个版本
nvm install xx # 安装某个版本
nvm uninstall xxx # 卸载某个版本
nvm alias default xxxx # 设置某个版本为默认版本

github 配置

  1. 本地生成 SSH 密钥对

    ssh-keygen -t rsa -b 4096 -C "your.email@example.com<这里换成你的邮箱,不需要引号>"
  2. 生成完毕之后,定位到该目标文件夹中

    cd ~
    cd .ssh
  3. 查看生成的 id_rsa.pub(默认是这个名称,如果你设置了文件名,那就是 xxx.pub)

    cat xxx.pub

面试复盘

· 阅读需 7 分钟
Yana Ching
Front End Engineer

summary

vue3 相关与 JS 原生

基本类型

number string boolean symbol undefined null

箭头函数与普通函数

this 指向

普通 - 根据运行时函数调用方式动态决定箭头 - 没有自己的 this,捕获上下文,不可改变

arguments 对象

普通 - 可使用 arguments 获取所有传入参数箭头 - 没有 arguments,但是可通过 ...args 获取所有传入参数

prototype 属性

普通 - 创建时自动拥有一个 prototype 属性箭头 - 没有 prototype 属性,无法创建对象的原型链

事件循环

浏览器环境中事件循环有以下阶段:

  • 同步任务执行阶段
  • 消息队列检查阶段(先进先出)
  • 微任务执行阶段
  • 渲染阶段
提示

常见微任务:

  • Promise.then
  • MutationObserver
  • Proxy
  • process.nextTick(Node)

常见宏任务

  • script
  • setTimeout/setInterval
  • UI rendering
  • postMessage、postChannel
  • setImmediate、I/O
执行机制是:
  • 执行宏任务
  • 遇到微任务,微任务入队列,完成宏任务之后依次执行微任务(FIFO)
直接执行 await 这一行中的同步代码,下一行之后的代码全部阻塞,进入微任务队列 **await 一定会阻塞 await 下一行之后的

代码**,将 await 下面的代码全部看作 Promise.then 即可,直接加入微任务队列,继续执行同步代码

正常情况 await 后就是一个 Promise,如果不是 Promise,相当于一个 return 语句,直接返回

(()=>{
try(){
new Promise(res=>{
const a = 1
console.log(a)
a = 2
console.log(a)
})
}catch(err){
console.log(3)
}
})()
注意 try-catch 只能捕捉同步代码中的 error 异步代码中错误由 Promise.reject(xxx) 来对外暴露错误信息

这里会打印出 1 之后直接报错 TypeError,常量不可以二次赋值触发 catch 中的逻辑,打印 3

所以结果是 1, 抛出异常

数组方法与异步操作

使用数组的方法的时候注意不要在循环提内部执行异步操作

  • forEach
  • filter
  • map
  • every
  • some

此时循环体内部的同步代码是不会被异常操作打断的,所以执行的代码会打印出很多个循环结束时候的结果,与预期的效果有出入

提示

如果是多个对象需要执行异步操作,建议使用 for-of 来循环对象内部的值,或者使用 Promise.all 方法来操作 :::

try-catch

只捕获同步代码错误,异步代码错误需要依靠 Promise 中的 reject 来对外暴露错误信息

em\rem\vh\vh\px

  • em 相对于父元素的 font-size
  • rem 先对于 html 元素的 font-size
  • vh、vw 是相对于视口的比例
  • px 是绝对单位

数组方法

  • push 栈方法
  • unshift 队列方法
  • splice 粘合
  • concat 拼贴 ----- 该方法不改变原数组,其他的改变

  • pop 栈推出
  • shift 队列出队
  • splice 第二个参数决定删除多少个
  • slice 切割数组 ----- 不改变原数组,其他改变

splice 第三个参数之后可以在原数组中插入新元素

  • indexOf 查元素的 pos
  • includes 判断是否在
  • find 寻找匹配的元素

排序

  • reserve 反转
  • sort 排序

ts 中 type 与 interface 的区别

  • type 不能重复定义,报错,复合、交叉、联合、函数类型
  • interface 可以重复定义,对象结构扩展

js 中的加法

0.1 + 0.2 约等于 0.3 (永远不会等于 3) ::: tip 会转换成位运算 :::

flex 简写

提示

放大、缩小、初始比例

flex: flex-grow, flex-shrink, flex-basis :::

会引起重排的属性

visible background-color font-size

TS 属性区别

for-in 与 for-of

  • for-in 遍历的是对象中的属性,数组中就是下标,对象中就是属性
  • for-of 遍历的是对象中的值,数组中就是元素,对象中就是属性值

vue3 的响应式

vue3 中的响应式只针对最外层对象进行处理 :::

因此如果 ref 与 reactive 中存在对象嵌套的情况,应该先获取对应的属性,再去求得相应的值

const a1 = ref(1)
const a2 = reactive(a1)
const a3 = reactive([a1])
const a4 = reactive({ key: a1 })

a1.value
a2.value
a3[0].value
a4['key'].value

在以上的情况中,会打印出 1 1 undefined undefined

后面两个若是想要正常显示,需要先获取 a3[0], a4['key'] 求得其 ref 对象才能获取后续的值,否则只会打印 undefined

vue3 概念

  • ref 创建的是具有 value 属性的基础类型数据
  • reactive 是基于 Proxy 的响应式
  • toRefs() 是将响应式转换为普通对象(该问题在上一问中有涉及)
  • markRaw() 标记对象不可代理 ---- 大致理解为 node_modules 中的依赖排除,因为三方的库已经自己做类型检查了
  • readonly 为只读代理,本质是不允许修改变量的堆地址,不关注对象内部的属性、属性值变化,属性、属性值变化由 Proxy 来监控

博客迁移

· 阅读需 4 分钟
Yana Ching
Front End Engineer

博客迁移

从 hexo 博客转移到 docusaurus 上

docusarus 环境要求

  • node 18+ (可以安装 nvm 管理多个 node 的切换)

安装 docusaurus

npx create-docusaurus@latest your-blog-project-name classic
提示

your-blog-project-name 必须 定义为你的 github 名称

主要是为后续的 github 静态博客

e.g.: xxxx.github.io

docusaurus 项目结构

  • blog 存放博客文章,默认会展示最新的几条博客
  • docs 可以存放文档
  • src 主要是针对博客本身做一些自定义操作
    • css 样式文件
    • pages 自定义页面
      • style.module.css 页面对应的样式文件
      • index.js 页面文件
  • static 静态资源
    • img 图片
  • docusaurus.config.js 配置文件(在这里可配置博客的一些基础信息)
  • package.json 项目相关的一些三方依赖信息
  • README.md 可以再此处补充你的项目信息
  • sidebars.js 这里可以配置博客页面的侧边菜单信息(可以做一些超链接跳转)

安装依赖

npm install

本地启动

npm run start

手动构建

npm run build

github 仓库 CI/CD 设置推送代码自动更新博客

配置 github 账户 ACCESS_TOKEN 为后续做准备

image-20240419105518873

image-20240419105600540

image-20240419105716045

image-20240419105804542

image-20240419105844236

image-20240419110010077

image-20240419110030472

image-20240419110227836

image-20240419110906240

创建一个 workflow 来自动构建脚本

image-20240419111030182

image-20240419111057657

image-20240419111113464

拷贝脚本到 workflow 文件中

脚本文件

name: Deploy Docusaurus Blog to GitHub Pages # 本次操作的名称定义

on:
push:
branches:
- master # 可以根据实际情况修改分支名称(监听该分支的更新,因此只有更新该分支才会触发自动部署)

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up Node.js # 安装 node 环境
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install dependencies # 下载依赖
run: yarn

- name: Build static files # 打包
run: yarn build

- name: Deploy to GitHub Pages # 发布到 gh-pages 分支
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.ACCESS_TOKEN }} # 这个 ACCESS_TOKEN需要在 github 账户中去配置
publish_dir: build
user_name: yanadev
user_email: 1245485816@qq.com
commit_message: 'Deploy Docusaurus blog to GitHub Pages'

image-20240419111238258

创建 gh-pages 分支支持自动化部署

image-20240419112337271

image-20240419112446608

image-20240419112536045

提示

至此,github 仓库的配置已经完成了

可以在本地做一些修改,推送到 main 分支检查是否能够正常更新(如果你在脚本中监听的是别的分支,那这里只要更新那个分支就可以 触发自动化部署 )

一些自定义使用的 api

useDocusaurusContext 站点的配置信息

  • siteConfig 可以访问 docusaurus.config.js 中的 title 、tagline 等字段信息
  • 对于 docusaurus.config.js 中不支持的字段,使用 customFields 自定义你需要的属性
import React from 'react'
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'

const Hello = () => {
const { siteConfig } = useDocusaurusContext()
const { title, tagline } = siteConfig

return <div>{`${title} · ${tagline}`}</div>
}

shopify/cli 使用

· 阅读需 4 分钟
Yana Ching
Front End Engineer

首次登录


shopify theme dev --store <your-store-name>

eg: shopify theme dev --store xxx.myshopify.com

随后就会打开一个网页链接,要求你登陆账号,才能继续后续操作登录成功之后,会在控制台显示当前状态 logged in 可以 ctrl+c 推出当前进程

切换店铺账号操作

如果需要在账户之间切换,可先注销当前用户之后,再重新登录

shopify auth logout

查看当前登陆账号信息

shopify theme info
## 执行该命令会列出你当前登录的店铺信息
$ shopify theme info
THEME CONFIGURATION
Store na2demo.myshopify.com
Development Theme ID Not set

TOOLING AND SYSTEM
Shopify CLI 3.58.2
OS windows-amd64
Shell E:\develop\Git\usr\bin\bash.exe
Node version v18.20.1
Ruby version 3.2.3

theme 常用命令

shopify theme dev 本地预览(热更新)
shopify theme check 分析 code 是否有误
shopify theme list 列出所有主题
shopify theme open 返回线上可预览的链接
shopify theme pull 拉取主题
shopify theme push 上传主题覆盖原主题
shopify theme share 上传主题(以新主题的形式上传)
shopify theme publish 发布主题
shopify theme package 将本地主题打包成可上传的 zip 格式
shopify theme delete 从商店中删除主题
shopify theme info 查看本地主题的运行环境

一个小案例

# 退出登录 如果已经登录了账户,需要切换(可选)
shopify auth logout

# 登录账户
shopify dev --store <your-store-name>

# 主题拉取:执行之后会出出先一个theme列表让你选择,你可以选择想要拉取的主题
## 会在当前的执行目录中,直接存放拉取来的代码
shopify theme pull

# 本地运行预览
shopify theme dev

# 开发完毕之后,可以执行查看线上的预览链接
shopify theme open

# 如果不想覆盖当前的主题,想要重新创建一个主题副本(新主题)
shopify theme share

# 更新覆盖主题
shopify theme push

至此 theme 项目已经可以在本地运行了

git 存储

# 初始化 git
git init

# 在 github 上创建新的仓库
# 获取仓库地址之后连接远程仓库
git remote add origin <your-github-repo-address>

# 本地提交代码、合并分支
git add .
git commit -m 'init: init project'

# your-branch-name 换成你在编辑的分支名称
git pull origin <your-branch-name>

# 拉取远程分支
git pull --allow-unrelated-histories origin <your-branch-name>

# 合并之后重新 commit 一下,提交代码
git commit -m 'update: merge'
git push origin <your-branch-name>

Sentry 接入飞书通知

· 阅读需 3 分钟
Yana Ching
Front End Engineer

概览

总共分三个步骤:

  1. 通过飞书机器人助手设置 webhook 触发器,发起一个 HTTP 请求,触发群组机器人群内消息通知
  2. 启动 sentry webhook 通知,并设置对应 webhook 地址为 飞书触发器的 webhook 地址
  3. 设置 sentry alert 信息,开启消息通知到 webhook,因为 sentry 类型限制,默认设置下,同类型的预警 5 分钟内不通知,仅显 示在后台

创建飞书机器人指令

image-20230731085551205

image-20230731085703969

image-20230731085818226

image-20230731090017719

设置并获取指令 webhook 地址(该 webhook 地址用于 sentry 后台 webhook 设置)

image-20230731090045453

将以下 JSON 填写到 触发器 JSON 中,暴露 sentry 传递的对象变量给下游的操作 :::
{
"event": {
"exception": {
"values": [
{
"stacktrace": {
"frames": []
}
}
]
},
"type": "Error",
"title": "Event Title",
"user": {
"data": {
"time": "",
"environment": ""
}
}
},
"level": "error",
"project": "payssion-dashboard-frontend",
"url": ""
}

image-20230731090703960

复制该 webhook 地址并保存 :::

image-20230731090828006

sentry 后台:启动项目 webhook 通知,并将上面获得的 webhook 地址设置到对应的 webhook 设置中

image-20230731091306780

image-20230731091211422

image-20230731091533486

image-20230731091712665

开启后台 webhook 警告,新增警报规则开启 webhook 通知

image-20230731091829942

image-20230731091942331

image-20230731092052935

image-20230731092332504

image-20230731092401679

image-20230731092421356

image-20230731092537243

设置飞书机器人指令发起 HTTP 请求通知群组机器人

image-20230731092756326

image-20230731092816374

image-20230731092941230

在请求体中输入一下 JSON,并手动替换其中的变量
  • event.user.data.time
  • project
  • event.type
  • event.tile
  • event.exception.values[0].stacktrace.frames
  • event.user.data.environment
  • url :::
{
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "event.user.data.time 【 project 】异常通知:",
"content": [
[
{
"tag": "text",
"text": "【 event.type 】event.tile"
}
],
[
{
"tag": "text",
"text": "event.exception.values[0].stacktrace.frames"
}
],
[
{
"tag": "text",
"text": "【环境】:"
},
{
"tag": "text",
"text": "event.user.data.environment"
}
],
[
{
"tag": "text",
"text": "【操作】:"
},
{
"tag": "a",
"text": "查看详情",
"href": "url"
}
]
]
}
}
}
}

image-20230731093912749

Sentry监控方案

· 阅读需 4 分钟
Yana Ching
Front End Engineer

开始

  1. 注册 sentry

  2. 点击 Qucik Start 快捷创建项目,选择项目对应的前端框架项目所属的团队

  3. 新建完毕根据 Configure SDK 指引,在项目中做引入

    • Install 安装依赖(React)

      # Using yarn
      yarn add @sentry/react

      # Using npm
      npm install --save @sentry/react
    • Configure

      import { createRoot } React from "react-dom/client";
      import React from "react";
      import * as Sentry from "@sentry/react";
      import App from "./App";

      Sentry.init({
      dsn: "https://******.ingest.sentry.io/******",
      integrations: [new Sentry.BrowserTracing(), new Sentry.Replay()],
      // Performance Monitoring
      tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
      // Session Replay
      replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
      replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
      });

      const container = document.getElementById("app");
      const root = createRoot(container);
      root.render(<App />)
    • Verify(代码中手动创造一个 error)

      return <button onClick={() => methodDoesNotExist()}>Break the world</button>;
    • Next Steps

      • Source Maps: Learn how to enable readable stack traces in your Sentry errors.
      • React Features: Learn about our first class integration with the React framework.

数据上报

前端常见方案

  1. 代码埋点:开发自行定义
  2. 可视化埋点:第三方方案,通过配置,对 UI 通用类的元素进行设置
  3. 无痕埋点:通过嵌入 SDK,来监控前端页面或者 http 请求的数据埋点
-代码埋点可视化埋点无痕埋点
方式手动开发可视化圈选嵌入 SDK
数据自定义
更新需要更新配置更新无需更新
成本+++++++
场景高度自定义UI 通用数据生命周期数据埋点

一般情况下,通过与后台约定好具体的数据格式,前端在埋点采集的时候自动转换成接口需要的数据格式进行本地存储,然后进行上报

实际项目中,在用户点击的时候记录用户信息及功能模块,传给后台

有效的数据埋点,既可用于单用户的链路操作的追踪,也可用于整体用户数据的统计,针对这些数据做相应的调整 :::

用户日志自动化埋点

通常用来定位用户问题时使用,通常需要提前在代码中打印日志,通过全局代理、装饰器处理关键模块和方法等方式来进行日志的自动打 印

react 项目接入

Sentry 注册与配置

注册账号

点击该链接注册 sentry 账号

登录账号并创建项目

  • 新建项目

    • platform:REACT

    • ProjectName: xxxxxx-dashboard-frontend

image-20230724165950360

image-20230724170225046

获取项目 DSN (SENTRY_DSN)

项目 >>> 设置 >>> 客户端密钥(DSN)

image-20230724172719562

获取项目 ORG(SENTRY_ORG)

头像 >>> 组织设置 >>> Organization Slug

image-20230724172939062

SENTRY_RELEASE_VERSION:v1.0.1(源码版本号:可自行维护)

生成 API_AUTH_TOKEN 定位线上源码(SENTRY_AUTH_TOKEN)

确保选中以下权限:

event:admin、event:read、member:read、org:read、project:read、project:releases、team:read、alerts:write、alerts:read、event:write、project:write

image-20230724171927879

image-20230724172015104

image-20230724172212397

获取以上 key 之后,可修改项目根目录下 .env 文件

SENTRY_DSN='******'

SENTRY_AUTH_TOKEN='*********'

SENTRY_RELEASE_VERSION='v1.0.1'

SENTRY_ORG='payssion',

SENTRY_PROJECT='payssion-dashboard-frontend',

Sentry 配置 webhook 通知

提示
  • 设置 >>> 项目 >>> 选择刚才创建的项目payssion-dashboard-frontend
  • 滚动到页面最下方,选择集成方式,启动 webhook
  • 同路径下,点击 WebHooks,粘贴飞书触发器 webhook 地址 :https://www.feishu.cn/flow/api/trigger-webhook/8eaa13786b44a6d07e057f6223737be9

image-20230724170454928

image-20230724170929401

image-20230724171317582

image-20230724171729998

B端 - 弹窗设计

· 阅读需 3 分钟
Yana Ching
Front End Engineer

弹窗

中断用户操作,对当前操作进行强制反馈的交互形式

分类

  • 模态弹窗
    • 需要做出对应交互,,模态才会消失
    • 对话弹窗、内嵌表单弹窗、分布表单弹窗、文件选择弹窗、复杂信息展示
  • 非模态弹窗
    • 不打扰用户,短暂停留
    • 通知提醒、全局提示、警告提示、气泡卡片、文字提示

做一个思维导图总结

结构拆解

  • 模态层
  • 关闭入口
  • 弹窗主体

模态层

颜色

B端设计指南04 —— 弹窗 究竟应该如何设计

多层级
避免多层级
  • 流程优化

检查流程是否足够精准,可否通过精简流程,减少不必要的多层模态的使用

  • 内容量优化

内容量较少的时候,可以采取下拉菜单进行优化,解决多层模态层叠加的问题

  • 弹窗形式选择

当涉及到很多交互时,不建议直接使用弹窗

处理多层模态

整体注意:

  • 多层模态超过两层,最好展示固定的遮罩颜色

  • 模态过多时,给出最大值,如超过 3 层只展示固定颜色即可

如何选择弹窗、抽屉、新建页

  • 页面内容量

内容量维度:新建页 > 抽屉页 > 弹窗

深度较深(长度较长):抽屉形式最佳

宽度较宽:弹窗形式更合理

深度深且宽度宽:新建页面更合适

  • 页面连贯性

抽屉 < 弹窗 < 新建页

  • 页面切换成本

当一个二级页面使用频率过高,即用户需要在 AB 页面之间来回切换,此时需要考虑 切换成本

ESLint语法规则

· 阅读需 1 分钟
Yana Ching
Front End Engineer

ESLint 的规则有三种级别

  • “off”或者 0: 不启用这个规则
  • “warn”或者 1: 出现问题会有警告
  • “error”或者 2: 出现问题会报错

eslint 文件修改了一定要重新手动编译运行。

修改 ESLint 空格检测

修改 .eslintrc.js 文件,一定要编译运行,ctrl+c停止,npm run serve重新编译

 'no-irregular-whitespace' : 'off'//这禁止掉 空格报错检查

没必要的返回语句

Unnecessary return statement no-useless-return

login() {
// console.log(this)登陆时候的预校验。
this.$refs.loginFormRef.validate(valid => {
if (!valid) return
})
}
// ========= 修改 ============
login() {
// console.log(this)登陆时候的预校验。
this.$refs.loginFormRef.validate(valid => {
if (!valid) return false
})
}

HTTP - GET 与 POST

· 阅读需 4 分钟
Yana Ching
Front End Engineer

汇总 post

GETPOST
后退按钮/刷新无害数据会被重新提交(浏览器应该改制用户数据会被重新提交)
书签可收藏为书签不可收藏为书签
缓存能被缓存不能缓存
编码类型application/x-www-form-urlencodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码
历史参数保存在浏览器历史中参数不会保存在浏览器历史中
数据长度有限制,URL 的最大长度时 2048 个字符无限制
数据类型只允许 ASCII 字符无限制,也允许二进制数据
安全性与 POST 相比,GET 安全性较差,因为发送的的数据是 URL 的一部分。发送密码或其他敏感信息时不要使用 GET !数据不会显示在 URL 中
可见性数据在 URL 中对所有人都是可见的数据不会显示在 URL 中

应用场景中的区别

GET 参数通过 URL 传递,POST 放在 Request Body(请求体)

URL 中传送的参数是有长度限制的,而 Request Body 没有(浏览器对 URL 长度有限制,并不是 http 协议对 get 请求参数的限 制

GET 比 POST 更不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息

GET 请求参数会被完整的保留在浏览器的历史记录里,而 POST 中的参数不会被保留

GET 请求只能进行 url 编码,而 POST 支持多种编码方式

GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置

GET 请求产生的 URL 地址可以被 bookmark(书签:登记 url),而 POST 不可以

GET 在浏览器 回退/刷新 时是无害的,而 POST 会再次提交请求

本质

两者并无区别,都是 HTTP 协议中发送请求的方法

HTTP 是基于 TCP/IP 的关于数据如何在万维网中通信的协议,底层是 TCP/IP,即 GET/POST 都是 TCP 链接

GET 请求也可以带 request body ,但不能保证一定被接收到(服务器处理方式不同);同样,POST 请求也可以在 URL 地址中传参数

GET 请求产生一个 TCP 数据包;POST 请求产生两个 TCP 数据包 :::

GET 请求:浏览器会把 HttpHeader 和 data 一并发出,服务器响应 200 (返回数据)

POST 请求:浏览器先发送 header ,服务器响应 100continue,再发送 data,服务器响应 200 ok(返回数据)

总结

  1. GET 与 POST 都有自己的语义,不能随便混用

  2. 网络环境好的时候:发一次包的时间和发两次包的时间 差别 基本可以无视;

    网络环境查的时候,发两次 TCP 在验证数据包完整性上,有非常大的优点。

  3. 并不是所有浏览器都会在 POST 中发送两次包,Firefox 就之发送一次

参考博文

econ项目数据库表

· 阅读需 5 分钟
Yana Ching
Front End Engineer

相册表(albums)

用于记录相册信息

字段描述备注
id🔑 主键
slugURL 别名
title相册标题
feature特色图像图片 URL 路径
description相册简介
created创建时间
views浏览次数
likes点赞数
status状态草稿(drafted)/ 已发布(published)/ 回收站(trashed)
user_id🔗 用户 ID当前文章的作者 ID

收藏表(collections)

用于记录用户收藏作品信息

字段描述备注
id🔑 主键
post_id🔗 作品 ID收藏作品 ID
user_id🔗 用户 ID收藏者 ID
created创建时间第一次收藏时间
status收藏状态0 - uncollect ;1 - collect

点赞表(likes)

用于记录用户点赞作品信息

字段描述备注
id🔑 主键
post_id🔗 作品 ID点赞的作品 ID
user_id🔗 用户 ID点赞者 ID
created创建时间点赞状态创建时间
status点赞状态0 - dislike;1 - like

浏览表(views)

用于记录用户浏览作品信息

字段描述备注
id🔑 主键
post_id🔗 作品 ID浏览的作品 ID
user_id🔗 用户 ID浏览者 ID
created创建时间浏览时间
status浏览状态发布(published)/ 回收站(trashed)

用户表(users)

用于记录用户信息

字段描述备注
id🔑 主键
slugURL 别名
email邮箱亦做登录名
password密码
nickname昵称
avatar头像图片 URL 路径
bio简介&nbsp;
status状态未激活(unactivated)/ 激活(activated)/ 禁止(forbidden)/ 回收站(trashed)
feature背景图片图片 URL 路径
fans粉丝数
follows关注数

作品表(posts)

用于记录作品信息

字段描述备注
id🔑 主键
slugURL 别名
title作品标题
feature特色图像图片 URL 路径 (图文封面 / 单图内容)
type作品类型图片(photo)/ 图文(article),默认图片
description作品简介
created创建时间
content内容如果 type = "photo",该字段为 null
views浏览次数
likes点赞数
collects收藏数
status状态草稿(drafted)/ 已发布(published)/ 回收站(trashed)
album_id🔗 相册 ID当前作品的相册 ID(图文默认为 null )
user_id🔗 用户 ID当前作品的作者 ID
category_id🔗 分类 ID当前作品的分类 ID

评论表(comments)

用于记录作品评论信息

字段描述备注
id🔑 主键
authors作者
email邮箱
created创建时间
content内容
status状态待审核(held)/ 准许(approved)/ 拒绝(rejected)/ 回收站(trashed)
post_id🔗 作品 ID
parent_id🔗 父级 ID

分类表(categories)

用于记录作品分类信息

字段描述备注
id🔑 主键
slugURL 别名
name分类名称

关注表 (follows)

字段描述备注
id🔑 主键
user_id🔗 用户 ID
followed_user🔗 被关注者 ID
status状态关注(follow)/ 取关(unfollow)
created创建时间第一次关注时间
update更新时间关注状态改变时间

粉丝表(fans)

字段描述备注
id🔑 主键
user_id🔗 用户 ID
follower🔗 粉丝 ID
status状态关注(follow)/ 取关(unfollow)
created创建时间第一次关注时间
update更新时间关注状态改变时间

选项表(options)

用于记录网站的一些配置属性信息,如:站点标题,站点描述等

字段描述备注
id🔑 主键
key属性键snake_case
value属性值JSON 格式