vue 实现类朋友圈浏览界面
移动端需要适应不同屏幕大小。
1.固定样式,width和height都固定,不管屏幕多大,我就是那么大。
2.使用rem,每个样式都用rem单位,width、height、font-size等都用,然后根据屏幕大小设置不同的rem,比如规定小屏1rem=10px,中屏1rem=20px,大屏1rem=30px,然后就世界有多大,我的心就有多大,Holle World!(这个我目前没试过,感觉是可以的)
3.配合各种ui,像amaziui会有根据屏幕大小等分宽度,或者不同比例的宽的,这个时候要控制高度等于宽度需要用js控制。
这里要求实现后按f12、拖动边框,图片还是会正方形缩放,我用的是第3种。
先上图:
样式图HTML
写出html结构,vue绑数据的部分可以先写死了,列表渲染部分也可以多复制粘贴几列。下面的是最后完善版的,大概看一下吧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue类朋友圈浏览界面</title>
</head>
<body>
<div id="app">
<!--整一块-->
<div class="am-g am-g-collapse moments" v-for="(item , index) in momentsData">
<!--左边头像部分-->
<div class="am-u-sm-2 moments-icon">
<img :src="item.icon" alt="用户头像">
</div>
<!--右边内容部分-->
<div class="am-u-sm-10">
<!--名字与倒计时-->
<div class="am-g am-g-collapse">
<div class="am-u-sm-9 am-text-left moments-name">{{item.mane}}</div>
<div class="am-u-sm-3 am-text-center moments-time">{{item.time}}</div>
</div>
<!--发表的文字-->
<div class="am-g am-g-collapse moments-diary">
{{item.diary}}
</div>
<!--晒的图片-->
<div class="am-g am-g-collapse moments-photos">
<ul class="am-avg-sm-3 am-thumbnails">
<!--这里的 :style="{height: Height+'px'}"通过js操作Height的数据使其等于该元素的宽-->
<li :style="{height: Height+'px'}" v-for="(url,index) in item.photos" class="getWidth">
<img class="am-thumbnail" :src="url" />
</li>
</ul>
</div>
<!--点赞部分-->
<div class="am-g am-g-collapse">
<ul class="am-u-sm-10 moments-like-image">
<li v-for="(image,index) in item.likeImage">
<img :src="image" />
</li>
</ul>
<div class="am-u-sm-2 am-text-center moments-like">
<span :class="item.heartStatus ? 'am-icon-heart' : 'am-icon-heart-o'" @click="changeHeart(item)"></span>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
CSS
样式使用amaziui,在头部引入
<link rel="stylesheet" href="http://cdn.amazeui.org/amazeui/2.7.2/css/amazeui.min.css">
然后加以修改
.moments {
border-bottom: 1px solid #EFEFEF;
padding-top: 15px;
padding-bottom: 15px;
}
.moments .moments-icon{
display: flex;
justify-content: center;
}
.moments .moments-icon img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
margin: 0;
padding: 0;
}
/**这些媒体查询都是根据屏幕大小改变头像和点赞部分图片的大小,设置了三层**/
@media screen and (min-width: 767px) {
.moments .moments-icon img {
width: 8.5rem;
height: 8.5rem;
}
.moments-like-image li {
width: 5rem;
height: 5rem;
}
.moments-like span {
font-size: 4rem;
}
}
@media screen and (min-width: 450px) and (max-width: 767px) {
.moments .moments-icon img{
width: 6.5rem;
height: 6.5rem;
}
.moments-like-image li {
width: 4rem;
height: 4rem;
}
.moments-like span {
font-size: 3rem;
}
}
@media screen and (max-width: 450px) {
.moments .moments-icon img{
width: 4.5rem;
height: 4.5rem;
}
.moments-like-image li {
width: 3rem;
height: 3rem;
}
.moments-like span {
font-size: 2rem;
}
}
.moments .moments-name{
font-size: 1.5rem;
color: #E298A5;
line-height: 2.5rem;
}
.moments .moments-time{
font-size: 1.3rem;
color: #AAAAAA;
line-height: 2.5rem;
}
.moments-diary {
padding-right: 1rem;
color: #000;
font-size: 1.3rem;
margin-top: 10px;
margin-bottom: 20px;
}
.moments-photos img {
border-radius: 5px;
}
.moments-photos {
padding-right: 2rem;
padding-bottom: 1.5rem;
}
.moments-photos .am-thumbnail{
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
margin: 0;
padding: 0;
border: none;
}
.moments-like-image {
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
margin: 0;
}
.moments-like-image li {
list-style: none;
margin: .2rem;
}
.moments-like-image li img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
margin: 0;
padding: 0;
border-radius: 50%;
}
.am-icon-heart-o , .am-icon-heart {
color: #E298A5;
}
javascript 部分
使用了vue,先引入vue,这里使用cdn方法引入:
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js "></script>
使用了一堆本地假数据来模拟,用js方法来控制晒的图片的高度,实现点击红心更改样式及增加点赞头像,详细看注释吧。
js选择元素的方法有以下几项:
1、document.getElementById("domId")
2、document.getElementsByName("domName")
3、element.getElementsByTagName("tagName");element是有效的DOM元素(包括document)
4、element.getElementsByClassName("classNames");element是有效的DOM元素(包括document)
5、document.querySelectorAll(".getWidth");selector为合法的CSS选择器,返回值是一个nodeList集合(不是Array)
<script type="text/javascript ">
new Vue({
el: '#app',
data: {
Height: "",
//虚拟数据
dengqianyonghu: {
icon: "https://i.loli.net/2018/08/10/5b6d0311bc6b2.jpg",
mane: "张三丰丰丰丰丰",
time: "1小时前",
diary: "发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈",
},
momentsData: [{
icon: "https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
mane: "张三丰丰丰丰丰",
time: "1小时前",
diary: "发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg"
],
heartStatus: false
},
{
icon: "https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
mane: "李四",
time: "9小时前",
diary: "又又又又又发朋友圈发朋友友圈",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
heartStatus: false
},
{
icon: "https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
mane: "zhaoming",
time: "13小时前",
diary: "又又又又又发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
heartStatus: false
},
{
icon: "https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
mane: "韩菲菲",
time: "21小时前",
diary: "呦呦切克闹",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
heartStatus: false
}
]
},
mounted() {
//刚挂载的时候调用
this.setheight();
//屏幕变化的时候调用
const that = this;
window.onresize = function () {
that.setheight();
}
// this.$nextTick(function () { })
},
methods: {
//由于宽是百分比,这里根据元素的宽设置高度,设置成正方形
setheight() {
//这里需要取得v-for之后li的宽度,再进行赋值给高度。
//开始时尝试vue的方法,用 :ref="getWidth"标记<li>,再用$refs选择,即 width = this.$refs.getWidth.offsetWidth;
//发现不行,因为v-for渲染之后的<li>是没有ref ="getWidth"的,也就找不到了,也试了放在 this.$nextTick(function () {})中运行,也不行。
//最终还是使用原生js方法,在vue中可以使用js,但尽量避免使用jq。
//js选择元素的方法有以下几项:
//1、document.getElementById("domId")
//2、document.getElementsByName("domName")
//3、element.getElementsByTagName("tagName");element是有效的DOM元素(包括document)
//4、element.getElementsByClassName("classNames");element是有效的DOM元素(包括document)
//5、document.querySelectorAll(".getWidth");selector为合法的CSS选择器,返回值是一个nodeList集合(不是Array)
width = document.getElementsByClassName("getWidth"); //这里的到的是一个数组
this.Height = width[0].offsetWidth
},
//点击改变心形状态,向当前项添加like头像
changeHeart(item) {
item.heartStatus = !item.heartStatus;
const current = this.dengqianyonghu.icon; //设置一个当前用户的本地数据,注意this的指向问题,应在if外面。
if (item.heartStatus == true) { //通过判断红心状态来增加或删除数组中当前用户的头像
item.likeImage.push(current)
} else {
const index = item.likeImage.indexOf(current);
item.likeImage.splice(index, 1)
}
}
}
})
</script>
全部代码如下,可以把上面的全部略过,直接看这里就好了,我前面写的那些并没有什么用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue类朋友圈浏览界面</title>
<link rel="stylesheet" href="http://cdn.amazeui.org/amazeui/2.7.2/css/amazeui.min.css">
<style>
.moments {
border-bottom: 1px solid #EFEFEF;
padding-top: 15px;
padding-bottom: 15px;
}
.moments .moments-icon{
display: flex;
justify-content: center;
}
.moments .moments-icon img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
margin: 0;
padding: 0;
}
/**这些媒体查询都是根据屏幕大小改变头像和点赞部分图片的大小,设置了三层**/
@media screen and (min-width: 767px) {
.moments .moments-icon img {
width: 8.5rem;
height: 8.5rem;
}
.moments-like-image li {
width: 5rem;
height: 5rem;
}
.moments-like span {
font-size: 4rem;
}
}
@media screen and (min-width: 450px) and (max-width: 767px) {
.moments .moments-icon img{
width: 6.5rem;
height: 6.5rem;
}
.moments-like-image li {
width: 4rem;
height: 4rem;
}
.moments-like span {
font-size: 3rem;
}
}
@media screen and (max-width: 450px) {
.moments .moments-icon img{
width: 4.5rem;
height: 4.5rem;
}
.moments-like-image li {
width: 3rem;
height: 3rem;
}
.moments-like span {
font-size: 2rem;
}
}
.moments .moments-name{
font-size: 1.5rem;
color: #E298A5;
line-height: 2.5rem;
}
.moments .moments-time{
font-size: 1.3rem;
color: #AAAAAA;
line-height: 2.5rem;
}
.moments-diary {
padding-right: 1rem;
color: #000;
font-size: 1.3rem;
margin-top: 10px;
margin-bottom: 20px;
}
.moments-photos img {
border-radius: 5px;
}
.moments-photos {
padding-right: 2rem;
padding-bottom: 1.5rem;
}
.moments-photos .am-thumbnail{
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
margin: 0;
padding: 0;
border: none;
}
.moments-like-image {
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
margin: 0;
}
.moments-like-image li {
list-style: none;
margin: .2rem;
}
.moments-like-image li img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
margin: 0;
padding: 0;
border-radius: 50%;
}
.am-icon-heart-o , .am-icon-heart {
color: #E298A5;
}
</style>
</head>
<body>
<div id="app">
<!--整一块-->
<div class="am-g am-g-collapse moments" v-for="(item , index) in momentsData">
<!--左边头像部分-->
<div class="am-u-sm-2 moments-icon">
<img :src="item.icon" alt="用户头像">
</div>
<!--右边内容部分-->
<div class="am-u-sm-10">
<!--名字与倒计时-->
<div class="am-g am-g-collapse">
<div class="am-u-sm-9 am-text-left moments-name">{{item.mane}}</div>
<div class="am-u-sm-3 am-text-center moments-time">{{item.time}}</div>
</div>
<!--发表的文字-->
<div class="am-g am-g-collapse moments-diary">
{{item.diary}}
</div>
<!--晒的图片-->
<div class="am-g am-g-collapse moments-photos">
<ul class="am-avg-sm-3 am-thumbnails">
<!--这里的 :style="{height: Height+'px'}"通过js操作Height的数据使其等于该元素的宽-->
<li :style="{height: Height+'px'}" v-for="(url,index) in item.photos" class="getWidth">
<img class="am-thumbnail" :src="url" />
</li>
</ul>
</div>
<!--点赞部分-->
<div class="am-g am-g-collapse">
<ul class="am-u-sm-10 moments-like-image">
<li v-for="(image,index) in item.likeImage">
<img :src="image" />
</li>
</ul>
<div class="am-u-sm-2 am-text-center moments-like">
<span :class="item.heartStatus ? 'am-icon-heart' : 'am-icon-heart-o'" @click="changeHeart(item)"></span>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js "></script>
<script type="text/javascript ">
new Vue({
el: '#app',
data: {
Height: "",
//虚拟数据
dengqianyonghu: {
icon: "https://i.loli.net/2018/08/10/5b6d0311bc6b2.jpg",
mane: "张三丰丰丰丰丰",
time: "1小时前",
diary: "发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈",
},
momentsData: [{
icon: "https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
mane: "张三丰丰丰丰丰",
time: "1小时前",
diary: "发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
"https://i.loli.net/2018/08/10/5b6d0311e1167.jpg"
],
heartStatus: false
},
{
icon: "https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
mane: "李四",
time: "9小时前",
diary: "又又又又又发朋友圈发朋友友圈",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
heartStatus: false
},
{
icon: "https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
mane: "zhaoming",
time: "13小时前",
diary: "又又又又又发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈发朋友圈",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
heartStatus: false
},
{
icon: "https://i.loli.net/2018/08/10/5b6d0311e1167.jpg",
mane: "韩菲菲",
time: "21小时前",
diary: "呦呦切克闹",
photos: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
likeImage: [
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg",
"https://i.loli.net/2018/08/10/5b6d0311de05e.jpeg"
],
heartStatus: false
}
]
},
mounted() {
//刚挂载的时候调用
this.setheight();
//屏幕变化的时候调用
const that = this;
window.onresize = function () {
that.setheight();
}
// this.$nextTick(function () { })
},
methods: {
//由于宽是百分比,这里根据元素的宽设置高度,设置成正方形
setheight() {
//这里需要取得v-for之后li的宽度,再进行赋值给高度。
//开始时尝试vue的方法,用 :ref="getWidth"标记<li>,再用$refs选择,即 width = this.$refs.getWidth.offsetWidth;
//发现不行,因为v-for渲染之后的<li>是没有ref ="getWidth"的,也就找不到了,也试了放在 this.$nextTick(function () {})中运行,也不行。
//最终还是使用原生js方法,在vue中可以使用js,但尽量避免使用jq。
//js选择元素的方法有以下几项:
//1、document.getElementById("domId")
//2、document.getElementsByName("domName")
//3、element.getElementsByTagName("tagName");element是有效的DOM元素(包括document)
//4、element.getElementsByClassName("classNames");element是有效的DOM元素(包括document)
//5、document.querySelectorAll(".getWidth");selector为合法的CSS选择器,返回值是一个nodeList集合(不是Array)
width = document.getElementsByClassName("getWidth"); //这里的到的是一个数组
this.Height = width[0].offsetWidth
},
//点击改变心形状态,向当前项添加like头像
changeHeart(item) {
item.heartStatus = !item.heartStatus;
const current = this.dengqianyonghu.icon; //设置一个当前用户的本地数据,注意this的指向问题,应在if外面。
if (item.heartStatus == true) { //通过判断红心状态来增加或删除数组中当前用户的头像
item.likeImage.push(current)
} else {
const index = item.likeImage.indexOf(current);
item.likeImage.splice(index, 1)
}
}
}
})
</script>
</body>
</html>
网友评论