在上篇文章中,我们学习了BEM的命名规范及使用技巧,所谓知行合一,我又去学习了微信团队开发的weui库,也因此,对微信页面产生了一些想法,哪怕才疏识浅,也想要试一试。
远观微信
简略分析一下,从上图我们可以看见 微信的布局是分为三块的,head、body、foot,head中又有三个元素,body呢,有一个搜索框 ,下面是消息体,每条消息框有有头像(img),预读消息(message)、时间(time)。底部是四个导航栏。
布局
一、HTML命名布局
我们将微信新闻列表页面划分为几个主要的部分:头部、搜索栏、新闻列表、底部导航栏。以下是各个模块的HTML结构。
1. 头部模块
头部模块包括页面的标题和左右图标。使用 BEM 命名规范,将头部的HTML结构分为几个部分:
<div class="weui__header">
<div class="weui__header-icon weui__header-icon_left"><img src="./省略号.svg" alt="Left Icon"></div>
<div class="weui__header-title">微信</div>
<div class="weui__header-icon weui__header-icon_right"><img src="./加号.svg" alt="Right Icon"></div>
</div>
weui__header是一个 Block,表示页面头部。weui__header-icon是一个 Element,表示头部的图标。weui__header-icon_left和weui__header-icon_right是 Modifiers,表示图标的不同位置(左和右)。
2. 搜索栏模块
搜索栏模块包括输入框和搜索图标,结构如下:
<div class="weui-search-bar" id="search_bar">
<form class="weui-search-bar__form">
<div class="weui-search-bar__box">
<i class="weui-icon-search"></i>
<input type="search" class="weui-search-bar__input" placeholder="搜索" id="search_input">
<a href="#" class="weui-icon-clear"></a>
</div>
<label id="search_text" for="search_input" class="weui-search-bar__label">
<i class="weui-icon-search"></i>
<span>搜索</span>
</label>
</form>
<a href="#" class="weui-search-bar__cancel-btn">取消</a>
</div>
weui-search-bar是一个 Block,表示搜索栏。weui-search-bar__form是一个 Element,表示搜索表单。weui-search-bar__box是一个 Element,表示搜索框。weui-search-bar__input是一个 Element,表示搜索输入框。weui-search-bar__label是一个 Element,表示搜索标签。weui-search-bar__cancel-btn是一个 Element,表示取消按钮。
3. 新闻列表模块
新闻列表模块包括多条新闻项,每条新闻项包含图片、标题、描述和时间信息,结构如下:
<div class="weui-cells weui-cells_access">
<a class="weui-cell weui-cell_access" href="#">
<div class="weui-cell__hd">
<img src="https://via.placeholder.com/50" alt="News Image 1">
</div>
<div class="weui-cell__bd">
<p class="news-title">News Title</p>
<p class="news-description">This is a detailed description of news item</p>
</div>
<div class="news-time">今天 10:00</div>
</a>
</div>
weui-cells是一个 Block,表示新闻列表。weui-cell是一个 Element,表示单条新闻。weui-cell__hd是一个 Element,表示新闻图片。weui-cell__bd是一个 Element,表示新闻内容区域。news-title是一个独立的类,表示新闻标题。news-description是一个独立的类,表示新闻描述。news-time是一个独立的类,表示新闻时间。
4. 底部导航栏模块
底部导航栏包括多个导航项,每个导航项包含图标和标签,结构如下:
<div class="weui-navbar">
<a href="#" class="weui-navbar__item">
<i class="weui-navbar__icon">
<img src="./消息.svg" alt="Home">
</i>
<span class="weui-navbar__label">消息</span>
</a>
<a href="#" class="weui-navbar__item">
<i class="weui-navbar__icon">
<img src="./通讯录.svg" alt="Contacts">
</i>
<span class="weui-navbar__label">通讯录</span>
</a>
<a href="#" class="weui-navbar__item">
<i class="weui-navbar__icon">
<img src="./发现.svg" alt="Discover">
</i>
<span class="weui-navbar__label">发现</span>
</a>
<a href="#" class="weui-navbar__item">
<i class="weui-navbar__icon">
<img src="./我.svg" alt="Me">
</i>
<span class="weui-navbar__label">我</span>
</a>
</div>
weui-navbar是一个 Block,表示导航栏。weui-navbar__item是一个 Element,表示单个导航项。weui-navbar__icon是一个 Element,表示导航图标。weui-navbar__label是一个 Element,表示导航标签。
整个布局也不难,但是要完美完成,也不容易。元素标签的选择、放置,盒子的嵌套,都需要我们去考虑
二、CSS样式的选择和组合
在这个项目中,使用了flexbox布局来实现页面的响应式设计。以下是各个模块的CSS样式。
1. 头部模块
头部模块使用flexbox布局,使图标和标题在水平和垂直方向上都居中对齐,并且需要固定在顶部。
.weui__header {
display: flex;
align-items: center;
width: 100%;
background-color: #000;
padding: 10px 20px;
position: fixed;
top: 0;
z-index: 1000;
}
.weui__header-title {
flex: 80%;
color: white;
text-align: center;
font-size: 18px;
}
.weui__header-icon {
flex: 10%;
}
.weui__header-icon img {
margin: 0 10px;
}
这个设置可以让头部一直固定在顶部
position: fixed;
top: 0;
2. 搜索栏模块
搜索栏模块和新闻列表模块分别设置了不同的边距和填充,以确保布局的整齐和美观:
.weui-search-bar {
top: 45px;
width: 100%;
}
.weui-cells {
margin-top: 56px;
}
.news-time {
color: #888;
font-size: 12px;
}
3. 新闻列表模块
新闻列表模块的每个新闻项使用flexbox布局,使图片和文本内容整齐排列:
.weui-cell__hd img {
width: 50px;
height: 50px;
}
.news-title {
font-size: 16px;
}
.news-description {
color: #888;
font-size: 14px;
}
.news-time {
color: #888;
font-size: 12px;
}
4. 底部导航栏模块
底部导航栏模块依旧使用flexbox布局,百用不厌,使各个导航项均匀分布在导航栏中,并且每个导航项内部的图标和标签垂直对齐,同时和头部一样,也需要固定在底部。
.weui-navbar {
position: fixed;
bottom: 0;
width: 100%;
opacity: 0.99;
display: flex;
justify-content: space-around;
}
.weui-navbar__item {
display: flex;
flex-direction: column;
align-items: center;
color: white;
}
.weui-navbar__item.weui-bar__item_on {
color: #1AAD19;
}
.weui-navbar__icon {
font-size: 24px;
margin-bottom: 5px;
}
.weui-navbar__label {
font-size: 12px;
}
-
不知道大家有没有想过,如果没有
width: 100%;将会如何呈现。 -
同时这里可以设置一个透明度,因为发现手机微信上的底部还是有一点透明的
opacity: 0.99;
position: fixed;
bottom: 0;
width: 100%;
opacity: 0.99;
三、JavaScript逻辑
在这个项目中,JavaScript主要用于处理搜索栏的交互和底部导航栏的状态切换。
1. 搜索栏交互
点击搜索标签时,给搜索栏添加一个新的类weui-search-bar_focusing,为何呢,因为有些盲人也会使用,他们不能看见但能听见,使用如读屏器可以体验,weui的使命便是面向所有人,虽然我们是一个小demo 但也应该遵循一些理念。
document.querySelector('.weui-search-bar__label').addEventListener('click', function () {
document.querySelector('.weui-search-bar').classList.add('weui-search-bar_focusing');
});
这种方案的好处是清晰简单,只需操作DOM中的class属性,就能实现样式的动态切换。
2. 底部导航栏状态切换
为每个导航项添加点击事件监听器,当用户点击导航项时,切换对应图标的图片,同时将之前点击的图标恢复原样。
- 当然除了foreach循环还有其他方法,由于循环事件是同步的而点击事件是异步的
-
同步操作:会阻塞代码的执行,直到完成。例如,循环是同步的。
-
异步操作:不会阻塞代码的执行,它们的回调函数会被放入事件队列中,等待主线程空闲时执行。例如,事件处理器和定时器是异步的。
-
- 因此代码中使用了立即执行函数创建了一个闭包,闭包是什么呢?
document.querySelectorAll('.weui-navbar__item').forEach(tab => {
tab.addEventListener('click', function (event) {
event.preventDefault();
const img = tab.querySelector('img');
const newSrc = img.src.replace('.svg', '选中.svg');
if (window.lastClickedImg) {
window.lastClickedImg.src = window.lastClickedSrc;
}
window.lastClickedImg = img;
window.lastClickedSrc = img.src;
img.src = newSrc;
});
});
这种方案使用了全局变量来记录上一次点击的图标和图片路径,从而避免了复杂的状态管理逻辑。这种方式简单直接。这里留了一个问题,如果重复点击的话就会使得路径错误,大家想想应该怎么优化呢?
完整代码
- 代码中引入了WeUI 的压缩版 CSS 文件,它包含了 WeUI 所有的样式规则,可以用来给网页添加 WeUI 的设计风格。但也需要自己去调整一些需要的,内部样式优先级更高
- 同时demo中的icon图标都来自阿里巴巴矢量图标库 比如说底部我们可以找 消息和消息-点击 切换icon用于更好的点击交互
- 代码中当然还有很多的可优化方案 欢迎大家提出一起学习😀
总结
通过这个实战微信页面的案例,我们学习了如何使用BEM命名规范构建HTML结构,如何通过模块化CSS实现响应式布局,以及如何使用JavaScript实现基本的页面交互。BEM规范和模块化CSS可以提高代码的可读性和可维护性,而JavaScript则为页面添加了动态交互的能力。这些技术的结合使得我们能够构建出功能强大且易于维护的Web应用。