LocalStorage 与前端基础特性学习笔记

28 阅读5分钟

一、LocalStorage:浏览器端的持久化存储

localStorage 是 Web Storage API 的一部分,用于在浏览器端进行本地持久化存储。其主要特点如下:

  • 本地性:数据保存在用户浏览器中,不会发送到服务器。
  • 持久性:除非用户手动清除或通过代码删除,否则数据永不过期
  • 键值对结构:以 key => value 形式存储,但 value 只能是字符串类型
  • 容量限制:通常每个域名下有约 5~10MB 的存储空间(不同浏览器略有差异)。

使用要点

由于 localStorage 只能存储字符串,当我们需要存储对象、数组等复杂数据结构时,必须借助 JSON.stringify() 进行序列化;读取时则需用 JSON.parse() 反序列化

// 存储
localStorage.setItem('todos', JSON.stringify(items));

// 读取(注意容错)
const items = JSON.parse(localStorage.getItem('todos')) || [];

⚠️ 注意:JSON.parse(null) 会报错,因此务必使用 || [] 等默认值处理。

在本例中,我们实现了一个简单的“待办事项”(Todos)应用,所有任务列表都通过 localStorage 持久化保存,即使刷新页面也不会丢失。


二、CSS 继承机制:哪些属性会继承?

CSS 具有**继承(inheritance)**特性,但并非所有属性都会自动从父元素传递给子元素。

会继承的属性(典型):

  • color
  • font-family
  • font-size
  • line-height
  • text-align

这些属性若没有继承机制,开发者将不得不为每个子元素重复书写样式,极大增加维护成本。

不会继承的属性(典型):

  • background
  • width / height
  • margin / padding
  • border
  • display

这些属性通常与布局和盒模型相关,若自动继承反而会导致布局混乱。

理解继承机制有助于我们写出更简洁、高效的 CSS 代码,并合理利用 inheritinitialunset 等关键字控制样式行为。


三、outline 轮廓线:不影响布局的视觉反馈

outline 是一个常被忽视但非常实用的 CSS 属性。

  • 类似于 border,用于绘制元素外边的线条。
  • 关键区别outline 不占据盒模型空间,不会影响元素的尺寸、位置或周围布局。
  • 常用于表单控件的聚焦状态(如输入框获得焦点时的高亮效果)。

在本项目中:

.add-items input {
    outline: 5px solid rgba(34, 34, 192, 0.8);
}

这里自定义了输入框的轮廓样式,既提供了良好的可访问性(用户知道当前聚焦在哪),又不会破坏原有布局。

✅ 最佳实践:不要完全移除 outline(如 outline: none),除非提供其他聚焦指示方式,否则会影响键盘用户的操作体验。


四、overflow:控制内容溢出行为

overflow 属性用于处理容器内内容超出其边界的情况。

常用值:

  • visible(默认):内容溢出可见。
  • hidden:隐藏溢出部分。
  • scroll:始终显示滚动条。
  • auto:仅在需要时显示滚动条。

虽然本例中未显式使用 overflow,但在实际开发中,它常用于:

  • 防止文本溢出破坏布局;
  • 创建滚动区域(如聊天窗口、长列表);
  • 清除浮动(配合 overflow: hidden 触发 BFC)。

五、Flexbox 布局:现代弹性盒子模型

本项目大量使用了 Flexbox(弹性盒子) 实现居中与排列。

核心思想

Flexbox 创建了一个新的格式化上下文(Formatting Context),让子元素(flex items)能够根据容器(flex container)的设置灵活伸缩、对齐。

关键代码解析

html {
    box-sizing: border-box;
    min-height: 100vh;
    display: flex;
    justify-content: center; /* 主轴(水平)居中 */
    align-items: center;     /* 交叉轴(垂直)居中 */
}
  • display: flex<html> 变为弹性容器。
  • justify-content: center 使 .wrapper 在水平方向居中。
  • align-items: center 使其在垂直方向居中。
  • 结合 min-height: 100vh,确保即使内容很少,也能全屏居中。

此外,.plates li 也使用了 display: flex,让复选框图标与文字在同一行并合理分配空间:

.plates li {
    display: flex;
}
.plates label {
    flex: 1; /* 占据剩余空间 */
}

这种写法避免了使用 floatposition,代码更简洁、语义更清晰。


六、JavaScript 事件与函数式思维

1. 表单提交处理

addItems.addEventListener('submit', addItem);
  • 监听 submit 事件而非按钮点击,更符合语义。
  • addItem 中调用 event.preventDefault() 阻止页面刷新。

2. 事件委托优化性能

itemsList.addEventListener('click', toggleItem);
  • 不为每个 <li> 单独绑定事件,而是在父级 <ul> 上监听。
  • 利用事件冒泡机制,通过 event.target 判断实际点击元素。
  • 动态添加的项无需重新绑定事件,天然支持。

3. 函数式封装思想

“流程式代码超过10行,一定要封装函数。”

项目中将 UI 渲染逻辑封装为 populateList 函数:

function populateList(plates = [], platesList) {
    platesList.innerHTML = plates.map((plate, i) => `
        <li>
            <input type="checkbox" data-index="${i}" id="item${i}" ${plate.done ? 'checked' : ''}>
            <label for="item${i}">${plate.text}</label>
        </li>
    `).join('');
}

优点:

  • 复用性:添加、切换状态后均可调用。
  • 可维护性:渲染逻辑集中,修改只需改一处。
  • 默认参数:ES6 的 plates = [] 避免传参为 undefined 时报错。

七、CSS 技巧:用伪元素实现自定义复选框

原生 <input type="checkbox"> 样式难以定制,本项目采用“隐藏原生 + 伪元素替代”方案:

.plates input {
    display: none; /* 隐藏原生复选框 */
}

.plates input + label::before {
    content: "⬜️";
    margin-right: 10px;
}

.plates input:checked + label::before {
    content: "✅";
}

原理:

  • 利用 + 相邻兄弟选择器,当 <input> 被选中时,其后的 <label> 伪元素内容改变。
  • 用户点击 <label> 仍能触发 <input>checked 状态(因 forid 关联)。

这种方式兼顾了语义化(仍使用标准表单元素)与视觉定制


总结

本项目虽小,却涵盖了现代前端开发的多个核心知识点:

技术点应用场景
localStorage数据持久化
CSS 继承样式传递机制
outline可访问性与视觉反馈
Flexbox响应式布局与居中
事件委托性能优化
函数封装代码可维护性
伪元素技巧UI 定制

通过这样一个“本地待办事项”应用,我们不仅掌握了具体 API 的使用,更理解了如何组织代码、如何设计交互、如何平衡功能与用户体验——这正是前端工程化的精髓所在。