最近在学习框架vue,不得不说vue确实上手快,但用的vant组件库里找了老半天都没找到聊天框样式的组件,啧,实在想用,就自己搭了个,其实就这个气泡框的角花了点时间,用到了伪元素类。
效果图如下:
直接上代码
页面结构代码:
<template>
<div class="main">
<!-- 仿微信的聊天框 -->
<!-- 顶部导航栏 -->
<van-sticky :offset-top="0">
<div class="tar">
<van-nav-bar
title="对方正在娇羞中..."
left-arrow
@click-left="onClickLeft"
class="tar_back"
>
<template #right>
<van-icon name="ellipsis" size="18" />
</template>
</van-nav-bar>
</div>
</van-sticky>
<!-- 长按淡出气泡提示框 -->
<van-popover
v-model="showPopover"
trigger="manual"
:actions="actions"
placement="right-end"
:offset="[0, -130]"
@select="onSelect"
>
<template #reference>
<!-- <div class="content">
<span
v-html="content"
@touchstart="start()"
@touchend="end()"
@click="showPopover = false"
></span>
<p>长按可以点赞收藏哦~</p>
</div> -->
<!-- 聊天内容 -->
<div
@touchstart="start()"
@touchend="end()"
@click="showPopover = false"
class="content"
>
<ul>
<li
v-for="(item, index) in loveArray"
:key="index"
:class="'text-' + item.class"
:style="{ '--url': item.url }"
>
<span>{{ item.text }}</span>
</li>
</ul>
<p>长按可以点赞收藏哦~</p>
</div>
</template>
</van-popover>
<!-- 聊天内容 -->
<!-- <div >
<ul>
<li
v-for="(item, index) in loveArray"
:key="index"
:class="'text-' + item.class"
:style="{ '--url': item.url }"
>
<span>{{ item.text }}</span>
</li>
</ul>
<p>长按可以点赞收藏哦~</p>
</div> -->
<!-- 换一个按钮 -->
<div class="changeButton">
<van-button class="button" type="primary" @click="Change">
不喜欢~ 那换一个吧
</van-button>
</div>
</div>
</template>
js代码:
这里把网络请求和本地存储的代码封装到了http里。调用起来不要太方便
import { get, post } from "../../http/axios";
import { Toast } from "vant";
import {
setLikeList,
setStarList,
getLikeList,
getStarList,
} from "../../http/likeAndstarUtils";
Toast.setDefaultOptions({ duration: 800 });
let baseURL_btstu = "http://api.btstu.cn";
let baseURL_oddfar = "https://api.oddfar.com/yl";
export default {
data() {
return {
url_right:
"url(" +
"https://tva2.sinaimg.cn/large/9bd9b167gy1fzjvskibgzj20b40b4t9b.jpg" +
")",
url_left:
"url(" +
"https://tva2.sinaimg.cn/large/9bd9b167ly1fzjwklpbihj20b40b4mxx.jpg" +
")",
loveArray: [],
showPopover: false,
actions: [
{ text: "喜欢", icon: "like-o", index: 1 },
{ text: "收藏", icon: "star-o", index: 2 },
],
likeList: [],
starList: [],
};
},
created() {
Toast.loading({
message: "加载中...",
forbidClick: true,
loadingType: "spinner",
});
this.Change();
},
methods: {
onClickLeft() {
this.$router.go(-1);
},
async Change() {
Toast.loading({
message: "加载中...",
forbidClick: true,
loadingType: "spinner",
});
this.actions[0].icon = "like-o";
this.actions[1].icon = "star-o";
//每次点击清空一下数组,防止for循环的数据留下
// this.loveArray = [];
//请求男头数据
let data_myimg = {
// api_key: "b116b45ef651aa8d",
method: "zsy",
lx: "a1",
format: "json",
};
// let myimgUrl = await get(baseURL_btstu, "/sjtx/api.php", data_myimg);
// this.url_right = "url(" + myimgUrl.data.imgurl + ")";
// console.log(myimgUrl.data.imgurl);
//请求女头数据
let data_sheimg = {
method: "zsy",
lx: "b1",
format: "json",
};
// let girlimgUrl = await get(baseURL_btstu, "/sjtx/api.php", data_sheimg);
// this.url_left = "url(" + girlimgUrl.data.imgurl + ")";
//请求土味情话数据
let data_love = {
c: 1001,
encode: "json",
};
let HappyRes = await get(baseURL_oddfar, "/q.php", data_love);
// console.log(HappyRes.data.text);
// console.log(this.loveArray);
// this.loveArray = myarray;
if (HappyRes.data.code == 200) {
//将需要的文案拿出
let text = HappyRes.data.text;
//通过先拆分在合并字符串的方法,将“”符号删除
let StringFrist = text.split("“");
let Stringtwo = StringFrist.join("");
let Stringthree = Stringtwo.split("”");
let ResultString = Stringthree.join("");
// 通过<br>字符分割文本
let myarray = ResultString.split("<br>");
// console.log(myarray);
//空数组暂时存放push后的数据,用于解决点击按钮后数据消失
let PushArray = [];
// v-for循环偶数class为right,奇数class为left
for (var i = 0; i < myarray.length; i++) {
let loveObj = new Object();
// i为偶数,在右边渲染,奇数在左边渲染
if ((i & 1) === 0) {
loveObj.text = myarray[i];
loveObj.class = "right";
loveObj.url = this.url_right;
} else {
loveObj.text = myarray[i];
loveObj.class = "left";
loveObj.url = this.url_left;
}
PushArray.push(loveObj);
}
this.loveArray = PushArray;
} else {
Toast.fail("网络连接失败");
}
},
start() {
clearTimeout(this.loop); //再次清空定时器,防止重复注册定时器
this.loop = setTimeout(() => {
// console.log("长按了");
this.showPopover = true;
}, 500);
},
end() {
clearTimeout(this.loop); //清空定时器,防止重复注册定时器
},
onSelect(action) {
if (action.index == 1) {
if (action.icon == "like-o") {
this.actions[0].icon = "like";
let likeObj = new Object();
likeObj.loveArray = this.loveArray;
likeObj.title = "土味情话";
//若本地存储中的列表为null则直接存储
if (
!getLikeList() &&
typeof getLikeList() != "undefined" &&
getLikeList() != 0
) {
this.likeList.push(likeObj);
setLikeList(this.likeList);
} else {
//不为null则先取出再存储
this.likeList = getLikeList();
this.likeList.push(likeObj);
setLikeList(this.likeList);
}
} else {
this.actions[0].icon = "like-o";
// delToken();
// localStorage.removeItem('LikeList')
}
} else {
//收藏
if (action.icon == "star-o") {
this.actions[1].icon = "star";
let starObj = new Object();
starObj.loveArray = this.loveArray;
starObj.title = "土味情话";
//若本地存储中的列表为null则直接存储
if (
!getStarList() &&
typeof getStarList() != "undefined" &&
getStarList() != 0
) {
this.starList.push(starObj);
setStarList(this.starList);
} else {
//不为null则先取出再存储
this.starList = getStarList();
this.starList.push(starObj);
setStarList(this.starList);
}
} else {
this.actions[1].icon = "star-o";
}
}
},
},
};
本来是写了随机头像的,太那个api请求数据太tm的慢了,就给注释掉了,有需要的可自取,有一说一是真的慢,这后端写的也太捞了。
最后是css的代码:
.main {
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
font-size: 16px;
position: relative;
background-color: #ededed;
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
}
.main .tar .tar_back {
background-color: #ededed;
box-shadow: 0px 1px 1px 0px rgba(212, 212, 212, 0.6);
}
.van-popover__wrapper{
width: 100%;
}
.main ul {
padding: 20px 45px;
list-style: none;
}
.main li {
padding: 10px 10px 10px 10px;
margin-bottom: 5px;
position: relative;
/* 让页面内的文字不可被选中 */
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.main li span {
display: inline-block;
border-radius: 7px;
background: #a6e860;
padding: 6px 10px 8px 10px;
max-width: 88%;
word-wrap: break-word;
}
.main li.text-left span {
background: white;
}
/* 伪元素类,在文本框前面加上头像 */
.main li.text-left:before {
content: "";
width: 38px;
height: 38px;
border-radius: 3px;
display: block;
background: var(--url);
background-size: 100%;
position: absolute;
left: -40px;
top: 10px;
}
/* 伪元素类 加上气泡框的角 */
.main li.text-left span:after {
content: "";
width: 0px;
height: 0px;
display: block;
/* transparent 透明色 */
border: 7px solid transparent;
/* 在右边生成一个白色的小三角 */
border-right: 7px solid white;
position: absolute;
left: -3px;
top: 12px;
}
.text-right {
text-align: right;
}
.text-right span {
text-align: left;
}
.main li.text-right:after {
content: "";
width: 38px;
height: 38px;
border-radius: 3px;
display: block;
background: var(--url);
background-size: 100%;
position: absolute;
right: -38px;
top: 10px;
}
.main li.text-right span:after {
content: "";
width: 0px;
height: 0px;
display: block;
border: 7px solid transparent;
border-left: 7px solid #a6e860;
position: absolute;
right: -3px;
top: 11px;
}
.changeButton {
text-align: center;
}
p {
/* text-align: center; */
margin-left: 70px;
font-size: 12px;
color: rgb(133, 131, 131);
}
.button {
margin: 50px auto;
border-radius: 8px;
}