VUE哔哩哔哩移动端项目使用vant 实现发布功能(上传文件)

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>
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值