个人开发知识库(164-183)

· knowledge-base

164. 服务端渲染 (SSR) 与 Nuxt.js

SSR 的优势

  1. 更快的首屏加载速度:用户能更快看到页面内容,解决了 CSR 的“白屏”问题。
  2. 更好的 SEO:搜索引擎可以直接抓取到完整的页面内容,有利于搜索引擎优化。

Nuxt.js 是一个基于 Vue.js 的通用应用框架,专注于 UI 渲染,简化了 SSR 应用的开发。在 Nuxt.js 项目中,<nuxt /> 组件相当于 Vue Router 中的 <router-view />

Nuxt.js rem 布局

165. CSS 早期 Flexbox 属性

在现代 Flexbox 布局普及之前,存在一些旧版本的属性,如 box-orientbox-flex。它们的功能与现在的 flex-directionflex 类似。

box-orient

虽然现在已不推荐使用,但在维护旧项目或处理某些特定浏览器的兼容性问题时可能会遇到。

166. HTTP Content-Type 和 Content-Disposition

Content-Type

Content-Type 请求头用于告知服务器客户端发送的数据格式。

Content-Disposition

Content-Disposition 响应头用于告知浏览器如何处理响应体。

Content-Disposition

167. line-height 的数值用法

line-height 设置为一个没有单位的数值(如 line-height: 2)时,它的实际行高是根据元素自身的 font-size 计算的。例如,font-size: 16px; line-height: 2; 的计算行高就是 16px * 2 = 32px

这种用法具有良好的继承性,子元素会继承这个比例因子,并根据自己的 font-size 计算行高。

168. Object.create(null)

Object.create(null) 用于创建一个“纯净”的对象,这个对象完全没有原型链,即它的 __proto__null

优点

纯净对象

169. Symbol 数据类型

Symbol 是 ES6 引入的一种新的原始数据类型,表示独一无二的值。

const id = Symbol('description')
const obj = {
  [id]: 'This is a unique property'
}

console.log(obj[id]) // "This is a unique property"

Symbol 示例

170. ES6 Map 与 WeakMap

Map

Map 是一种键值对的集合,其键可以是任意类型的值。

WeakMap

WeakMap 是一种特殊的 Map,其键必须是对象,并且是“弱引用”。

WeakMap

171. 扩展运算符与深浅拷贝

扩展运算符 (...) 在处理对象和数组拷贝时,行为是浅拷贝

扩展运算符拷贝

要实现真正的深拷贝,需要使用 JSON.parse(JSON.stringify(obj)) (有局限性) 或递归函数等方法。

172. Object.keys() vs Object.getOwnPropertyNames()

for...in 循环和 JSON.stringify() 也只会处理可枚举属性。

属性可枚举性

173. JavaScript 连续赋值

var a = b = { n: 3 } 这样的连续赋值语句,是从右到左执行的。

  1. b = { n: 3 }: b 指向对象 { n: 3 }
  2. a = b: a 也指向 b 所指向的同一个对象。

面试题解析

let a = { n: 1 }
let b = a
a.x = a = { n: 2 }

console.log(a.x) // undefined
console.log(b.x) // { n: 2 }

解析

  1. ab 指向同一个对象 { n: 1 }
  2. a.x = a = { n: 2 } 这一行,先计算 = 右边的值,即 { n: 2 }
  3. 然后执行赋值,a.xa 此时仍然是旧对象 { n: 1 },所以 b 所指向的对象被添加了一个 x 属性,其值为 { n: 2 }
  4. 最后,变量 a 的引用被修改,指向了新对象 { n: 2 }
  5. 因此,新的 a 没有 x 属性,而旧的 a (即 b) 有了 x 属性。

连续赋值面试题

174. 小程序伪元素使用注意

在微信小程序中,伪元素 (::before, ::after) 的兼容性最好的是 view 标签。如果将伪元素直接应用在自定义组件的标签上,可能会因为组件内部结构的原因导致定位、样式等出现问题。

最佳实践:在自定义组件外部包裹一层 view 标签,并将伪元素样式应用在这层 view 上。

小程序伪元素

175. Git Cherry-pick

git cherry-pick <commit-hash> 命令用于将指定分支的单个或多个 commit “摘取”过来,合并到当前分支。

使用场景

操作步骤

  1. 切换到目标分支:git checkout main
  2. 执行 cherry-pick:git cherry-pick abcdefg (abcdefg 是源分支的 commit hash)

cherry-pick

176. 缓存问题排查

当遇到“相同代码,不同执行结果”的诡异问题时(尤其是在多环境部署下),应首先怀疑是缓存导致的。

排查步骤

  1. 强制刷新:在浏览器中使用 Ctrl + Shift + R (或 Cmd + Shift + R) 清除缓存并刷新页面。
  2. 清除应用缓存:如果是小程序或 App,尝试清除其缓存或重新安装。
  3. 检查构建产物:确认部署的静态资源是否为最新版本。
  4. CDN 缓存:如果使用了 CDN,可能需要手动刷新 CDN 缓存。

清除缓存

177. JavaScript 数据类型判断

判断 JavaScript 数据类型的常用方法:

  1. typeof: 能准确判断除 null 以外的原始类型,但对于所有引用类型(数组、对象等)都返回 'object'
  2. instanceof: 判断一个对象是否在另一个对象的原型链上,适合判断自定义类实例,但对跨 iframe 的对象无效。
  3. constructor: obj.constructor === Array,可以被修改,不可靠。
  4. Object.prototype.toString.call(): 最可靠的方法,能准确判断所有数据类型。
    Object.prototype.toString.call([]) // "[object Array]"
    Object.prototype.toString.call({}) // "[object Object]"
  5. Array.isArray(): ES5+ 提供的判断数组的最佳方法。

数据类型判断

178. 管理后台列表查询缓存

在管理后台开发中,列表页的查询条件通常需要被缓存,以便用户在返回列表页时能看到之前的筛选结果。

实现方式

  1. Vuex/Pinia:将查询条件存储在全局状态管理中。离开页面时不清除,返回页面时从 store 中恢复。
  2. Keep-alive:使用 Vue 内置的 <keep-alive> 组件缓存整个列表页组件的实例。当组件被缓存时,会触发 activated 钩子,可以在此钩子中处理刷新逻辑。
  3. 路由参数:将查询条件作为 URL 的查询参数。这是 RESTful 的做法,能让 URL 精确对应页面状态,便于分享和刷新。

keep-alive

179. align-content vs align-items

这两个 Flexbox 属性都用于控制交叉轴上的对齐,但作用范围不同:

align-content vs align-items

180. iframe vs web-view

主要区别在于运行环境和能力。<web-view> 作为原生组件,可以与 App/小程序进行更深度的交互(通过 JSBridge),而 <iframe> 只是一个纯粹的 Web 元素。

web-view

181. Node.js 版本管理

nvm 常用命令

nvm

182. Git 工作流与代码回滚

Git 三个区域

  1. 工作区 (Working Directory):你正在修改的文件。
  2. 暂存区 (Staging Area):通过 git add 添加,准备提交的文件。
  3. 本地仓库 (Local Repository):通过 git commit 提交后,文件快照永久保存的地方。

代码撤销/回滚

git 撤销

183. uniapp 调用原生能力

uniapp 通过 plus 对象来调用 HTML5+ 扩展规范,从而实现调用设备原生能力(如摄像头、文件系统、推送等)。

// #ifdef APP-PLUS
plus.nativeUI.toast('这是一个原生 Toast')
// #endif

plus 对象

_HBin Zhuang_ 📝