实现了一个简单的前端开发移动端瀑布流布局的方案
-
HTML部分:
- 页面使用了Flex布局,整体分为顶部导航栏和内容区域两部分。
- 导航栏包含若干个导航选项,并使用Font Awesome图标库的搜索图标作为过滤器。
- 内容区域为瀑布流布局,采用两列显示,并使用
list-warpper
和list-item
样式。
-
CSS部分:
- 定义了页面的整体样式,包括顶部导航栏、瀑布流布局和列表项的样式。
- 导航栏选项在激活和悬停时有不同的背景和颜色变化。
- 使用Flex布局实现瀑布流布局,设置了两列,
column-gap
用于设置列之间的间隔。
-
Vue.js部分:
- 创建一个Vue实例,将其绑定到
#app
元素上。 - 在
data
中定义了navList
,list
和currentId
三个数据。 navList
表示导航栏的选项列表,包含id
和title
字段。list
是一个包含20个模拟列表项的数组,每个项都有title
、desc
、img
和id
字段,分别表示标题、描述、图片和ID。currentId
用于存储当前选中的导航栏选项或列表项的ID,默认为1。- 在
methods
中定义了一个handleClick
方法,用于处理导航栏选项或列表项的点击事件。点击时会将对应的ID赋值给currentId
,实现选中状态的切换。
- 创建一个Vue实例,将其绑定到
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#app {
display: flex;
flex-direction: column;
height: 100vh;
background: #f7f7f7;
}
.header {
flex-shrink: 0;
height: 50px;
background: #26a69a;
display: flex;
align-items: center;
justify-content: space-between;
}
.content {
flex: 1;
display: flex;
overflow: hidden;
width: 100vw;
margin-top: 10px;
}
.nav-warrper {
font-family: 'Microsoft YaHei';
font-size: 20px;
white-space: nowrap;
display: flex;
align-items: center;
height: 100%;
padding:0 5px;
}
.nav-item {
padding: 0 20px;
color: #fff;
}
.nav-item.active {
color: #000;
background: #fff;
transition: all .3s;
}
.nav-item:hover{
background: #fff;
color: #000;
transition: all .3s;
cursor: pointer;
}
.left {
flex-shrink: 0;
width: 100px;
background: #26a69a;
}
.right {
flex: 1;
display: flex;
flex-direction: column;
}
.filter {
flex-shrink: 0;
padding: 10px;
background: #26a69a;
/* 左边增加白色阴影 */
position: relative;
}
.list-warpper{
flex: 1;
overflow: scroll;
padding: 10px;
column-gap: 10px;
column-count: 2;
}
.list-item{
flex-shrink: 0;
min-width: calc(50% - 10px);
box-sizing: border-box;
overflow: hidden;
align-self: flex-start;
background-color: #fff;
margin-bottom: 10px;
/* 左上和右上圆角5px */
border-top-left-radius: 5px;
border-top-right-radius: 5px;
/* 增加阴影 */
box-shadow: 0 0 10px #00000030;
}
</style>
</head>
<body>
<div id="app">
<header>
<div class="header">
<div class="nav-warrper">
<div :class="item.id===currentId?'active':''" class="nav-item" v-for="item in navList" :key="item.id" @click="handleClick(item.id)">{{item.title}}</div>
</div>
<div class="filter">
<i class="fa fa-search" style="font-size:20px"></i>
</div>
</div>
</header>
<div class="content">
<div class="list-warpper">
<div class="list-item" v-for="item in list" :key="item.id" @click="handleClick(item.id)">
<div class="img-warpper">
<img :src="item.img" alt="">
</div>
<div class="title">{{item.title}}</div>
<div class="desc">{{item.desc}}</div>
</div>
</div>
</div>
</div>
</body>
<script>
// 创建vue实例
const app = new Vue({
el: '#app',
data: {
navList: [
{ id: 1, title: '首页' },
{ id: 2, title: '分类' },
{ id: 3, title: '购物车' },
{ id: 4, title: '我的' },
],
// 模拟一个列表数据,长度为20,有标题、图片、id、描述等字段
list: Array.from({ length: 20 }).map((item, index) => {
return {
title: `标题${index}`,
// 描述生成一个随机文字,长度10-30,用于区分不同的描述
desc: Array.from({ length: Math.floor(Math.random() * 100 + 10) }).map(() => {
return '描述'
}).join(''),
img: `https://picsum.photos/200/200?random=${index}`,
id: index,
// desc: `描述${index}`
}
}),
// 用于存储当前选中的id
currentId: 1,
},
methods: {
// 点击列表项时触发
handleClick(id) {
// 将当前选中的id赋值给currentId
this.currentId = id
}
}
})
</script>
</html>