前端实现pdf、图片、word、excel文件预览,以及对应的文件下载,文件上传,轮播图展示多张图片,鼠标小手指

1,127 阅读5分钟

1. 前端实现图片预览

一、图片在后端中存储 一般来说,图片在后端的存储方式分为两种:
其一:可以将图片以独立文件的形式存储在服务器的指定文件夹中,再将路径存入数据库字段中;
其二:将图片转换成二进制流,直接存储到数据库的 Image 类型字段中.

  • 对于第一种存储方式,我们前端直接将存储路径赋值给 src 属性即可轻松显示。
  • 对于第二种存储方式,我们前端需要将其二进制流交由 blob 对象处理,然后通过 blob 的 API 生成临时 URL 赋值给 src 属性来显示。

遇到的问题数据乱码

image.png

出现问题的原因的axios 默认返回的是 json 文本形式,二进制图片数据被强制转换成了 json 文本形式。
找到了原因,解决方案就好办了。我们在 axios 里面,responseType 默认返回数据类型是 json,将其改为返回数据类型 blob。

1.1 网上参考代码:

  1. 请求数据
  export function miniprogramQrcode (params) {
  return axios.post(
    env.MI_URL + '/XXXX/XXX/XXXX',
    params,
    // 将responseType的默认json改为blob
    {
    responseType: 'blob',
    emulateJSON: true
  }).then(res => {
    if (res.data) {
      return Promise.resolve(res.data)
    } else {
      throw res
    }
  }).catch(err => {
    return Promise.reject(err)
  })
}
  1. 处理blob对象
  • 在特定元素中显示图片
//这是在页面中显示图片
  createMiniQrcode (blob) {
  let img = document.createElement('img')
  img.onload = function (e) {
    // 元素的onload 事件触发后将销毁URL对象, 释放内存。
    window.URL.revokeObjectURL(img.src)
  }
  // 浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL。
  // 这个 URL 以blob://开头,表明对应一个 Blob 对象。
  img.src = window.URL.createObjectURL(blob)
  document.querySelector('.imgQrCode').appendChild(img)
}

1.2 我项目中用的代码如下,在浏览器新窗口打开图片:

function createMiniQrcode(blob) {
        // // 浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL。
        // // 这个 URL 以blob://开头,表明对应一个 Blob 对象。
        let imgssrc = window.URL.createObjectURL(blob)
        // window.open(item, `img${index}`) // 尝试失败
        window.open('').document.write(`<!DOCTYPE html><html><body ><img src='${imgssrc}' /></body></html>`)   
      }
      
  // 请求图片数据
      const getBolob = async () => {
        return await axios
          .get(
            `api/FileMessage/Download?fid=${row.FileMessageId}&dirUrl=${this.catalogList[0].DirectoryUrl}&dlTag=${false}`,
            // 将responseType的默认json改为blob
            {
              responseType: 'blob',
              emulateJSON: true,
            }
          )
          .then((res) => {
            if (res.data) {
              return Promise.resolve(res.data)
            } else {
              throw res
            }
          })
          .catch((err) => {
            return Promise.reject(err)
          })
      }

      getBolob().then((res) => {
        console.log('res', res)
        // 新窗口打开图片
        createMiniQrcode(res)
      })
   

2. vue-office 预览docx、.xlsx、pdf

vue-office是一个支持多种文件(docx、.xlsx、pdf)预览的vue组件库,支持vue2和vue3。 链接地址

直接安装这三个库

#docx文档预览组件
npm install @vue-office/docx vue-demi

#excel文档预览组件
npm install @vue-office/excel vue-demi

#pdf文档预览组件
npm install @vue-office/pdf vue-demi

如果是vue2.6版本或以下还需要额外安装 @vue/composition-api

npm install @vue/composition-api

完整可实现代码如下:把接口换成自己的接口就可以

<template>
  <div class="file">
    <div v-if="src" class="docx">
      <vue-office-docx :src="src" v-if="src" />
    </div>
    <div v-if="pdf" class="pdf">
      <vue-office-pdf :src="pdf" v-if="pdf" @rendered="renderedHandler" @error="errorHandler" />
      <div class="pagination">
      
      </div>
    </div>
    <div v-if="excel" class="excel">
      <vue-office-excel :src="excel" :options="options" style="height: 100vh;" @rendered="renderedHandler" @error="errorHandler" />
    </div>
  </div>
</template>
<script>
import axios from 'axios'
import mammoth from 'mammoth'
import VueOfficeDocx from '@vue-office/docx'
import VueOfficePdf from '@vue-office/pdf'
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
import '@vue-office/docx/lib/index.css'
export default {
  name: 'file',
  props: {},
  data() {
    return {
      src: '',
      pdf: '',
      excel: '',
      options: {
        xls: false, //预览xlsx文件设为false;预览xls文件设为true
        minColLength: 0, // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
        minRowLength: 0, // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
        widthOffset: 10, //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
        heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
        beforeTransformData: (workbookData) => {
          return workbookData
        }, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
        transformData: (workbookData) => {
          return workbookData
        }, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
      },
      htmlContent: '',
      currentPage: 1,
      totalPages: 0,
      pages: [],
    }
  },
  components: { VueOfficeDocx, VueOfficePdf, VueOfficeExcel },
  computed: {},
  methods: {
    renderedHandler() {
      console.log('渲染完成')
    },
    errorHandler() {
      console.log('渲染失败')
    },
    getFileData() {
      let query = this.$route.query
     
      const getBolob = async () => {
      //这里是你请求的地址
        return await axios
          .get(
            `api/FileMessage/Download?fid=${query.fid}&dirUrl=${query.dirUrl}&dlTag=${query.dlTag}`,

            // 将responseType的默认json改为blob
            {
              responseType: 'blob',
              emulateJSON: true,
            }
          )
          .then((res) => {
            if (res) {
              return Promise.resolve(res)
            } else {
              throw res
            }
          })
          .catch((err) => {
            return Promise.reject(err)
          })
      }
   
      getBolob().then((res) => {
        let fileType = res.headers['content-disposition'].split('.')[1]
        console.log('fileType', fileType)
        console.log('res', res)
        let path = window.URL.createObjectURL(res.data)
        console.log('path', path)
        if (fileType === 'doc' || fileType === 'docx') {
          console.log('world文档')
          this.src = path
        } else if (fileType === 'pdf') {
          console.log('pdf文档')
          this.pdf = path
        } else if (fileType === 'xls' || fileType === 'xlsx') {
          this.excel = path
        }
      })
    },
  },
  watch: {},
  mounted() {
    console.log('ruote', this.$route)
    this.getFileData()
  },
}
</script>
<style lang="scss" scoped>
.file {
  height: 100vh;

  .docx {
    height: 800px;
    overflow: auto;
    width: 100%;
  }
  .pdf {
    height: 800px;
    width: 100%;
    overflow: auto;
  }
  .excel {
    height: 800px;
    width: 100%;
    overflow: auto;
  }
}
</style>

3. 文件下载

关键代码如下:

methods:{

// 请求数据
    async getBolob(row, query) {
      return await axios
        .get(
          `api/FileMessage/Download?fid=${row.FileMessageId}&dirUrl=${this.catalogList[0].DirectoryUrl}&dlTag=${query.dlTag}`,
          // 将responseType的默认json改为blob
          {
            responseType: 'blob',
            emulateJSON: true,
          }
        )
        .then((res) => {
          if (res) {
            return Promise.resolve(res)
          } else {
            throw res
          }
        })
        .catch((err) => {
          return Promise.reject(err)
        })
    },
    
    // 下载的点击事件
    download(row) {
      console.log('row', row)
      let query = {
        fid: row.FileMessageId, //文件ID
        dirUrl: this.catalogList[0].DirectoryUrl, //资料库路径
        dlTag: true, //下载标记
      }
      //这里是请求数据
      this.getBolob(row, query).then((res) => {
        console.log('res', res)
        //获取文件的后缀
        let fileType = res.headers['content-disposition'].split('.')[1]
        console.log('fileType', fileType)
        const blob = res.data
        const link = document.createElement('a')
        link.href = URL.createObjectURL(blob)
        //文件的名字
        link.download = row.FileMessageName + '.' + fileType
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        URL.revokeObjectURL(link.href)
      })
    },

}


4. 文件上传

使用element-ui的组件el-upload实现文件上传

介绍如下: 具体参数说明,如何实现上传、下载、删除等功能

  • action:文件上传地址,我的项目里已经封装好了请求。使用的时候需要依据项目填写。

  • show-file-list: 是否显示已上传文件列表。

  • headers:设置上传的请求头部。我的项目需要传token。

  • on-preview:点击文件列表中已上传的文件时的钩子。 可以在这个这个回调方法里写下载功能部分代码,实现点击文件下载功能。

  • on-remove:文件列表移除文件时的钩子。 在文件列表回显时,使用数组fileData记录id列,执行删除回调时,匹配id,因为删除回调方法返回的file中不记录id,只记录url,可通过url相同返回id,再调用删除接口。

  • on-success: function(response, file, fileList) 文件上传成功时的钩子。 如果不设置auto-upload:false ,则选取文件后立即进行上传,成功回调后使用返回的参数调用接口,完成文件上传。

<el-upload
		class="upload-demo" 
		action  //必要属性,上传文件的地址,可以不给,但必须要有,不给就i调接口上传
		:http-request="uploadFile"//这个是就上传文件的方法,把上传的接口写在这个方法里
		ref="upload"
		:limit="fileLimit"//上传文件个数的限制
		:on-remove="handleRemove"//上传之后,移除的事件
		:file-list="fileList"//上传了那些文件的列表
		:on-exceed="handleExceed"//超出上传文件个数的错误回调
		:before-upload="beforeUpload"//文件通过接口上传之前,一般用来判断规则,
		//比如文件大小,文件类型
		:show-file-list="false"//是否用默认文件列表显示
		:headers="headers"//上传文件的请求头
		>
		<!-- action="/api/file/fileUpload" -->
		<el-button class="btn"><i class="el-icon-paperclip"></i>上传附件</el-button>
	</el-upload>

网上代码参考如下:

<template>
  <basic-container>
        <el-upload class="upload-demo"
          ref="upload"
          :headers="headers"
          action="/admin/sys-file/upload"
          :on-success="handleAvatarSuccess"
          :show-file-list="false">
          <el-button slot="trigger" size="small" type="primary">上传文件</el-button>
        </el-upload>
        <el-table class="down" :data="dataList" border stripe style="width: 100%;margin-top: 20px;">
            <el-table-column prop="attachName" label="文件名称"></el-table-column>
            <el-table-column prop="attachSize" label="文件大小">
              <template slot-scope="scope">
                  <span v-if="scope.row.attachSize / 1024 / 1024 < 1">{{(scope.row.attachSize / 1024).toFixed(2) + 'KB'}}</span>
                  <span v-else>{{(scope.row.attachSize / 1024 / 1024).toFixed(2) + 'MB'}}</span>
              </template>
            </el-table-column>
            <el-table-column prop="createTime" label="上传时间"></el-table-column>
            <el-table-column width="150px" label="操作">
                <template slot-scope="scope">
                    <el-button size="small" type="text">
                        <a @click="downloadFile(scope.row.attachName,scope.row.attachUrl)">下载</a>
                    </el-button>
                    <el-button size="small" type="text" @click="deleteHandle(scope.row.id)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
    </el-form>
  </basic-container>
/template>

<script>
  import {   getObj,   addObj,   putObj,   fetchList,  getnoticeId,  delObj } from '@/api/policy/noticeattachment'
  import store from '@/store'
  import {mapState} from 'vuex'
  export default {
    data() {
      return {
        dataForm: {
          id: 0,
          noticeId: '',
          attachName: '',
          attachUrl: '',
          attachSize: '',
        },
        dataList: [],
        headers: {
          'Authorization': 'Bearer ' + store.getters.access_token,
        },
      }
    },
    methods: {
      init(id) {
        this.dataForm.noticeId = id
        this.$nextTick(() => {
          if (this.dataForm.noticeId) {
            this.getDataList()
          }
        });
      },
      //获取附件列表
      getDataList(){
        getnoticeId(this.dataForm.noticeId).then(response => {
          this.dataList = response.data.data;
        });
      },
      //下载按钮回调
      downloadFile(name,url){
        var a = document.createElement('a');
        var event = new MouseEvent('click');
        a.download = name;
        a.href = url;
        a.dispatchEvent(event);
      },
      //成功回调
      handleAvatarSuccess(res, file, fileList) {
        this.dataForm.attachName = file.name
        this.dataForm.attachUrl = res.data.url
        this.dataForm.attachSize = file.size
        this.dataFormSubmit()
      },
      // 删除
      deleteHandle(id) {
        this.$confirm('是否确认删除该附件', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(function () {
          return delObj(id)
        }).then(data => {
          this.$message.success('删除成功')
          this.getDataList()
        })
      },
      // 表单提交
      dataFormSubmit() {
        addObj(this.dataForm).then(data => {
          this.$message.success('添加成功')
          this.getDataList()
        })
      }
    }
  }
</script>
<style lang="scss" scoped="scoped">
  .down >>> a {
    color: #409EFF;
  }
</style>


我按需求功能实现的代码如下:

<template>
  <div class="home">
    <div class="header">
      <div>
        <el-upload class="upload-demo" ref="upload" :action="actionsPath" :on-preview="handlePreview" :on-remove="handleRemove" :auto-upload="false" :on-change="onChange" :show-file-list="false" :headers="headers" :file-list="fileList" :data="query" :on-success="onSuccess">
          <el-button slot="trigger" type="primary" icon="el-icon-plus" @click="handleAddFile" size="small" round>添加文件</el-button>
          <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload" round icon="el-icon-upload2">确认上传</el-button>
        </el-upload>

      </div>
      <div>
        <el-radio-group v-model="radio">
          <el-radio :label="3">同名时加后缀</el-radio>
          <el-radio :label="6">同时时覆盖</el-radio>
        </el-radio-group>
      </div>
      <div class="tips"><span>提示:单个文件大小不超过1G</span></div>
    </div>
    <div class="main">
      <el-table :data="tableData" style="width: 100%">
        <el-table-column prop="FileMessageName" label="文件名称" width="420" style="font-size: 12px;" />
        <el-table-column prop="FileMessageSize" label="文件大小" width="220" />
        <el-table-column prop="UploadState" label="上传状态">
          <template #default="scope">
            <span v-if="scope.row.UploadState == 2" style="color:#ff5722;">
              {{ scope.row.Message }}
            </span>
            <span v-else-if="scope.row.UploadState != 2"> {{ scope.row.Message }} </span>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>
<script>
export default {
  name: 'home',
  props: {
    catalogList: {
      type: Array,
      default: [],
    },
  },
  data() {
    return {
      headers: {},
      radio: '3',
      fileList: [],
      tableData: [],

      actionsPath: '/api/FileMessage/Upload', //上传的接口
      query: {
        //上传的参数
        DirectoryIdTag: '', //目录ID,
        SimilarAddSuffix: false, //同名称添加后缀
        SimilarCover: false, //同名称覆盖
        DirectoryUrl: '', //资料库路径
      },
    }
  },
  components: {},
  computed: {},
  methods: {
    onSuccess(res) {
      console.log('上传成功!', res)
      if (res.IsSuccess) {
        this.$layer.msgSuccess('上传成功!')
        this.$parent.$parent.openUploadDialog(false)
        this.$parent.$parent.queryFiles()
      }
    },
    onChange(file, files) {
      console.log(file)
      console.log('files', files)

      const fileSize = file.size
      let fileSizeStr = ''
   //确认文件的大小
      function formatFileSize(fileSize) {
        const units = ['GB', 'MB', 'KB']
        const thresholds = [1024 * 1024 * 1024, 1024 * 1024, 1024]

        for (let i = 0; i < units.length; i++) {
          if (fileSize >= thresholds[i]) {
            return (fileSize / thresholds[i]).toFixed(2) + ' ' + units[i]
          }
        }
        return fileSize + ' B' // 如果小于1KB,返回原始大小
      }

      // 使用示例
      fileSizeStr = formatFileSize(fileSize)

      console.log('file.response', file.response)

      const index = this.tableData.findIndex((q) => q.uid === file.uid)
      if (file.response) {
        const success = file.response.IsSuccess
        this.tableData[index].Message = success ? file.response.Data : file.response.ErrorMessage
        this.tableData[index].UploadState = success ? 1 : 2
      } else {
        this.tableData.push({
          uid: file.uid,
          LibName: 'hxzkLib',
          FileMessageName: file.name,
          FileMessageSize: fileSizeStr,
          UploadState: 0,
          Message: '待上传文件。。。',
        })
      }

      console.log('catalogList', this.catalogList)
    },

    handleAddFile() {},
    handleUpload() {},
    submitUpload() {
      this.query.DirectoryIdTag = this.catalogList.at(-1).DirectoryId
      this.query.DirectoryUrl = this.catalogList[0].DirectoryUrl

      console.log(' this.actionsPath', this.actionsPath)
      this.$refs.upload.submit()
    },
    handleRemove(file, fileList) {
      console.log(file, fileList)
    },
    handlePreview(file) {
      console.log(file)
    },
  },
  watch: {},
  mounted() {
  //获取token
    let token = this.$cookies.get(this.$member.TOKEN)
    this.headers = {
      token: token,
    }
  },
}
</script>
<style lang="scss" scoped>
.home {
  height: 500px;
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .tips {
      font-size: 12px;
      color: red;
    }
  }
  .main {
    margin-top: 20px;
    border-top: 1px solid #ccc;
  }
}
</style>

效果如下:

image.png

注意:

使用element ui中el-upload组件实现文件上传功能,主要分为两种:

    1. 通过action, url为服务器的地址
    1. 通过http-request(覆盖默认的上传行为,可以自定义上传的实现), 注意此时 on-success 和 on-error事件无法使用

方法1: action (上传xls文件),自己补充上传文件的方法

<el-upload
    class="upload-demo"
    accept=".xls,.xlsx" 
    action="/dashboardSystem/manage/uploadFile" // 服务器地址
    :data="fileupload"  // 上传时附带的额外参数通常为{}, 比如 {date: '2023-05-05'}, 上传参数为{date: xx, file: Binary}
    :style="{ textAlign: 'left' }"
    ref="upload"
    :show-file-list="true"
    :before-upload="beforeUpload" // 判断文件类型和文件大小
    :on-exceed="handleExceed" // 上传文件个数限制
    :on-success="fileSuccess" // function(res, file, fileList)    上传成功res为服务器返回的数据可以判断是否解析成功
    :on-error="showError" // function(err, file, fileList) 上传失败
    :limit="1"
    >
      <el-button
        slot="trigger"
        :style="{ display: 'inlineBlock' }"
        size="small"
        type="primary"
        >选择文件
      </el-button>
   </el-upload>

方法2: 通过http-request自定义上传文件,没有on-success, on-error

template中:

<div class="flex-div uploaditem">
    //这里是上传了那些文件的提示,我没有要默认的文件提示
	<el-tooltip class="item" effect="dark" :content="tag.name" placement="top-start" v-for="(tag,index) in fileList" :key="index">
		<el-tag style="margin-right:10px;display:flex;" :disable-transitions="false" @close="handleClose(index)" closable  @click="downloadFile(tag)"><i class="el-icon-paperclip"></i><span class="tagtext">{{tag.name}}</span></el-tag>
	</el-tooltip>
	<el-upload
		class="upload-demo" 
		action  //必要属性上传文件的地址可以不给但必须要有不给就i调接口上传
		:http-request="uploadFile"//这个是就上传文件的方法把上传的接口写在这个方法里
		ref="upload"
		:limit="fileLimit"//上传文件个数的限制
		:on-remove="handleRemove"//上传之后移除的事件
		:file-list="fileList"//上传了那些文件的列表
		:on-exceed="handleExceed"//超出上传文件个数的错误回调
		:before-upload="beforeUpload"//文件通过接口上传之前一般用来判断规则,
		//比如文件大小文件类型
		:show-file-list="false"//是否用默认文件列表显示
		:headers="headers"//上传文件的请求头
		>
		<!-- action="/api/file/fileUpload" -->
		<el-button class="btn"><i class="el-icon-paperclip"></i>上传附件</el-button>
	</el-upload>
</div>

data中:

//上传后的文件列表
fileList: [],
// 允许的文件类型
fileType: [ "pdf", "doc", "docx", "xls", "xlsx","txt","png""jpg", "bmp", "jpeg"],
// 运行上传文件大小,单位 M
fileSize: 50,
// 附件数量限制
fileLimit: 5,
//请求头
headers: { "Content-Type": "multipart/form-data" },

methods:中

//上传文件之前
beforeUpload(file){
	if (file.type != "" || file.type != null || file.type != undefined){
	    //截取文件的后缀,判断文件类型
		const FileExt = file.name.replace(/.+\./, "").toLowerCase();
		//计算文件的大小
		const isLt5M = file.size / 1024 / 1024 < 50; //这里做文件大小限制
		//如果大于50M
		if (!isLt5M) {
			this.$showMessage('上传文件大小不能超过 50MB!');
			return false;
		}
		//如果文件类型不在允许上传的范围内
		if(this.fileType.includes(FileExt)){
			return true;
		}
		else {
			this.$message.error("上传文件格式不正确!");
			return false;
		}
	}
},
//上传了的文件给移除的事件,由于我没有用到默认的展示,所以没有用到
handleRemove(){
},
//这是我自定义的移除事件
handleClose(i){
	this.fileList.splice(i,1);//删除上传的文件
	if(this.fileList.length == 0){//如果删完了
		this.fileflag = true;//显示url必填的标识
		this.$set(this.rules.url,0,{ required: true, validator: this.validatorUrl, trigger: 'blur' })//然后动态的添加本地方法的校验规则
	}
},
//超出文件个数的回调
handleExceed(){
	this.$message({
		type:'warning',
		message:'超出最大上传文件数量的限制!'
	});return
},
//上传文件的事件
uploadFile(item){
	this.$showMessage('文件上传中........')
	//上传文件的需要formdata类型;所以要转
	let FormDatas = new FormData()
    FormDatas.append('file',item.file);
	this.$axios({
		method: 'post',
		url: '/file/fileUpload',
		headers:this.headers,
		timeout: 30000,
		data: FormDatas
		}).then(res=>{
			if(res.data.id != '' || res.data.id != null){
				this.fileList.push(item.file);//成功过后手动将文件添加到展示列表里
				let i = this.fileList.indexOf(item.file)
				this.fileList[i].id = res.data.id;//id也添加进去,最后整个大表单提交的时候需要的
				if(this.fileList.length > 0){//如果上传了附件就把校验规则给干掉
					this.fileflag = false;
					this.$set(this.rules.url,0,'')
				}
				//this.handleSuccess();
			}
		})
},
//上传成功后的回调
handleSuccess(){
	
},

5. 轮播图展示多张图片

效果如下:

image.png 1.安装swiper(我安装的是4.5.1)

npm install swiper@4.5.1
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'

新建SwiperBanner.vue

  • 完整代码如下:粘贴复制,替换自己的数据就可以
<template>
  <div>
    <div class="pc-banner">
      <div class="swiper-container">
        <div class="swiper-wrapper" style="display: flex;align-items: center;">
          <div class="swiper-slide" v-for="item in imgList" :key="item.index">
            <img :src="item.src" alt="" height="200px">
          </div>
        </div>
      </div>
      <div class="swiper-pagination"></div>
      <div class="button">
        <div class="swiper-button-prev">
        </div>
        <div class="swiper-button-next">
        </div>
      </div>
    </div>
  </div>
</template>
  
<script>
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'

export default {
  props: {
    // 这里是展示图片的路径数组
    imgList: {
      type: Array,
      default: [],
    },
  },
  data() {
    return {}
  },
  mounted() {
    this.Lunbo()
  },
  methods: {
    Lunbo() {
      var swiper = new Swiper('.swiper-container', {
      //这里的4是展示图片的张数
        slidesPerView: 4,
        breakpoints: {
          750: {
            slidesPerView: 1,
          },
          990: {
            slidesPerView: 2,
          },
        },
        spaceBetween: 0,
        loop: true,
        speed: 1000,
        autoplay: true,
        autoplayDisableOnInteraction: false,
        disableOnInteraction: true,
        observer: true,
        observeParents: true,
        pagination: '.swiper-pagination',
        paginationClickable: true,
        mousewheelControl: true,
        debugger: true,
        navigation: {
          nextEl: '.swiper-button-next',
          prevEl: '.swiper-button-prev',
        },
      })
       // 鼠标移入停止播放,鼠标离开继续轮播
      swiper.el.onmouseover = function () {
        swiper.autoplay.stop()
      }
      swiper.el.onmouseleave = function () {
        swiper.autoplay.start()
      }
    },
  },
}
</script>
<style lang="scss" scoped>

.pc-banner {
  position: relative;

  .swiper-container {
    width: 100%;
  }

  .button {
    width: 100%;
    display: flex;
    justify-content: space-between;
    position: absolute;
    top: 50%;

    .swiper-button-next {
      color: black;
    }
  }
}

@media only screen and (min-width: 1200px) {
  .main {
    background: springgreen;
  }
}

/*最大的宽度是1200px,小于1200px都适用于这里*/
@media only screen and (max-width: 960px) {
  .main {
    width: 100%;
  }
}

/*
       大于min-width的宽度,小于max-width宽度
       * */
@media only screen and (min-width: 960px) and (max-width: 1200px) {
  .main {
    width: 100%;
  }
}

.swiper-slide {
  -webkit-transition: transform 1s;
  -moz-transition: transform 1s;
  -ms-transition: transform 1s;
  -o-transition: transform 1s;
  // -webkit-transform: scale(0.7);
  // transform: scale(0.7);
}

.swiper-slide-active {
  -webkit-transform: scale(1);
  transform: scale(1);
}

.none-effect {
  -webkit-transition: none;
  -moz-transition: none;
  -ms-transition: none;
  -o-transition: none;
}

.swiper-slide {
  img {
    width: 100%;
    display: block;
  }
}

.button {
  width: 100%;
  margin: auto;
  position: relative;
  top: 25%;
}

@media screen and (max-width: 750px) {
  .button {
    width: 100%;
  }
}

.swiper-button-prev {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l4.2%2C4.2L8.4%2C22l17.8%2C17.8L22%2C44L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")
    #c9c9ca center 50%/50% 50% no-repeat;
}

.swiper-button-next {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L5%2C44l-4.2-4.2L18.6%2C22L0.8%2C4.2L5%2C0z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")
    #c9c9ca center 50%/50% 50% no-repeat;
}

@media screen and (max-width: 750px) {
  .button div {
    width: 28px;
    height: 28px;
  }
}
</style>

父组件使用: image.png

配置项链接参考

6.css 鼠标悬浮时变成小手指

.cursor {
  cursor: pointer; //悬浮时变手指
}

image.png

PS:工作中用过的一些知识点,自己记录的笔记和整理来网络上的资源 ,方便以后复习使用。