原型和原型链的理解

每个函数都有一个原型(prototype

每个对象(prototype也是对象)都有__proto____proto__指向该函数的构造函数的prototype

当a(对象)访问a.name时,会先去找自身有没有name,没有就会通过__proto__找上层的prototype中有没有name,还是没有继续上向找,这个过程就是原型链

实例.__proto__ → 构造函数.prototype → Object.prototype → null

防抖和节流的理解、区别和实现

防抖是”第一次或最后一次说了算”

节流是”每隔一段时间执行一次”

宏任务和微任务

异步任务的两个类型:

常用的 promise 就是微任务

setTimeout 就是宏任务

requestAnimationFrame比较特殊,在微和宏之间

执行顺序: 同步代码 → 微任务队列清空 → 一个宏任务 → 微任务队列清空 → 下一个宏任务……

登录鉴权方案

JWT(JSON Web Token)

登录返回token,每次请求都带上,过期就用长期token刷新请求token

Session方案:

服务端存储会话,客户端只存sessionId,过期就401或重定向到登录。

requestAnimationFrame和setTimeout / setInterval

rAF用来制作动画,使用定时器会有不精确的时间间隔,过度消耗性能。导致掉帧,卡,浪费资源。

rAF主要用于(滚动监听、Canvas 绘图、DOM 动画、游戏循环),且是唯一的最佳选择

重放攻击

攻击者拿到完整的Curl,重复的请求发送,导致数据或服务出现问题。

常见手段:

  • 时间有效期
  • 一次随机数
  • 时间 + 随机数 + 签名
  • https(加密传输)

浏览器到页面生成完整过程

  1. DNS解析(本地缓存,再系统hosts,最后问DNS服务器)
  2. TCP三次握手,HTTPS还需要TLS握手
    1. 你好 → 你好我也好(HTTPS返回加密方式) → 开始
  3. HTTP请求
  4. 返回HTML并处理
  5. 浏览器解析HTML
    1. 构建DOM
    2. CSS到CSSDOM 加 <head> 防止阻塞
    3. <SCRIPT> 加 defer/asyn 防止阻塞
  6. DOM+CSSDOM 生成树
  7. 计算位置和尺寸
  8. 绘制到屏幕上
  9. 合成,图层以合并输出画面

闭包

一个函数能够记住并访问它自己和它周围的变量,即使它已经离开了出生地(return了),就是闭包。

闭包使函数拥有了“记忆力”。

常见场景:

  1. 防抖/节流
  2. 私有变量
  3. 函数工厂,根据参数返回不同的结果和做不同的事件
  4. 缓存/记忆函数,避免重复计算

闭包会让变量不被垃圾回收,用完要注意释放,避免内存泄漏。常见就是removeEventListener和clearInterval

onMounted(() => {
  const timer = setInterval(() => {
    console.log('running')
  }, 1000)

  // 组件销毁时没清除定时器 → 内存泄漏
  // ✅ 应该在 onUnmounted 里清除
  onUnmounted(() => clearInterval(timer))
})


function bindEvent() {
  const bigData = new Array(100000).fill('数据')

  function handleClick() {
    console.log(bigData)
  }

  const btn = document.getElementById('btn')
  btn.addEventListener('click', handleClick)

  // 用完后移除监听器,闭包引用断开,bigData 可以被回收
  return function cleanup() {
    btn.removeEventListener('click', handleClick)
  }
}

const cleanup = bindEvent()
// 不需要时调用
cleanup()

深拷贝和浅拷贝

浅拷贝:只复制对象的第一层

深拷贝:所有层级都复制,且是独立的新对象,互不影响

1. JSON.parse简单暴力
JSON.parse(JSON.stringify(obj))

2. structuredClone
const deep = structuredClone(obj)

3. 递归
function deepClone(obj) {
  if notnull notobject
  const clone = Array.isArray(obj) ? [] : {}
	for(let key in obj) {
    if(obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key])
    }
  }
}

4. 生产项目用 lodash 

Vue2 和 Vue3 的核心区别

  1. 响应式原理的区别,解决了无法检测属性新增/删除
  2. 使用区别:CompositionAPI和OptionAPI
  3. 组件支持多根节点
  4. 整体性能更好

Vue 响应式原理

vue2:Object.defineProerty vue3:Proxy 都根据其方法的get,set获取变更,从而展示出来,不同在于vue2需要遍历每个key才能监听,而且不知道新增和删除(使用Vue.set解决),数组更是需要重写方法才能监听(改写7个原生方法⁠ push、⁠pop、⁠shift、⁠unshift、⁠splice、⁠sort、⁠reverse)

Vue3都是完美原生支持,就是不支持IE😃

computed 和 watch 的区别

一对多和多对一、缓存,有返回无返回,多次用computed,复杂用watch

v-model 的原理 ⭐️待复习

本质是语法糖,:value+@input,也就是prop+emit。有一个细节:在中文输入的时候不会触发监听(compositionstart开始合成文字和compositionend结束合成)

Vue3支持多个v-model:name,原理就是update:name

Vue 生命周期及父子组件执行顺序

Created -> mounted ->updated -> destroyed

到了Vue3就是steup -> onMounted -> onUpdated -> Unmount

keep-alive 是什么

组件缓存,避免不必要的,常用于tab切换,router-view

因为有缓存更新的需要使用用activated,缓存大小是可控的

Vue 组件通信方式

常用的prop + emit,ref + defineExpose(vue2不需要,默认导出全部)

跨组件provide / inject,其实用vuex/pinia更好

Vue Router 导航守卫

全局用beforeEach、afterEach,路由用beforeEnter,组件内onBeforeRouteEnter,onBeforeRouteUpdate,onBeforeRouteLeave

hash 模式和 history 模式的区别

hash带#,history不带,但是需要nginx配置,/ 指向index.html

nextTick 是什么

Vue更新DOM是异步的,我更新完成数据,如果要DOM的值,就会用nextTick

ref 和 reactive 的区别

ref基本类型和对象,reactive只能对象

ref需要带.value,reactive不需要

建议统一使用ref

defineProps 和 defineEmits 的用法

defineProps 接收定义的 props

defineEmits 定义可触发的事件

defineExpose 是什么

ref想用子组件方法,就需要defineExpose暴露方法在外面。

watchEffect 和 watch 的区别

一个不返回,一个返回旧值。

默认执行,默认不执行。

只能监听一个值,需要什么就写什么,这一点和computed类似,但是没有缓存,但是是支持异步的。

Teleport 是什么 ⭐️待复习

指定渲染位置,一般用于DOM全局的组件(提示,Loading,选框类)

Suspense 是什么 ⭐️待复习

Suspense做骨架图用的,加载慢的地方用。

v-show 和 v-if 的区别

v-if会销毁组件

v-show只操作DOM

为什么 v-if 和 v-for 不建议一起用

vue2中v-for等级高于v-if,先遍历再判断,就会有性能浪费。

vue3是反过来的,但是v-if拿不到v-for的变量会报错。

Vue 中 key 的原理

虚拟DOM的唯一标识,它是服务于 vue的diff算法,精准快速的找到这个DOM,并知道它是否更新。

什么是虚拟 DOM

真实DOM的一种抽象表达,每次数据变化,vue先生成新的虚拟DOM树,再通过diff算法对比新旧树,只有差异部分更新到真实DOM上,减少重绘。

DIFF算法

简单说就是用最省时,省力的方法,把虚拟DOM的变化同步到真实DOM上。

  1. 同层比较
  2. 利用key
  3. 四种命中策略,双端对比(头对头、尾对尾、头对尾、尾对头)
    1. 头对头/尾对尾 确认位置是否变化。
    2. 头对尾/尾对头 专门处理 翻转 的情况。
  4. 如果都没有中(Map 查找策略
    1. 旧队列所有key存进map
    2. 拿新队形开头的key去map里面搜索
  5. 没有key,继续利复用。

vue3有一个更新 静态提升,就是启动不改变的HTML,如下

<div>
  <h1>我是一个标题</h1> <!-- 静态节点:内容永远不变 -->
  <p>8</p>    <!-- 动态节点:内容会随 count 改变 -->
  <span>固定文本</span>  <!-- 静态节点 -->
</div>

作用域和作用域链

作用域是变量可被访问的范围

作用域链:函数在查找变量时时,一层一层(先块级函数级,找不到就全局)作用域往外找,一直找到自己的作用变量,这个查找链接就是作用域链。

Promise、async/await 和事件循环

Promise是解决回调地狱的一个方法。理论上可以无限链调用。

async/await是promise的语法糖,用同步代码的方式写异步代码

事件循环:JS是单线程,通过事件循环来处理异步任务,执行顺序

1. 执行同步代码
1. 先清空微任务队列promise
1. 再取宏任务setTimeout、setInterval
1. 继续重复2-3

​ 其中有一个特殊:requestAnimationFrame,在微任务和宏任务中间触发,不属于事件循环,是浏览器的机制。

Vue3 相比 Vue2 的升级点

  1. compositionAPI
  2. 响应式
  3. 性能
  4. 多根节点
  5. 新组件:teleprot,SUspense
  6. 生命周期
  7. v-model可以多个

浏览器缓存机制 ⭐️待复习

浏览器缓存分两类

  1. 强缓存Cacthe-Control: max-age=3600,老写法是Expires-过期时间。
  2. 弱缓存(协商缓存)携带ETag/Last-Modified给服务器对比,没变化返回304,有变化200+新内容

CSS 垂直居中方法

  1. flex
  2. grid
  3. absolute + translate
  4. width + height + margin
  5. line-height

CSS 样式优先级

  1. !important
  2. 内联
  3. #ID
  4. 类选择,属性选择
  5. 标签
  6. 通配符*

如何防护 XSS 攻击 ⭐️待复习

  1. 不用innerHTML,document.write,eval(解析JOSN对象)
  2. CSP,后端通过HTTP 响应头限制页面能加载的资源来源
  3. HttpOnly Cookie,JS无法读取Cookie,请求自动带上。
  4. 富文本要用白名单或黑名单过滤

后台权限管理如何设计 ⭐️待复习

页面权限、按钮权限、接口权限

  1. 根据权限动态生成路由
  2. 根据角色控制按钮显示隐藏
  3. 每次请求携带 token

首屏加载优化方案 ⭐️待复习

  1. 效果好
    1. 路由懒加载&图片懒加载
    2. 组件按需引入
    3. 浏览器缓存
    4. tree-shaking(vue3)去除未使用代码
    5. 骨架图(让用户感觉很快)
    6. 小图转base64
    7. CDN GZIP 加速,服务器配置
    8. SSR

组件封装的理解和思路 ⭐️待复习

  1. 重复使用
  2. 功能相关独立
  3. 交互逻辑需要隔离

跨域是什么?如何解决

浏览器同源策略限制,协议、域名、端口相同,就会跨域。

  1. 开发环境 - vite/webpack 代理
  2. Nginx 反向代理
  3. 后端开放CORS
  4. JSON(现在基本不用了)

TypeScript 中 type 和 interface 的区别

type 用于基本类型 string boolean array number any

interface 联合类型,常用于接口设置或接收参数

var、let、const 的区别

var 声明前可以看,undefined 不报错,会全局污染。

let 声明前查看会报错。

const 和let一样,不能重新赋值,但是属性可以改。

== 和 === 的区别?

二等宽松

三等严格

区别:类型不同、null和undefined、0和false

this 的理解

调用方式 this 指向
对象方法调用 调用该方法的对象
构造函数(new) 新创建的实例
call / apply / bind 手动指定的对象
箭头函数 继承外层作用域的 this,不可更改

call / apply / bind 详解

三者都是用来手动指定 this 的,call 和 apply 都是立即执行,bin返回一个新函数

  call apply bind
是否立即执行 ✅ 是 ✅ 是 ❌ 返回新函数
传参方式 逐个传 数组传 逐个传(可预设部分参数)

内存泄漏的常见场景

  1. 定时器没有清除
  2. 事件监听没清除
  3. 闭包引用大对象
  4. 全局变量用多了
  5. DOM 引用没有释放
  6. watch没有停止

Webpack 和 Vite 的区别?

  Webpack Vite
开发模式 打包后启动,项目越大越慢 基于 ESM 按需加载,启动极快
热更新 重新打包受影响模块,较慢 只更新变动文件,几乎即时
生产打包 自身打包 用 Rollup 打包
插件 Loader Plugin

ox

Webpack 打包后再启动,Vite按需加载,启动很快。Webpack是自身打包,Vite用Rollup打包

Webpack 的构建流程

  1. 读配置文件,合并参数,创建compiler
  2. 确定入口,从 entry 开始
  3. 编译模块,各种loader
  4. 所有依赖关系理成,生成依赖图
  5. 输出,根据依赖图组成 Chunk,文件输出到 output

Git rebase 和 git merge 的区别

都是分支合并的作用。历史记录处理不同

mere 会生成新的历史,看的更清楚,真实记录(要合并到主分支用这个)

rebase 历史成为一条直线,会有漂亮整洁的commit,如果冲突多了,要一个一个的解决(个人分支用)

git reset 和 git revert

都是撤回提交

reset 是”时光机”,直接回到过去,之后的历史消失

revert 是”反向操作”,在历史上再加一笔”撤销”,原历史还在

已经push了,最好只用revert,除非你一个开发。

HTTP 状态码有哪些

  • 2xx 成功
    • 200 成功
    • 201 post/创建成功
    • 204 delete常用
  • 3xx 重定向
    • 301 永久重定向
    • 302 临时重定向
    • 304 协商缓存,本地缓存
  • 4xx 客户端error
    • 400 参数
    • 401 没有token
    • 403 有token没权限
    • 404 不存在
  • 5xx 服务端error
    • 500 内部错误
    • 502 Nginx转发错了
    • 503 服务挂了

GET 和 POST 的区别

GET默认有浏览器缓存,POS默认不缓存。

传参都可以有Body,URL参数,但是 RESTful API 设计规范

GET查询、POST新增、PUT修改、DELETE删除

说说 HTTP1.0 / 1.1 / 2.0 的区别

1.0 每次都建立新的TCP

1.1 持久连接,一个TCP连接可以多个请求,支持管道化,就是一个请求一个请求的来,会有阻塞问题

2.0 解决阻塞问题:一个 TCP 多个并行请求;1.x是文本协议,2.x是二进制;

3.0 用QUIC替换了TCP,解决了队头阻塞问题。目前就大厂和一些VPN用户在用。

WebSocket 是什么?和 HTTP 的区别?应用场景?

WebSocket 是一种全双工通信协议,连接后可以互相主动发消息,不需要轮询。

HTTP请求完就结束了。

WebSocket场景:实时聊天,客服,股票,监控,协同文档

说说回流(重排)和重绘的区别?如何优化?

回流:尺寸,位置,结构发生变化,开销大

重绘:外观变化、颜色、背景,不影响布局,开销比较小

回流一定触发重绘,重绘不一定触发回流。

优化手段:

  1. 合并修改width,height,margin或者加class
  2. 写一个虚拟DOM,写完再渲染
  3. CSS相关用transform替换left/top,使用will-change提升性能

CSS BFC 是什么?有什么作用?

BFC 块级格式化上下文,给元素加一个结界 作用:内外互不影响

以下可以触发BFC

  1. overflow 不为 visible
  2. display: flex / grid / inline-block
  3. position: absolute / fixed
  4. float 不为 none

说说 flex 布局的常用属性

flex-direction 方向

justify-content X轴

align-items Y轴

flex-wrap 换行

gap 间距

子元素: flex:1 等分剩余空间

order:1 排序

说说 CSS Grid 布局

二维布局,可以同时控制行和列,合适整体页面框架,表格布局

grid-template-columns 控制列

grid-template-rows 控制行

grid-template-areas 命名区域

说说 CSS 预处理器(Sass/Less)的理解

CSS预处理是对CSS扩展,增加了变量、嵌套、混入、函数一些功能,最终编译成CSS

现在趋势:Vue3也推荐用Sass,原生CSS的变量可以替代部分Sass的功能

说说响应式设计的原理和实现方式

响应式就是不同尺寸都有良好的效果

方式:

  1. 媒体查询
  2. 弹性单位 %,vw/vh,em
  3. 弹性布局 flex,grid

字体方案:

  1. vw方案(根据设计稿计算),使用postcss-px-to-viewport自动计算
  2. clamp 设置最小值和最大值

说说事件委托(事件代理)是什么?应用场景?

事件委托:利用事件冒泡,把子元素的事件监听器绑定到父元素上,由父元素统一处理。

// ❌ 每个 li 都绑定一个监听器
document.querySelectorAll('li').forEach(li => {
  li.addEventListener('click', handleClick)
})

// ✅ 委托给父元素,一个监听器搞定
document.querySelector('ul').addEventListener('click', (e) => {
  if (e.target.tagName === 'LI') {
    handleClick(e.target)
  }
})

说说 JavaScript 继承的几种方式

  1. 原型链继承
  2. 构造函数继承
  3. 组合继承
  4. ES6 Class继承(现代写法)

你是如何实现与蓝牙设备(BLE)通信的? (项目相关)

使用navigator.bluetooth

  1. 搜索,筛选 requestDevice
  2. 连接 connect
  3. 获取服务 用服务ID 拿到service
  4. 获取特征值 特征ID 拿到characteristic
  5. 使用characteristic,读取数据 / 监听通知 / 写入数
    1. 读取的时候会设计密码算法(各种公司各种设备都不同)
// 1. 请求设备(弹出选择框)
const device = await navigator.bluetooth.requestDevice({
  filters: [{ name: '变频器设备名' }],
  optionalServices: ['battery_service', 'your-service-uuid']
})

// 2. 连接 GATT 服务
const server = await device.gatt.connect()

// 3. 获取主服务
const service = await server.getPrimaryService('your-service-uuid')

// 4. 获取特征值(Characteristic)
const characteristic = await service.getCharacteristic('your-char-uuid')

// 5. 读取数据
const value = await characteristic.readValue()  // 返回 DataView

// 6. 监听通知(设备主动上报)
await characteristic.startNotifications()
characteristic.addEventListener('characteristicvaluechanged', (e) => {
  const data = e.target.value  // DataView
  const byte = data.getUint8(0)  // 读第一个字节
})

// 7. 写入数据(发指令给设备)
const command = new Uint8Array([0x01, 0x02, 0x03])
await characteristic.writeValue(command)

前端处理 16 进制数据时,ArrayBuffer 和 DataView 怎么用?

ArrayBuffer 是原始二进制数据的容器,不能直接读写,需要通过视图来操作。

DataView 是其中一种视图,可以精确控制读取的字节位置和数据类型。

蓝牙返回的数据是 DataView

蓝牙连接不稳定、丢包或数据延迟,前端做了哪些重试或兜底机制?

  1. 监测断开,提示用户,自动重连
  2. 丢包,超时,一般在300ms以内,过了时间就算超市,等待100ms左右,继续尝试,尝试2次,失败了标记,告诉用户检查设备指示灯或重新连接

硬件状态频繁上报时,前端如何保证渲染不卡顿?

  1. 节流控制更新频率
  2. requestAnimationFrame 批量更新
  3. 图表类数据用虚拟列表

动态表单引擎是如何设计的?

借鉴Vben Admin的Schema 结构设计,JSON 驱动表单,天然支持动态渲染和联动。

fields > key,name,label,required,reles,show,showWhen

大数据量列表渲染如何优化?虚拟列表原理是什么?

虚拟列表滚动

原理:只渲染可视区域内的条目,滚动时动态替换内容,DOM 节点数量始终保持很少。

列表监听scroll,动态更新 startIndex

可视区高度:500px
每条高度:50px
可视区最多显示:10条
那只渲染14条左右的数据

不定高的虚拟列表更为复杂,实际项目还是直接使用成熟的三方库 vxe-table、vue-virtual-scroller、Element Plus

JSBridge 原理是什么?H5 如何调用 iOS 原生能力?

  1. URL Scheme 假URL请求,原生拦截
  2. 封闭 window.webkit 方法 window.webkit.messageHandlers.scan.postMessage

iOS/Android 不同机型兼容性问题怎么排查和解决?

  1. 刘海屏/安全区(部分app需要背景全屏),使用 safe-area-inset

  2. 键盘弹起输入框被遮挡

    1. 监听focusin调整页面或者滚动页面
  3. IOS滚动/穿透,给body加上fixed overflow

    body { overflow: hidden; position: fixed; width: 100%; }

  4. Android 字体渲染不一致 * { -webkit-font-smoothing: antialiased; }

  5. 调试用chrome的chrome://inspect调试webview,IOS需要手动打包真机调试

Vue2 升级 Vue3 技术选型的思路?

先根据项目判断是否值得升级,长期/短期项目;

项目风险评估:检查依赖;

团队成本:Vue3学习成本,历史代理的改造量;

迁移思路: 先用兼容模式,将vue2在vue3的vite在跑起来。

逐步把Optino API改Composition API。

新功能必须用 Vue3,如果碰到依赖的vue2一并改造。

Vue2 和 Vue3 在 computed 和 watch 执行顺序

执行顺序上基本一致,响应式数据变化时先触发watch,再触发computed

为什么 JS 用单线程?Event Loop 存在的意义?

刚出生时是因为网面交互,为了避免并发问题,同一时刻既想删除DOM又想修改样式,如果多线程就冲突了。所以JS就一直采用单线程。

单线程就意味着时间长,所以就把网络请求,文件读写,定时器给浏览器(多线程环境)去处理。

任务队列 + Event Loop 的工作方式:

1. 主线程执行同步代码
2. 异步任务完成后,callback 进入任务队列
3. Event Loop 不断检查:主线程空了吗?空了就从队列里取任务执行
4. 回到步骤 1

Event Loop 就是两者协调的枢纽

为什么使用 JSVerbalExpressions?它解决了原生正则的什么痛点?

作用是匹配基因序列校验

链式调用,可读性好 ,可维护性高。 缺点就是性能略差原生正规。

前端高亮分析长篇基因序列数据,怎么做性能优化?

  1. 虚拟滚动
  2. 分段懒加载
  3. CSS优先 content-visibility: auto 不渲染看不到的地方
  4. Canvas 渲染

按钮级权限如何实现?

  1. vue的自定义指令,diretive中拿store做判断
  2. 封闭组件,原理是一样的,引入组件,传入权限别名(user.create)

路由级权限如何实现?动态路由 addRoutes

  1. 前端存储完整路由,用户登录后根据权限过滤出有权限的路由

  2. 用户权限发生变动,使用addRouter添加路由权限

TypScript 泛型在封装通用组件(如动态 Table)时如何使用?

泛型是为了使用组件和创建组件的时候用的数据类型是正确的。使用keyof T组件更安全。使用组件更方便,在ide中可以直接.出来

日常开发中如何利用 AI 辅助编程?有哪些排错或提效场景?

  1. 主要场景,代码生成,写组件。
  2. 老代码或遗留项目,功能和代码解读。
  3. 文档查询,比查文档快。

主要是辅助,核心逻辑和业务代码还是需要自己写。

要保证质量就要,Ai Review + 人工审核 + 单元测试

AI擅长重复性工作,但业务理解、系统设计、创造性问题还是人的强项

Cordova 到纯原生再到 Vue3,谈谈不同跨端技术的选型场景

  1. Crodova

    Webview 开发效率高,只需要安卓和Ios出一个壳子(Ai写就可以),一套代码跑全平台

    性能有瓶颈,复杂动画卡顿,全WebView的iOS可能会有审核问题。

    适合业务简单,交互动画不需要很酷炫或高级,内部工作,快速开发迭代

  2. 纯原生

    性能强,体验好

    多平台成本高

    高性能App,复杂交互,游戏

  3. React Native / Flutter

    JS能直接控制原生,一套代码双端,接近原生

    某底层能力受限,生态不如原生(国内)

  4. uniapp/vue3

    一键导出各种小程序

    不适合做App,只适合简单业务的小程序

RN受限地方:

1. 复杂的手势,拖拽没问题,多指,连笔性能不如原生 2. iOS后台问题,后台播放媒体经常失效。 3. 3D图形,RN 使用 WebGL 性能一般,这方面 Flutter 的 Skia 引擎强一些。

WebGL和 Flutter 的 Skia

​ WebGL 是”在浏览器里用 GPU 画一切”,Skia 是 Flutter 的”画板”,负责把 Dart 代码变成平台的像素。

面对紧急需求或技术难点(如第一次接触蓝牙通信),如何快速攻克?

  1. 拆解问题,问AI做计划。
    1. 不懂ble协议,先查文档,了解流程
  2. 先跑Demo
    1. 能跑能运行就行
    2. 能搜索到蓝牙
  3. 功能玄序渐进的加
    1. 功能一个一个测,测完再下一个
  4. 遇到问题要设置止损时间点
    1. 到点就换方案/救助,不能死磕

Vue 中自定义指令的应用场景有哪些?

  1. 常见权限控制
  2. 自动聚焦
  3. 图片懒加载
  4. 复制到剪贴板

React 核心关键词速记

  • JSX → UI语法(JS写HTML)
  • Component → 函数组件
  • Props → 组件传参
  • State → 组件状态

  • useState → 状态管理
  • useEffect → 副作用处理
  • useLayoutEffect → 同步副作用(阻塞渲染)
  • useMemo → 缓存值
  • useCallback → 缓存函数
  • useRef → 持久引用(不触发render)
  • useContext → 跨组件传值
  • useReducer → 复杂状态管理

  • React.memo → 组件缓存(props不变不渲染)
  • useMemo → 避免重复计算
  • useCallback → 避免函数重复创建
  • key → diff优化标识

  • render → 计算UI(纯函数)
  • commit → 更新DOM
  • diff → 找变化
  • Fiber → 调度机制(可中断)

  • 单向数据流 → 父 → 子
  • props → 传数据
  • callback → 子传父

  • react-router → 路由管理
  • BrowserRouter → 路由容器
  • Route → 路由配置
  • useNavigate → 跳转
  • useParams → 取参数

  • useEffect → 请求/订阅
  • cleanup → 清理副作用
  • debounce → 防抖
  • throttle → 节流

  • 组件拆分 → 提高复用
  • 自定义Hook → 逻辑复用
  • 受控组件 → 表单状态受控

  • useState → 局部状态
  • useContext → 跨层级
  • useReducer → 复杂逻辑
  • Redux → 全局状态
  • Zustand → 轻量状态库

  • Suspense → 异步加载占位
  • lazy → 组件懒加载
  • StrictMode → 开发检测
  • SSR → 服务端渲染
  • hydration → 客户端接管

小程序速记

  1. Page 定义页面逻辑 Page({})

  2. Component 定义组件 Component({})

  3. App 全局入口 App({})

  4. 插值 数据绑定

  1. wx:if 条件渲染(会销毁节点)
  1. hidden 控制显示隐藏(不会销毁)
  1. wx:for 列表渲染
  1. wx:key 列表唯一标识(优化渲染)

  2. block 不生成节点的容器

  1. bindtap 绑定事件(会冒泡)

  2. catchtap 阻止冒泡

  3. dataset 传递自定义数据

  1. e.currentTarget.dataset 获取数据

  2. data 页面数据 data: { count: 0 }

  3. setData 更新视图(核心API) this.setData({ count: 1 })

  4. 路径更新 局部更新优化 this.setData({ ‘list[0].name’: ‘xx’ })

  5. onLoad 页面加载(只执行一次)

  6. onShow 页面显示(每次触发)

  7. onReady 首次渲染完成

  8. onHide 页面隐藏

  9. onUnload 页面销毁

  10. wx.navigateTo 保留当前页面跳转

  11. wx.redirectTo 关闭当前页面跳转

  12. wx.switchTab 跳转 tab 页面

  13. wx.reLaunch 重置页面栈

  14. 页面栈(10层) 最大 10 层

  15. properties 父 → 子传值

  16. triggerEvent 子 → 父通信

  17. slot 内容分发(提高复用)

  18. wx.request 发起请求

  19. Promise封装 提高可维护性

  20. 减少 setData 避免频繁调用

  21. 合并 setData 批量更新

  22. 避免大数据传输 减少通信成本

  23. 分包加载 提升启动速度

  24. wx:if vs hidden 合理选择

  25. view 类似 div

  26. text 文本

  27. image 图片

  28. button 按钮

  29. input 输入框

  30. 双线程模型 逻辑层 + 渲染层

  31. 无 DOM 不能直接操作节点

  32. 数据驱动视图 通过 setData 更新 UI

  33. 必背“短句”

👉 双线程 小程序采用逻辑层和渲染层分离。

👉 setData 用于更新视图,但频繁调用会影响性能。

👉 生命周期 onLoad 只执行一次,onShow 每次进入都会触发。

👉 路由 navigateTo 保留页面,redirectTo 替换页面。

👉 组件通信 父传子用 properties,子传父用 triggerEvent。

👉 事件 bindtap 会冒泡,catchtap 阻止冒泡。

👉 setData 原理 & 性能优化

必答:

  • 数据从逻辑层 → 渲染层
  • JSON 序列化传输

👉 优化:

  • 批量更新
  • 避免大对象
  • 局部更新路径写法

项目: 我做了一个行李寄存预约小程序,用户可以填写取货地、还货地、取件时间、归还时间、联系人和类型来创建预约。项目里我把订单列表抽到了 MobX store 中做统一管理,用于跨页面共享订单数据;创建页主要维护表单本地状态,提交后调用 store action 创建订单;列表页通过 mobx-miniprogram-bindings 直接绑定 store,实现订单数据变化后的自动更新;详情页则展示订单状态,并模拟待审核、接单、寄存中、已退款、完成等状态流转。

**🧠 小程序本质 **

小程序是运行在微信环境中的轻量级应用,采用双线程架构,通过 setData 实现数据驱动视图。

**🧠 生命周期 **

onLoad 只执行一次,onShow 每次进入都会执行。

**🧠 路由 **

navigateTo 保留页面,redirectTo 替换页面,最多 10 层。

**🧠 性能 **

减少 setData,避免大数据传输。

**🧠 登录 **

wx.login 获取 code,后端换 openid 并返回 token。

🧠 支付

后端生成支付参数,前端调用 requestPayment。

小程序的优缺点