深入理解CSS继承与LocalStorage:从基础到实战应用
前端开发中,CSS的继承特性和LocalStorage的本地存储功能是两个非常重要且实用的概念。本文将结合具体代码示例,深入探讨这两个主题,并展示如何在实际项目中巧妙运用它们。
一、CSS继承属性详解
1.1 什么是CSS继承?
CSS继承是指某些CSS属性能够从父元素传递到子元素的特性。这一机制让我们的样式编写更加高效,避免了重复代码。 会继承的CSS属性:
- 字体相关:
font-family,font-size,font-weight等 - 文本相关:
color,text-align,line-height等 - 列表相关:
list-style-type等 - 可见性:
visibility等
不会继承的CSS属性:
- 盒模型相关:
width,height,margin,padding等 - 背景相关:
background-color,background-image等 - 定位相关:
position,top,left等 - 布局相关:
display,float,overflow等
1.2 继承实战分析
让我们通过一个具体例子来理解CSS继承:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css继承属性</title>
<style>
body{
background-color: green; /* body背景色设置为绿色 */
}
</style>
</head>
<body>
<p>Hello World</p>
<!-- overflow 属性不会被子元素继承 -->
<div style="overflow: hidden; font-size: 28px; height:300px; background-color:yellow; color:pink">
你好
<!-- height: inherit 明确指示子元素继承父元素的高度 -->
<p style="background-color: red;height: inherit;">三国演义</p>
</div>
<div>1111</div>
</body>
</html>
在这个例子中:
font-size和color会继承到子元素<p>中background-color不会继承,所以子元素设置了红色背景overflow: hidden不会继承,子元素不受影响height: inherit明确指示子元素继承父元素的高度
1.3 控制继承的CSS值
CSS提供了几个特殊值来控制继承行为:
inherit:明确继承父元素的值initial:使用属性的初始值unset:如果是继承属性则继承,否则使用初始值
二、CSS Reset与全局样式设置
在现代前端开发中,合理的CSS重置和全局设置至关重要:
html{
box-sizing: border-box; /* 设置盒模型为border-box */
min-height: 100vh; /* 最小高度为视口高度 */
display: flex; /* 弹性格式化上下文 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
text-align: center; /* 文本居中 */
}
/* 通配符选择器,应用于所有元素及伪元素 */
*,*::before,*::after{
box-sizing: inherit; /* 继承盒模型设置 */
}
.wrapper{
padding: 20px;
max-width: 350px;
background-color: rgba(255, 255, 255, 0.95); /* 半透明白色背景 */
box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1); /* 盒子阴影:水平偏移 垂直偏移 模糊半径 扩散半径 */
}
h2{
text-align: center;
margin: 0;
font-weight: 200; /* 细体字 */
}
.plates{
margin: 0;
padding: 0;
text-align: left;
list-style: none; /* 移除列表默认样式 */
}
.plates li{
border-bottom: 1px solid rgba(0, 0, 0, 0.2); /* 底部边框 */
padding: 10px 0;
font-weight: 100;
display: flex; /* 设置弹性格式化上下文 */
}
.plates label{
flex: 1; /* 弹性布局,占满剩余空间 */
/* cursor属性用于设置鼠标指针在元素上时显示的光标样式 pointer表示可以点击的手型👆👆 */
cursor: pointer;
}
.plates input{
display: none; /* 隐藏原生checkbox */
}
/* 使用伪元素自定义checkbox样式 */
.plates input + label:before{
content: "⬜⬜️"; /* 未选中状态 */
margin-right: 10px;
}
.plates input:checked + label:before{
content: "✅"; /* 选中状态 */
}
.add-items{
margin-top: 20px;
}
.add-items input{
padding: 10px;
outline: 5px solid rgba(14, 14, 211, 0.8); /* 轮廓线,不占据布局空间 */
border: 1px solid rgba(0, 0, 0, 0.1);
}
这段代码做了以下几件事:
- 盒模型统一:通过
box-sizing: border-box让所有元素的宽度计算包含padding和border - 继承盒模型:使用
box-sizing: inherit确保所有元素和伪元素都继承这一设置 - Flexbox居中:通过Flexbox实现完美的垂直水平居中
- 自定义表单控件:通过CSS伪元素自定义checkbox样式
三、LocalStorage深度解析
3.1 LocalStorage基础
LocalStorage是HTML5提供的Web Storage API的一部分,用于在浏览器中持久存储数据。 主要特性:
- 存储容量:通常为5MB左右
- 生命周期:数据永久存储,除非手动清除
- 作用域:同一域名下的所有页面共享
- 数据类型:仅支持字符串存储
3.2 LocalStorage核心API
// 存储数据
localStorage.setItem('key', 'value');
// 读取数据
const data = localStorage.getItem('key');
// 删除特定数据
localStorage.removeItem('key');
// 清空所有数据
localStorage.clear();
// 获取键名
const keyName = localStorage.key(index);
3.3 实战:TodoList应用
下面是一个完整的TodoList应用,结合了CSS继承和LocalStorage:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LocalStorage Todos</title>
<link rel="stylesheet" href="./common.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading tapas....</li>
</ul>
<form class="add-items">
<input
type="text"
placeholder="Item Name"
required
name="item"
>
<input type="submit" value="+ Add Item">
</form>
</div>
<script>
// 获取DOM元素
const addItems = document.querySelector('.add-items');
const itemList = document.querySelector('.plates');
// 从localStorage读取数据,如果没有则初始化为空数组
const items = JSON.parse(localStorage.getItem('todos'))||[];
// 函数式封装,拒绝流程式代码
// 封装实现的细节,比较难,封装的人和调用的人是两波人
// 复用
// 函数默认值是es6
// 流程式代码超过10行,一定要封装函数
function populateList(plates=[],platesList){
platesList.innerHTML= plates.map((plate,i)=>{
return `
<li>
<input type="checkbox" data-index=${i} id="item${i}"
${plate.done?'checked':''} <!-- 根据完成状态设置checked属性 -->
/>
<label for="item${i}">${plate.text}</label>
</li>
`
}).join('') // 将数组转换为字符串
}
function addItem(event){
event.preventDefault(); // 阻止默认行为(表单提交刷新页面)
console.log('/////////')
// 函数执行的时候会有this 事件处理函数的时候,指向form
const text = (this.querySelector('[name=item]').value.trim()) // 获取表单的值,.trim()用于移除字符串两端的空白值
const item = {
text,
done:false
}
items.push(item);
// 持久化存储key=>value
localStorage.setItem('todos',JSON.stringify(items))
populateList(items,itemList);
this.reset() // 清空表单内容
}
function toggleDone(event){
const el=event.target
console.log(el.tagName,'?/?/')
// 使用事件委托,只处理checkbox的点击
if(el.tagName == 'INPUT'){
const index= el.dataset.index;
items[index].done = !items[index].done
localStorage.setItem('todos',JSON.stringify(items));
populateList(items,itemList);
}
}
// 事件监听
addItems.addEventListener('submit',addItem);
itemList.addEventListener('click',toggleDone) // 事件委托模式,给父元素ul绑定来监听所有子元素
// 初始渲染
populateList(items,itemList);
</script>
</body>
</html>
四、代码优化与最佳实践
4.1 函数封装的重要性
从上面的代码中我们可以看到良好的函数封装习惯:
// 不好的写法:流程式代码
// 直接写操作逻辑,难以复用和维护
// 好的写法:函数式封装
function populateList(plates = [], platesList) {
// 封装渲染逻辑
}
function addItem(event) {
// 封装添加逻辑
}
function toggleDone(event) {
// 封装状态切换逻辑
}
封装的好处:
- 复用性:可以在多个地方调用同一个函数
- 可维护性:修改逻辑只需在一个地方进行
- 可读性:函数名清晰表达意图,代码更易理解
- 团队协作:不同开发者可以并行工作
4.2 事件委托的巧妙运用
// 传统方式:为每个元素单独绑定事件
// 当列表项很多时性能较差
// 事件委托方式:只在父元素上绑定一个事件监听器
itemList.addEventListener('click', toggleDone);
事件委托的优势:
- 性能优化:减少事件监听器数量
- 动态元素支持:对新添加的元素自动生效
- 内存效率:避免内存泄漏
4.3 CSS继承的实际应用
在项目中合理运用CSS继承:
/* 在父元素设置,子元素继承 */
.plates li {
font-weight: 100; /* 子元素会继承此字体粗细 */
color: #333; /* 子元素会继承此颜色 */
}
/* 明确继承 */
.plates input:checked + label {
color: inherit; /* 明确继承父元素颜色 */
}
五、总结
通过这个完整的TodoList项目,我们深入理解了:
- CSS继承机制:如何合理利用继承减少代码重复
- LocalStorage应用:实现数据的持久化存储
- 现代JavaScript编程:函数式封装、事件委托等最佳实践
这个项目展示了前端开发中多个重要概念的有机结合,是学习现代Web开发的优秀范例。掌握这些技术后,你可以轻松构建出功能完善、用户体验良好的Web应用。 关键要点回顾:
- CSS继承让样式更简洁易维护
- LocalStorage提供客户端持久化存储能力
- 函数封装提高代码质量和可维护性
- 事件委托优化性能和动态内容处理