一、前端的布局方式有哪些?
以下将列出部分布局方式及其简单举例
1.流式布局(Flow Layout):
传统的HTML布局,元素按照它们在文档中出现的顺序排列。
<div>这是一个流式布局的div。</div> <p>这是段落文本。</p>
优点:
- 灵活性:流式布局可以根据不同的屏幕尺寸和分辨率自适应调整,提供更灵活的显示效果。
- 响应性:流式布局是响应式设计的基础,能够适应各种设备,包括手机、平板和桌面电脑。
- 用户体验:由于布局能够自适应,用户在不同设备上浏览网页时可以获得一致的体验。
- 维护简便:相比固定宽度的布局,流式布局通常只需要设置一套样式规则,减少了维护的复杂性。
- 内容优先:流式布局强调内容的重要性,布局会根据内容的多少自动调整,避免出现过多的空白。
缺点:
- 控制性差:由于布局元素的尺寸会随浏览器窗口变化,因此在某些情况下可能难以精确控制元素的布局和间距。
- 设计限制:对于一些需要固定布局或特定排版的设计,流式布局可能无法满足需求。
- 性能问题:在某些情况下,流式布局可能需要更多的计算来适应不同的屏幕尺寸,这可能会影响页面加载速度。
- 兼容性问题:尽管现代浏览器普遍支持流式布局,但在一些老旧的浏览器上可能会出现兼容性问题。
- 过度滚动:在小屏幕上,流式布局可能导致内容过宽,用户需要水平滚动来查看全部内容,影响阅读体验。
2.弹性布局**(Flexible Box Layout,Flexbox)**:
一种更加高效的布局方式,允许容器内元素在不同屏幕尺寸下动态调整大小和排列。
<div class="container"> <div>Flex 1</div> <div>Flex 2</div> </div> .container { display: flex; flex-direction: row; /* 或者 column */ justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ }
优点:
- 空间分配:易于在容器内分配空间。
- 对齐与分布:提供丰富的对齐和分布选项。
- 响应式设计:支持不同屏幕尺寸的自适应布局。
- 简化代码:减少CSS代码量,提高开发效率。
- 兼容性:现代浏览器广泛支持。
缺点:
- 学习曲线:需要时间学习Flexbox的属性和行为。
- 旧浏览器兼容性:可能需要额外的前缀或polyfills支持。
- 过度使用:可能导致布局复杂,难以维护。
- 性能影响:在处理大量元素时可能影响性能。
- 特定布局限制:对于某些复杂布局,可能不如CSS Grid直观。
3.网格布局(Grid Layout):
一种二维布局系统,可以创建复杂的行和列布局,非常适合复杂的页面布局。
html:
<div class="grid-container"> <div>Grid 1</div> <div>Grid 2</div> <div>Grid 3</div> </div>
css:
.grid-container { display: grid; grid-template-columns: auto 1fr auto; /* 定义三列 */ grid-gap: 10px; }
优点:
- 二维布局:同时控制行和列的布局方式。
- 灵活性:可以创建复杂的布局结构。
- 对齐与分布:提供丰富的对齐和分布选项。
- 响应式:易于实现响应式设计。
- 控制性:对布局的控制力强,易于实现精确布局。
缺点:
- 学习曲线:相对于其他布局模型,学习成本较高。
- 浏览器兼容性:尽管现代浏览器支持良好,但一些旧浏览器可能不支持或需要polyfills。
- 性能问题:在处理大量网格项时可能影响性能。
- 过度使用:可能导致布局过于复杂,难以维护。
4.浮动布局(Float Layout):
通过CSS的
float
属性使元素脱离文档流,通常用于创建多列布局。html:
<div class="float-left">浮动到左边</div> <div>右侧内容</div>
css:
.float-left { float: left; width: 50%; }
优点:
- 简单性:浮动是CSS中的基本特性,易于理解和使用。
- 兼容性:几乎所有的浏览器都支持浮动。
缺点:
- 布局限制:难以创建复杂的布局结构。
- 维护性:浮动元素脱离文档流,可能导致布局混乱。
- 响应性:需要额外的技巧来实现响应式设计。
- 清除浮动 :需要使用
clear
属性或额外的元素来清除浮动,以避免布局问题。5.定位布局(Positioned Layout):
使用CSS的
position
属性(如relative
,absolute
,fixed
,sticky
)来控制元素的位置。html:
<div class="relative"> <div class="absolute">绝对定位元素</div> </div>
css:
.relative { position: relative; } .absolute { position: absolute; top: 20px; left: 20px; }
6.响应式布局(Responsive Layout):
利用媒体查询(Media Queries)来根据设备特性(如屏幕尺寸、分辨率)调整布局。
css:
@media (max-width: 600px) { .container { flex-direction: column; } }
优点:
- 自适应性:能够适应不同屏幕尺寸和设备。
- 用户体验:提供一致的浏览体验,无论设备大小。
- 维护性:通常只需要一套样式表,简化维护。
- 搜索引擎优化:响应式设计有助于提高网站的SEO表现。
缺点:
- 复杂性:实现响应式设计可能需要更复杂的CSS和JavaScript。
- 性能:响应式图片和媒体查询可能会影响页面加载速度。
- 测试:需要在多种设备和分辨率上进行测试,以确保兼容性。
- 控制性:在某些情况下,响应式设计可能难以实现精确的布局控制。
7.自适应布局(Adaptive Layout):
根据设备类型或屏幕尺寸范围提供不同的布局设计。
.container { width: 100%; max-width: 1200px; /* 最大宽度 */ margin: 0 auto; /* 水平居中 */ }
8.框架布局(Frame Layout):
使用框架(如
<iframe>
或<frame>
)来嵌入其他页面或内容。9.单列布局(Single-column Layout):
将内容分成多个垂直列,类似于报纸的布局。
<div class="single-column"> 内容从上到下排列。 </div>
10.圣杯布局(Holy Grail Layout):
一个经典的三列布局,中间列宽度可变,两侧列固定宽度。
html:
<div class="container"> <div class="sidebar">侧边栏1</div> <div class="content">主要内容</div> <div class="sidebar">侧边栏2</div> </div>
css:
.container { display: flex; justify-content: space-between; } .sidebar { flex: 1; } .content { flex: 3; }
11.CSS框架布局:
使用CSS框架(如Bootstrap, Foundation, Tailwind CSS等)提供的预定义类和组件来快速构建布局。
html:
<div class="container"> <div class="row"> <div class="col-md-4">列1</div> <div class="col-md-4">列2</div> <div class="col-md-4">列3</div> </div> </div>
12.视口单位布局(Viewport Units Layout):
使用视口宽度(
vw
)、视口高度(vh
)等单位来创建响应式元素尺寸。html:
<div class="full-screen">全屏元素</div>
css:
.full-screen { width: 100vw; /* 视口宽度 */ height: 100vh; /* 视口高度 */ }
二、vw、vh是什么?
vw
和vh
是CSS中用于布局的视口单位(Viewport Units)。
vw
:视口宽度的百分比(Viewport Width)。1vw
等于视口宽度的1%。例如,如果视口宽度是100个单位,那么10vw
就是10个单位。这个单位常用于创建响应式设计,因为它会根据视口宽度的变化而变化。
vh
:视口高度的百分比(Viewport Height)。1vh
等于视口高度的1%。与vw
类似,vh
也是根据视口高度来计算的。这允许元素的高度能够根据视口的高度自适应变化。
三、JavaScript中原型链和类继承有什么区别?
JavaScript中的原型链和类继承是两种不同的概念,它们用于实现代码的复用和继承特性。以下是原型链和类继承的主要区别:
1.实现方式:
- 原型链 :基于原型的对象继承。在JavaScript中,每个对象都有一个内部属性
[[Prototype]]
(可以通过__proto__
访问),它指向了创建该对象时所用构造函数的原型对象。属性和方法的查找会沿着这个原型链进行。- 类继承 :基于ES6中引入的
class
语法。类继承实际上是语法糖,其背后仍然使用原型链来实现。class
允许你定义一个构造函数,并使用extends
关键字来实现继承。2.语法:
- 原型链 :使用构造函数和显式的原型对象(
prototype
)来定义对象的结构和行为。- 类继承 :使用
class
关键字来定义类,并通过extends
关键字来实现类的继承。3.可读性:
- 原型链:原型链的继承可能难以追踪,尤其是在多层继承的情况下。
- 类继承:提供了更清晰和直观的语法,使代码更容易理解和维护。
4.构造函数的使用:
- 原型链 :在原型链继承中,构造函数可以通过
call
或apply
方法被调用,以确保能正确设置this
的上下文。- 类继承 :在类继承中,子类的构造函数会自动调用父类的构造函数(使用
super()
),确保this
的上下文被正确设置。5.方法访问:
- 原型链:方法必须定义在原型对象上,所有实例共享这些方法。
- 类继承 :方法可以定义在类体内,每个子类实例都可以有自己的方法实例,也可以通过
static
关键字定义静态方法。6.私有属性和方法:
- 原型链:没有真正的私有属性或方法,但可以使用闭包来模拟。
- 类继承 :可以使用
#
前缀定义私有字段和方法,提供了更好的封装性。7.多重继承:
- 原型链:可以通过组合多个原型来实现多重继承的效果。
- 类继承:不支持直接的多重继承,但可以通过混入(mixins)或其他模式来实现类似的效果。
8.性能:
- 原型链:由于原型链的查找可能涉及多个对象,可能会有轻微的性能开销。
- 类继承:由于JavaScript引擎的优化,类继承的性能通常与原型链相当。
9.兼容性:
- 原型链:所有JavaScript引擎都支持原型链。
- 类继承 :较新的JavaScript引擎支持
class
关键字,但一些旧的浏览器可能需要转译。
四、【算法】删除有序数组中的重复项
题目:
给你一个 非严格递增排列 的数组
nums
,请你**原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回nums
中唯一元素的个数。考虑
nums
的唯一元素的数量为k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。- 返回
k
。判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案 int k = removeDuplicates(nums); // 调用 assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; }
如果所有断言都通过,那么您的题解将被 通过。
示例 1:
输入: nums = [1,1,2]
输出: 2, nums = [1,2,_]
解释: 函数应该返回新的长度 2**,并且原数组** nums 的前两个元素被修改为 1 , 2 。 不需要考虑数组中超出新长度后面的元素。示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
已按 非严格递增 排列int removeDuplicates(int* nums, int numsSize) {
}
题解:
我们可以使用双指针的方法。
首先,检查数组的大小,如果为 0,则返回 0。
初始化一个指针
k
为 1,因为我们至少有一个唯一的元素。遍历数组,从第二个元素开始,比较当前元素和前一个元素:如果两个元素不同,就意味着找到了一个新的唯一元素,我们将其放到
k
指向的位置,并将k
增加 1。循环结束后,返回
k
,这就是去重后的数组中唯一元素的个数。int removeDuplicates(int* nums, int numsSize) {
if (numsSize == 0) {
return 0; // 如果数组为空,返回 0
}int k = 1; // k 初始化为 1,因为至少存在一个唯一元素 for (int i = 1; i < numsSize; i++) { // 只要当前元素与前一个元素不同,就将其放置在 k 的位置 if (nums[i] != nums[k - 1]) { nums[k] = nums[i]; k++; // 增加 k 的大小 } } return k; // 返回唯一元素的个数
}