bilibili发布页面主要有:发布按钮、多行文本框、一个上传图片的按钮(此处使用了vant)
组件里面的头部有:左返回按钮(使用vant)、发布按钮
<div class="top">
<van-icon name="arrow-left" class="top-lef" @click="go" />
<!-- 给按钮绑定一个class 如果computed返回的是true 就调用rel-highlight 这个css样式-->
<div
class="rel"
:class="{ 'rel-highlight': isHighLight }"
@click="regSave"
>
发布
</div>
</div>
需要实现功能:当文本框输入内容时 发布按钮就会高亮。
实现思路:使用computed监听文本框的变化,当文本框的内容长度>0时,就调用isHighLight函数,动态改变按钮的class名(rel-highlight),即改变了按钮的样式 。
<div class="text">
<textarea
class="text"
placeholder="分享我的哔哩哔哩动态"
v-model.trim="msg"
></textarea>
</div>
v-model.trim=“msg” 给文本框的内容进行双向绑定 同时删除前后空格 (当输入空格时 发布按钮的事件并不会触发 不会高亮)
computed: {
isHighLight: function () {
// 判断文本框是否输入内容 有内容是true 就调用高亮函数
return this.msg.length > 0;
},
},
上传文件:此处使用了vant
想要实现的效果就是这样的 但是当时出现了一个问题,就是我向后端发送请求之后 图片预览不出来。 (vant官方图片之所以能预览出来,是因为它自动将图片发送到vant的服务器,所以能展示出来。)
解决方法:查找vant文件上传的官方函数有:before-read=“beforeRead” 是上传前置处理,类似于钩子函数,在图片上传到vant服务器之前,将图片/视频的地址发到后端的服务器,如果上传成功,后端把拿到图片的地址和文件类型返回过来,图片/视频就可以展示出来。
:after-read=“afterRead” : 文件上传完毕后会触发 after-read 回调函数,获取到对应的 file 对象,将图片展示出来。
<!-- 上传的图片预览 -->
<div class="add">
<div v-for="(i, idx) in fileMe" :key="idx" class="a-showImgVideo">
//当上传的文件类型为0时 就显示图片;是1时就显示视频
<img class="myImg" :src="i.Mysrc" v-if="i.type == '0'" />
<video
class="myImg"
width="320"
height="240"
v-if="i.type == '1'"
autoplay
muted
>
<source :src="i.Mysrc" type="video/mp4" />
</video>
</div>
<!-- vant 上传图片/视频 -->
<van-uploader
v-model="fileList"
multiple
:before-read="beforeRead"
/>
</div>
调用 beforeRead函数,将文件的地址和类型传送到后端服务器 成功之后拿到返回值,显示出来:
methods: {
beforeRead(file) {
console.log("file", file);
console.log("file.type", file.type);
//判断文件的类型是否是图片
let type = file.type.indexOf("image") == -1 ? 1 : 0;
//使用FormData 的最大优点就是可以异步上传二进制文件
const forms = new FormData();
forms.append("filename", file); // 增加文件的参数
forms.append("type", type); // 增加类型参数
//获取返回过来的图片/视频 进行展示
axios({
url: "/bili/dynamic/uploadPicture",
method: "post",
data: forms, //URLSearchParams对象用于处理URL中查询字符串,即?之后的部分。
headers: {
"Content-Type": "multipart/form-data",
}, //php 默认要求传递请求头
})
.then((res) => {
console.log("返回res.data", res.data);
// if (res.data.data.code == "0") {
// if(res.data.code == 0){
console.log("上传成功", res.data.msg);
let imgInfo = {
Mysrc: res.data.url,
type: res.data.type,
};
this.fileMe.push(imgInfo);//fileMe是在data里定义的 是个空的数组 存的是上传图片的地址和类型
console.log("this.imgUrl", this.imgUrl);
})
.catch((e) => {
console.log("服务器出错", e);
});
},
点击发布按钮之后 将文本和图片/视频上传到后端服务器
// 点击发布按钮
regSave() {
console.log("this.fileMe", this.fileMe);
// 通过FormData将文件转成二进制数据
const forms = new FormData();
forms.append("uid", sessionStorage.getItem("uid")); // uid
forms.append("urlList", [this.fileMe[0].Mysrc]); // 添加 键和值
forms.append("descr", this.msg); // 获取上传图片描述
// forms.append("date", this.fileDate); // 获取上传图片上传时间
forms.append("type", this.fileMe[0].type); // 获取上传图片类型
axios({
url: "/bili/dynamic/addDynamic",
method: "post",
data: forms, //URLSearchParams类型
headers: {
"Content-Type": "multipart/form-data",
}, //php 默认要求传递请求头
})
.then((res) => {
// if (res.data.status === 200) {
console.log(res.data);
})
.catch((e) => {
console.log("服务器出错了", e);
});
setTimeout(() => {
// 发布成功 跳转到动态页面
this.$router.push('/Move/Space/SpaceMy');
}, 2000);
},
全部代码:
<template>
<div class="box">
<div class="top">
<van-icon name="arrow-left" class="top-lef" @click="go" />
<!-- 给按钮绑定一个class 如果computed返回的是true 就调用rel-highlight 这个css样式-->
<div
class="rel"
:class="{ 'rel-highlight': isHighLight }"
@click="regSave"
>
发布
</div>
</div>
<van-notice-bar mode="link">新人福利,分享视频领限定头像框、个性装扮</van-notice-bar>
<div class="content">
<div class="text">
<textarea
class="text"
placeholder="分享我的哔哩哔哩动态"
v-model.trim="msg"
></textarea>
</div>
<!-- 上传的图片预览 -->
<div class="add">
<div v-for="(i, idx) in fileMe" :key="idx" class="a-showImgVideo">
<img class="myImg" :src="i.Mysrc" v-if="i.type == '0'" />
<video
class="myImg"
width="320"
height="240"
v-if="i.type == '1'"
autoplay
muted
>
<source :src="i.Mysrc" type="video/mp4" />
</video>
</div>
<!-- 上传图片/视频 -->
<van-uploader
v-model="fileList"
multiple
:before-read="beforeRead"
/>
</div>
<div class="address" v-show="isShow">
<div class="address-lef">
<span class="iconfont-zm icon-lujing"></span>西安市
</div>
<div class="address-rig">
<span class="iconfont-zm icon-X" @click="isShow = false"></span>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "RelCenter",
data() {
return {
// 用户输入 msg
msg: "",
url: "",
fileMe: [],
isShow: true,
fileList: [
// { url: "https://img01.yzcdn.cn/vant/leaf.jpg" },
// Uploader 根据文件后缀来判断是否为图片文件
// 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
],
};
},
methods: {
beforeRead(file) {
console.log("file", file);
console.log("file.type", file.type);
//判断文件类型是不是图片
let type = file.type.indexOf("image") == -1 ? 1 : 0;
const forms = new FormData();
forms.append("filename", file); // 获取上传图片信息
forms.append("type", type); // 获取上传图片信息
console.log("type shiping", type);
axios({
url: "/bili/dynamic/uploadPicture",
method: "post",
data: forms, //URLSearchParams类型
headers: {
"Content-Type": "multipart/form-data",
}, //php 默认要求传递请求头
})
.then((res) => {
console.log("返回res.data", res.data);
// if (res.data.data.code == "0") {
// if(res.data.code == 0){
console.log("上传成功", res.data.msg);
let imgInfo = {
Mysrc: res.data.url,
type: res.data.type,
};
this.fileMe.push(imgInfo);
console.log("this.imgUrl", this.imgUrl);
})
.catch((e) => {
console.log("服务器出错", e);
});
},
go() {
this.$router.go(-1);
},
// 点击发布按钮
regSave() {
console.log("this.fileMe", this.fileMe);
// 通过FormData将文件转成二进制数据
const forms = new FormData();
forms.append("uid", sessionStorage.getItem("uid")); // uid
forms.append("urlList", [this.fileMe[0].Mysrc]); // 添加 键和值
forms.append("descr", this.msg); // 获取上传图片描述
// forms.append("date", this.fileDate); // 获取上传图片上传时间
forms.append("type", this.fileMe[0].type); // 获取上传图片类型
axios({
url: "/bili/dynamic/addDynamic",
method: "post",
data: forms, //URLSearchParams类型
headers: {
"Content-Type": "multipart/form-data",
}, //php 默认要求传递请求头
})
.then((res) => {
// if (res.data.status === 200) {
console.log(res.data);
})
.catch((e) => {
console.log("服务器出错了", e);
});
setTimeout(() => {
// 跳转到动态页面
this.$router.push('/Move/Space/SpaceMy');
}, 2000);
},
},
computed: {
isHighLight: function () {
// 判断文本框是否输入内容 有内容是true 就调用高亮函数
return this.msg.length > 0;
},
},
};
</script>
<style scoped>
@import url(../../assets/IconFont/Moves/font3/iconfont.css);
.box {
width: 100%;
}
.top {
width: 100%;
height: 0.44rem;
line-height: 0.44rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 0.16rem;
box-sizing: border-box;
}
.top-lef {
font-size: 0.16rem;
color: #000;
}
.rel {
width: 0.5rem;
height: 0.28rem;
background-color: #e7e7e7;
border-radius: 0.14rem;
font-size: 0.14rem;
text-align: center;
line-height: 0.28rem;
color: #919191;
}
.content {
width: 100%;
}
.text {
width: 100%;
height: 1.3rem;
box-sizing: border-box;
padding: 0.2rem 0.16rem 0;
}
textarea {
width: 100%;
height: 1.3rem;
color: #000;
font-size: 0.16rem;
border: 0;
outline: none;
}
.add {
width: 1.14rem;
height: 1.14rem;
padding: 0 0.16rem;
}
.van-uploader__upload {
width: 1.14rem;
height: 1.14rem;
border: 0.01rem solid dashed;
}
.address {
width: 1.05rem;
height: 0.26rem;
line-height: 0.26rem;
margin-left: 0.12rem;
color: #277ac3;
border-radius: 0.13rem;
margin-top: 0.7rem;
position: fixed;
bottom: 0.6rem;
}
.address-lef {
float: left;
width: 0.77rem;
height: 0.26rem;
text-align: center;
color: #277ac3;
background-color: #f4f4f4;
border-top-left-radius: 0.14rem;
border-bottom-left-radius: 0.14rem;
box-sizing: border-box;
}
.address-rig {
float: left;
width: 0.26rem;
height: 0.26rem;
line-height: 0.26rem;
text-align: center;
color: #277ac3;
margin-left: 0.02rem;
background-color: #f4f4f4;
border-top-right-radius: 0.14rem;
border-bottom-right-radius: 0.14rem;
}
.icon-lujing {
font-size: 0.14rem;
margin-right: 0.04rem;
}
.icon-X {
font-size: 0.08rem;
}
//上传成功之后图片和视频的大盒子样式
.a-showImgVideo {
margin-top: 0.2rem;
width: 1.2rem;
height: 1.2rem;
}
.a-showImgVideo .myImg {
width: 100%;
height: 100%;
}
</style>
<style>
.preview-cover {
position: absolute;
bottom: 0;
box-sizing: border-box;
width: 100%;
padding: 0.04rem;
color: #fff;
font-size: 0.12rem;
text-align: center;
background: rgba(0, 0, 0, 0.3);
}
.van-uploader .van-uploader__wrapper {
flex-wrap: nowrap;
}
/* 动态样式 */
.top .rel-highlight {
background-color: #ea7a99;
color: #fff;
}
</style>