news 2026/8/24 15:07:13

小程序面试指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
小程序面试指南

一、为什么会出现小程序?

App太重,H5网页太糙

小程序是 App 和 H5 网页之间的“黄金平衡点”。它既保留了 App 流畅的体验和强大的功能,又拥有了 H5 网页无需下载、极其轻便的优势。

App、H5、小程序对比

对比维度原生AppH5网页小程序
获取与安装太重:需去应用商店搜索、下载几百兆安装包、注册登录,门槛极高。最轻:无需下载,复制个链接就能打开。适中:无需下载安装,扫码或微信搜索“即用即走”,不占手机内存。
性能与流畅度极佳:直接调用手机系统底层硬件,滑动丝滑,加载极快。较差:依赖浏览器渲染,每次打开都要重新加载,复杂动效容易卡顿。较好:体验接近原生 App,加载快、流畅度高,告别了 H5 的卡顿感。
系统权限与功能无限制:能调用手机所有底层功能(如后台常驻、复杂蓝牙等)。极受限:几乎没有系统权限,无法调用摄像头、蓝牙等高级硬件功能。较丰富:依托微信生态,能调用支付、定位、扫码等常用底层 API,满足 90% 业务需求。
开发与维护成本极高:需 iOS 和安卓两套代码,开发周期长,每次更新都要重新提交应用商店审核。极低:一套代码多端运行,修改服务器代码即可,无需审核,迭代极快。适中:一套代码(如 uni-app)即可生成,开发门槛较低,更新只需提交微信审核,非常便捷。
传播与分享困难:用户很难主动去分享一个 App,获客成本高昂。容易:链接可随意发到任何聊天软件或朋友圈,但容易流失。极佳:背靠微信庞大流量,可一键转发给好友或微信群,裂变传播极快。
用户留存与触达强:图标常驻桌面,可通过系统推送随时唤醒沉睡用户。极弱:关闭网页就找不到了,无法主动触达用户。中等:用完即走导致留存较弱,但可通过微信订阅消息在限定时间内触达用户。

二、小程序生命周期

1. 应用级别生命周期(App 级)

生命周期函数触发时机核心作用与实战场景Vue3 对标
onLaunch小程序首次启动时触发,全局仅执行 1 次全局初始化:检查登录状态、获取用户信息、初始化全局配置(如globalData)。App 初始化
onShow小程序启动或从后台切回前台时触发,可多次执行全局状态刷新:检查 Token 是否过期、恢复全局音频/视频播放、埋点统计。App activated
onHide小程序从前台切到后台时触发全局资源释放:保存临时表单草稿、暂停全局定时器、停止音乐播放。App deactivated

2. 页面级别生命周期(Page 级)

生命周期函数触发时机核心作用与实战场景Vue3 对标
onLoad页面首次加载时触发,仅执行 1 次接收参数与初始请求:接收页面跳转传来的参数(options),发起核心的接口请求(如获取商品详情)。onMounted(初始化)
onShow页面显示或从后台切回前台时触发,可多次执行数据动态刷新:比如从详情页返回列表页时,刷新列表的未读消息数或最新状态。onActivated
onReady页面初次渲染完成时触发,仅执行 1 次DOM 操作与动画:获取节点信息(如获取元素宽高)、启动页面入场动画、初始化地图/图表组件。onMounted
onHide页面被隐藏或切到后台时触发暂停与保存:暂停当前页面的视频播放、停止页面专属的倒计时器、保存表单进度。onDeactivated
onUnload页面被卸载(关闭)时触发彻底清理:清除定时器(防止内存泄漏)、取消未完成的网络请求、解绑事件监听。onUnmounted

3. 组件级别生命周期(Component 级)

核心阶段uni-app(Vue3)生命周期原生小程序生命周期触发时机与核心作用实战开发场景
创建阶段setupcreated实例刚创建,数据初始化。
此时组件实例刚刚被创建,视图层(DOM)还未生成。
初始化组件内部状态、定义响应式变量、接收父组件传参。注意:不能操作 DOM。
挂载阶段onMountedattached进入节点树,DOM 准备就绪。
组件实例进入页面节点树,视图层已渲染完毕。
最常用的初始化时机。发起组件自身的网络请求、初始化第三方图表(如 ECharts)、获取 DOM 节点宽高。
布局完成(Vue3 无直接对应)ready视图层布局完成。
attached之后触发,此时可以获取节点信息。
在原生小程序中,若需要精确获取组件在屏幕上的位置或宽高,放在这里最稳妥。
更新阶段onUpdated(原生无直接对应)数据变更,视图重新渲染后。
响应式数据更新导致 DOM 重新渲染后触发。
在数据更新后,执行依赖最新 DOM 的操作(如:列表渲染完后自动滚动到底部、重新计算长列表高度)。
销毁阶段onUnmounteddetached离开节点树,组件销毁。
组件被从页面节点树移除时触发。
极其重要的清理时机。清除定时器(clearInterval)、解绑全局事件监听、断开 WebSocket,防止内存泄漏。

三、小程序生命周期流程

1. 应用级生命周期流程(App.vue)

应用级生命周期负责管理整个小程序从出生到死亡的全局状态。

  • 启动与初始化(onLaunch:当用户首次打开小程序时触发,全局仅执行 1 次。通常在这里做全局配置、检查登录状态等。
  • 进入前台(onShow:小程序启动,或者从后台切回前台时触发(可多次执行)。适合做全局状态刷新、恢复播放等。
  • 进入后台(onHide:当用户点击右上角胶囊关闭、切回微信聊天界面或手机锁屏时触发。适合做数据保存、暂停全局定时器等“善后”工作。
  • 销毁(后台机制):小程序进入后台后,如果超过一定时间(如 10 分钟)未切回前台,或者系统内存不足,小程序会被系统彻底销毁。下次再打开时,就会重新走一遍onLaunch(冷启动)。

2. 页面级生命周期流程(Page 级)

页面级生命周期是日常开发中最常用的,它管理单个页面的生老病死。

  • 页面加载(onLoad:页面首次加载时触发,仅执行 1 次。主要用于接收路由参数和发起核心网络请求。
  • 页面显示(onShow:页面显示/切入前台时触发,可多次执行。每次从其他页面返回,或从后台切回前台都会触发,适合刷新页面数据。
  • 初次渲染完成(onReady:页面初次渲染完成时触发,仅执行 1 次。此时 DOM 节点已经准备好,适合获取元素宽高或初始化图表。
  • 页面隐藏(onHide:页面被隐藏(如navigateTo到下一个页面,或切到后台)时触发。适合暂停当前页面的视频或定时器。
  • 页面卸载(onUnload:页面被销毁(如navigateBack返回上一页,或redirectTo重定向)时触发。必须在这里清除定时器和事件监听,防止内存泄漏。

四、小程序登录流程(判断登录是否过期)

1. 小程序登录时序

  1. 小程序客户端调用uni.login,向微信服务器发起获取临时凭证的请求。
  2. 微信服务器验证通过后,向小程序客户端返回临时凭证(code)。
  3. 小程序客户端通过自定义网络请求,将临时凭证(code)发送至开发者服务器。
  4. 开发者服务器将临时凭证(code)、AppID 和 AppSecret 发送至微信服务器。
  5. 微信服务器验证通过后,向开发者服务器返回用户唯一标识(openid)和会话密钥(session_key)。
  6. 开发者服务器生成自定义登录态(Token)。
  7. 开发者服务器将自定义登录态(Token)返回给小程序客户端。
  8. 小程序客户端将Token存储至本地。
<script setup> import { onLaunch } from '@dcloudio/uni-app'; onLaunch(() => { console.log('App 启动,开始静默登录...'); // 1. 调用 uni.login 获取临时 code uni.login({ provider: 'weixin', // 指定微信登录 success: async (loginRes) => { if (loginRes.code) { // 2. 将 code 发送给咱们自己的后端 const res = await uni.request({ url: 'https://your-api.com/api/login', // 替换为你的后端接口 method: 'POST', data: { code: loginRes.code } }); // 3. 接收后端返回的 Token,并存储在本地 if (res.data.token) { uni.setStorageSync('user_token', res.data.token); console.log('登录成功,Token已保存'); } } }, fail: (err) => { console.error('微信登录失败', err); } }); }); </script>

2. 登录过期判断

校验微信底层登录态(session_key)

微信的session_key具有一定的时效性,微信官方并没有公开具体的过期时间,而是根据用户使用小程序的行为动态续期。为了判断其是否过期,开发者需要使用微信提供的检测接口:

  • 前端校验:通过调用wx.checkSession接口来检测当前用户的微信登录态是否有效。如果接口调用成功,说明session_key未过期;如果调用失败,则说明已经失效,需要重新执行wx.login登录流程。
  • 注意事项:由于wx.checkSession接口平均耗时约 200ms,如果在每次发起网络请求前都进行校验,会产生较大的性能开销。因此,不建议在每次请求前都调用此接口。

校验开发者服务器登录态(自定义 Token)

除了微信底层的登录态,开发者服务器自身维护的登录态(Token)也存在过期的可能。在实际业务中,推荐采用以下策略来判断:

  • 接口调用前:仅校验前端本地是否存在有效的Token,不校验后端及微信的登录态,以节省每次请求的校验开销。
  • 接口调用后:在获取到后端的响应数据后进行解析。如果后端返回了与登录态相关的错误码(例如 HTTP 401 状态码),则说明后端的Token已经失效。此时前端应重置本地的登录态,并自动触发重新登录流程,然后重新发起业务请求。

五、小程序支付流程

  1. 小程序前端调用uni.login,向微信服务器获取用户的openid
  2. 小程序前端将订单信息及openid发送至开发者后端服务器。
  3. 开发者后端服务器调用微信支付统一下单接口,向微信服务器请求生成预付单。
  4. 微信服务器返回预支付交易会话标识(prepay_id)给开发者后端服务器。
  5. 开发者后端服务器对支付参数进行二次签名,并将结果返回给小程序前端。
  6. 小程序前端调用uni.requestPayment,向微信客户端发起调起支付的请求。
  7. 用户在微信客户端完成验密及支付授权。
  8. 微信服务器向开发者后端服务器异步推送支付成功通知。
  9. 微信客户端向小程序前端返回支付结果回调。
  10. 小程序前端根据回调结果向用户展示支付状态。
<template> <view class="pay-page"> <button class="pay-btn" :disabled="isPaying" @click="handlePay"> {{ isPaying ? '支付处理中...' : '立即支付' }} </button> </view> </template> <script setup> import { ref } from 'vue'; // 1. 定义防抖状态,防止用户手抖连续点击导致重复支付 const isPaying = ref(false); // 2. 发起支付的主流程 const handlePay = async () => { // 如果正在支付,直接拦截 if (isPaying.value) return; isPaying.value = true; try { // 【第一步】向你的后端请求支付参数 // 实际项目中,这里通常还会先调用创建订单的接口拿到 orderId const payParams = await requestPayParams('ORDER_20240526001'); // 【第二步】调起微信支付 await wxPay(payParams); // 【第三步】支付动作完成,跳转到支付结果页 // 注意:这里的 success 只代表用户完成了支付动作,真正的结果以后端为准 uni.redirectTo({ url: '/pages/pay/result?status=success&orderId=ORDER_20240526001' }); } catch (err) { console.error('支付流程异常:', err); // 【第四步】异常兜底处理 if (err.errMsg && err.errMsg.includes('cancel')) { // 用户在支付密码框点击了“取消” uni.showToast({ title: '支付已取消', icon: 'none' }); } else if (err.code === 'ORDER_EXPIRED') { // 订单超时等后端自定义错误 uni.showModal({ title: '提示', content: '当前订单已超过支付时效,请重新下单', showCancel: false }); } else { // 其他未知错误 uni.showToast({ title: '支付失败,请重试', icon: 'none' }); } } finally { // 无论成功失败,解除按钮禁用状态 isPaying.value = false; } }; // 3. 封装:请求后端获取支付参数 const requestPayParams = (orderId) => { return new Promise((resolve, reject) => { uni.request({ url: 'https://your-api.com/api/pay/create', // 替换为你的后端接口 method: 'POST', data: { orderId }, success: (res) => { if (res.data.code === 200) { resolve(res.data.data); // 返回后端生成的支付参数对象 } else { reject(res.data); } }, fail: reject }); }); }; // 4. 封装:调起微信支付 const wxPay = (payParams) => { return new Promise((resolve, reject) => { uni.requestPayment({ timeStamp: payParams.timeStamp, nonceStr: payParams.nonceStr, package: payParams.package, // 格式必须是 prepay_id=*** signType: payParams.signType, // V3接口通常为 RSA,V2接口为 MD5 paySign: payParams.paySign, success: (res) => { console.log('支付动作完成:', res); resolve(res); }, fail: (err) => { reject(err); } }); }); }; </script>

六、小程序路由跳转

路由方法核心参数说明页面栈的变化
wx.navigateTourl(必填)保留当前页面,跳转到应用内的某个非 tabBar 页面。可以使用wx.navigateBack返回到原页面。新页面入栈。当前页面被隐藏(触发onHide),新页面被压入栈顶(触发onLoadonShow)。页面栈深度加 1。
wx.redirectTourl(必填)关闭当前页面,跳转到应用内的某个非 tabBar 页面。不允许返回到原页面。当前页面出栈,新页面入栈。相当于“替换”了当前页面。原页面被卸载(触发onUnload),页面栈深度保持不变。
wx.switchTaburl(必填)跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。不能携带参数。页面全部出栈,只留下新的 Tab 页面。页面栈被清空,仅包含目标 tabBar 页面。
wx.reLaunchurl(必填)关闭所有页面,打开到应用内的某个页面(任意页面均可)。页面全部出栈,只留下新的页面。相当于强制重启小程序到指定页面。
wx.navigateBackdelta(选填)关闭当前页面,返回上一页面或多级页面。delta表示返回的层数,默认为 1。页面不断出栈,直到目标返回页。页面栈深度减少delta的值。若返回到栈底则停止。
  • 页面栈上限:小程序的页面栈通常最多只有 10 层。如果频繁使用wx.navigateTo而不及时返回或重定向,很容易导致页面栈溢出,之后再调用navigateTo会失效。因此在长流程(如电商下单、表单填写)的终点,建议使用redirectToreLaunch
  • API 使用限制wx.navigateTowx.redirectTo只能打开非 tabBar 页面,而wx.switchTab只能打开 tabBar 页面。如果路径配置错误,API 会调用失败。
  • 不要直接修改页面栈:虽然可以通过getCurrentPages()获取当前页面栈实例,但千万不要尝试直接修改这个数组,否则会导致路由和页面状态出现严重错误。
  • 路由参数获取:通过路由跳转携带的参数(如 url 中拼接的?id=123),可以在目标页面的onLoad(options)生命周期函数中直接通过options对象获取。

七、小程序的实现原理

1. Web 单线程的执行机制(传统 H5 网页)

传统网页的渲染和 JS 逻辑是互斥的单线程模型。

  • 执行机制:浏览器中,JavaScript 引擎线程(处理逻辑)和 GUI 渲染线程(处理页面显示)是互斥的。同一时刻只能执行一个任务,如果 JS 执行了耗时的计算或死循环,页面渲染就会被阻塞,导致用户感觉“页面卡死”。
  • 为什么设计成单线程:主要是为了避免复杂的并发问题。如果允许多线程同时操作 DOM(比如一个线程在修改按钮颜色,另一个线程在删除按钮),会导致不可预测的渲染混乱和竞态条件。
  • 痛点:复杂的 JS 运算会直接抢占 UI 渲染的资源,导致页面卡顿、掉帧。

2. 小程序双线程的执行机制

为了解决 Web 单线程的卡顿问题,并满足微信的安全管控需求,小程序采用了逻辑层与视图层分离的双线程模型。

  • 逻辑层(App Service):运行在独立的 JavaScript 引擎中(iOS 用 JavaScriptCore,Android 用 V8 等)。它负责处理所有的 JS 业务逻辑、数据请求、API 调用等。
  • 视图层(View Layer):运行在 WebView 线程中。它负责解析 WXML 和 WXSS,进行页面的 UI 渲染。一个小程序有多个页面,就会有多个 WebView 线程。
  • 核心优势
    • 性能隔离:即使逻辑层在进行极其复杂的数据计算,也不会阻塞视图层的渲染。用户的滑动、点击依然能保持丝滑流畅。
    • 安全管控:逻辑层是一个纯粹的 JS 沙箱环境,没有windowdocument对象,开发者无法直接操作 DOM。这从根源上防止了恶意脚本攻击和页面篡改。

3. 小程序实现的底层原理(Native Bridge 通信)

既然逻辑层和视图层是两个独立的线程,它们之间是如何协同工作的呢?这就涉及到了小程序的底层通信原理。

  • Native 层中转(JSBridge):这两个线程之间是完全隔离、不共享内存的。它们之间的任何数据传递和事件触发,都必须通过宿主环境(微信客户端的 Native 层)作为桥梁进行异步转发。
  • 数据驱动视图(setData原理)
    1. 当逻辑层数据发生变化时,调用setData
    2. 框架将数据序列化为字符串(JSON),通过 Native 层转发给视图层。
    3. 视图层接收到数据后,进行反序列化,利用虚拟 DOM(Virtual DOM)机制进行 Diff 算法对比,最后将差异应用到真实的 DOM 树上完成渲染。
  • 事件触发流程:用户在界面点击按钮(视图层),WebView 拦截事件,将事件信息序列化后通过 Native 层传递给逻辑层,逻辑层找到对应的 JS 事件处理函数执行。

八、小程序启动与销毁

1. 小程序的两种启动方式

小程序的启动主要分为两种状态:

  • 冷启动(Cold Start):当用户首次打开小程序,或者小程序被系统销毁后再次打开时,就会触发冷启动。此时,小程序需要重新加载全部资源并执行初始化(触发onLaunch),耗时相对较长。
  • 热启动(Hot Start):如果用户之前打开过小程序,但在一定时间内再次打开,此时小程序并未被销毁,只是从“后台”状态切换回“前台”状态。这个过程就是热启动,它无需重新加载资源,几乎是瞬间恢复。

2. 小程序销毁机制(什么情况下会销毁?)

当用户点击小程序右上角的“关闭”按钮,或者按 Home 键离开时,小程序并不会立即被销毁,而是进入了“后台”状态。只有在满足以下特定条件时,小程序才会被彻底销毁(下次打开即为冷启动):

  • ① 后台停留时间过长:小程序进入后台后,如果长时间没有再次切回前台,系统会主动将其销毁。不同平台的判定时间有所不同:
    • 抖音小程序:后台停留超过 5 分钟会被主动销毁。
    • B站小程序:进入后台并被挂起后,超过 30 分钟未进入前台会被销毁。
    • 其他平台:部分平台(如涂鸦小程序)的后台存活时间可能长达 10 分钟。
  • ② 系统资源紧张(内存告急):当手机系统内存不足时,宿主应用(如微信、抖音)会主动回收后台的小程序。例如,当客户端连续收到系统内存告警时,会根据策略主动销毁后台的小程序,以保证宿主 App 的正常运行。
  • ③ 后台小程序数量达到上限:系统对同时存在于后台的小程序数量是有上限的。例如,在 iOS 系统上,最多允许有 5 个小程序同时存在。如果用户打开了第 6 个小程序,那么最早进入后台的那一个就会被强制销毁。
  • ④ 业务异常或主动配置(直接销毁,不进入缓存):在某些特殊场景下,小程序关闭时会直接销毁,不进行内存缓存:
    • 页面异常:如果用户关闭小程序时页面处于白屏状态,系统会直接销毁,避免下次打开时恢复异常页面。
    • 流程未结束:如果关闭时小程序仍有启动流程或网络请求在执行中,会直接销毁。
    • 主动禁用缓存:开发者可以在全局配置(如disableCache: true)中强制设置退出时销毁小程序,确保每次打开都是全新的冷启动。
    • 非正式版本:开发版、体验版等非正式版本的小程序,通常不做内存缓存,关闭即销毁。

九、小程序的渲染流程

1. 启动与初始化阶段

当用户点击小程序图标时,宿主环境(如微信客户端)会启动小程序进程,并同步初始化两个核心线程:

  • 渲染线程(视图层):初始化 WebView 环境,加载基础库和渲染框架,准备接收渲染指令。
  • 逻辑线程(逻辑层):加载基础库,执行app.js创建 App 实例,并触发App.onLaunchApp.onShow生命周期。

2. 页面加载与数据准备阶段

初始化完成后,系统开始加载具体的页面:

  • 逻辑层执行:加载入口页面对应的page.js,创建 Page 实例,收集初始化数据(initData),并依次触发页面的onLoadonShow生命周期。
  • 数据下发:逻辑层将准备好的initData序列化后,通过 Native 层(JSBridge)派发给渲染线程。

3. 首次渲染阶段(构建视图树)

渲染线程接收到初始数据后,开始执行真正的渲染工作:

  • 解析与编译:解析页面的 WXML 模板和 WXSS 样式文件,将其转换为对应的节点树和样式规则。
  • 构建视图树:将节点树与样式规则合并,生成最终的“视图树”(Render Tree),仅包含可见节点。
  • 首次绘制:将视图树交由底层图形系统进行绘制,完成页面的首次内容绘制(FCP)和首次有意义绘制(FMP)。渲染完成后,会通知逻辑层触发onReady生命周期。

4. 运行时更新阶段(数据驱动视图)

在页面展示后,用户的交互或网络请求会触发数据更新,进而引发重新渲染:

  • 触发更新:开发者调用setData修改数据。逻辑层会对新旧数据进行 Diff 对比,找出发生变化的部分。
  • 跨线程通信:逻辑层将变化的数据序列化为消息,通过 Bridge 异步发送给渲染线程。
  • 局部重绘:渲染线程接收消息并反序列化,精准更新对应的 DOM 节点,触发页面的局部重排与重绘,最终通知逻辑层更新完成。

十、小程序提速手段

启动性能优化(打破首屏加载瓶颈)

代码包体积优化(最影响首次打开速度)

  • 代码分包:将主包体积严格控制在 2MB 以内。主包只放首页和 TabBar 页面,其他低频页面(如个人中心、活动详情)拆分为子包,按需加载。
  • 清理冗余:删除未使用的页面、组件、图片和样式,避免打包多余的第三方库。

提前发出请求与预加载

  • 数据预加载:在页面跳转前(如点击列表项时),提前请求下一页的数据并挂载到全局(如getApp().globalData)。新页面加载时直接使用,可大幅缩短首屏渲染时间。
  • App.js瘦身:不要在onLaunch中做耗时操作(如复杂的同步计算、同步请求),非必要逻辑可放到首页的onShow或延迟执行。

优化首屏渲染体验

  • initData预热:在页面初始化时,构造好核心渲染数据的骨架结构。底层框架会提前创建 DOM 元素,待真实数据返回时仅替换内容,无需重新创建元素,节省大量渲染时间。
  • 骨架屏:在页面加载时展示骨架屏占位,降低用户的等待焦虑。

2. 运行时性能优化(保证交互流畅度)

极致优化setData(最核心的痛点)

  • 减少调用频率:严禁在for循环、高频滚动事件或定时器中调用setData。尽量合并多次数据更新,一次性传给视图层。
  • 控制数据量:单次setData的数据量建议控制在 100KB 以内,避免 JSON 序列化耗时过长。
  • 路径更新:使用数据路径语法精确更新(如'list[0].name': 'newName'),避免整个大对象或大数组的全量刷新。

长列表与渲染优化

  • 虚拟列表:对于成百上千条数据的列表,必须使用分页加载或虚拟列表技术,只渲染用户可视区域内的 DOM 节点,防止内存暴涨和滑动卡顿。
  • 避免复杂模板逻辑:不要在 WXML 的{{}}中写复杂的表达式或函数调用。复杂的数据处理应在 JS 层(逻辑层)计算好再传给视图层。

图片与静态资源优化

  • 图片懒加载:使用lazy-load属性,仅加载可视区域内的图片,减少初始网络请求和内存占用。
  • WebP 格式与云端化:将图片转换为 WebP 格式(体积可减小 30%~50%),并将大图、封面图全部上传至云端(OSS/CDN),不要放在本地包中。

内存管理(防止闪退)

  • 及时清理资源:在页面或组件卸载时(onUnload/onUnmounted),务必清理定时器(clearInterval)、解绑全局事件监听,防止内存泄漏。
  • 控制页面层级:避免连续跳转 5 层以上的页面,不用的页面及时使用redirectTo关闭,避免页面栈过深占用过多内存。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 15:02:42

React + Zustand + JWT:从零实现登录鉴权与请求拦截

引言你有没有遇到过这样的场景&#xff1a;用户登录成功后&#xff0c;刷新页面就丢了登录态&#xff1f;或者每个请求都要手动写一遍 Authorization 头&#xff0c;代码又臭又长&#xff1f;说白了&#xff0c;登录鉴权的本质&#xff0c;就是在无状态的 HTTP 协议上&#xff…

作者头像 李华
网站建设 2026/8/24 15:01:36

3步完成QQ空间说说全量备份:GetQzonehistory历史备份完整指南

3步完成QQ空间说说全量备份&#xff1a;GetQzonehistory历史备份完整指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 如果你的QQ空间攒了多年说说和旧照片&#xff0c;别等哪天找不…

作者头像 李华
网站建设 2026/8/24 15:01:02

字节阿里腾讯校招AI岗位超多?7个真相揭示AI行业反直觉机会

2026年校招中&#xff0c;字节、阿里、腾讯等大厂AI岗位激增&#xff0c;但行业呈现反直觉趋势&#xff1a;开放岗位门槛极高&#xff0c;本科生或胜过硕士生&#xff0c;底层系统工程师薪资追平研究员&#xff0c;CV/NLP岗位被大模型整合&#xff0c;游戏公司AI投入激进&#…

作者头像 李华
网站建设 2026/8/24 14:57:17

Landsat数据—6s大气校正

Landsat数据认识—以及6s大气校正处理1. Landsat卫星介绍2. Landsat数据介绍2.1 数据级别介绍2.2 数据名称命名格式3. Landsat数据波段信息介绍3.1 Landsat 4-5 Thematic Mapper ( TM )3.2 Landsat 7 Enhanced Thematic Mapper Plus (ETM)3.3 Landsat 8-9 Operational Land Ima…

作者头像 李华