1、首先要安装@vueuse/core

npm i @vueuse/core

2、实现过程如下:

<template>  <div class="goods-image">        <div v-show="show" class="large" :style="[{backgroundImage:`url(${images[currIndex]})`},largePosition]"></div>        <div class="middle" ref="target">      <img :src="images[currIndex]" alt="">            <div v-show="show" class="layer" :style="layerPosition"></div>    </div>        <ul class="small">      <li v-for="(img,i) in images" :key="img" :class="{active:i===currIndex}">        <img @mouseenter="currIndex=i" :src="img" alt="">      </li>    </ul>  </div></template><script>import { reactive, ref, watch } from 'vue'import { useMouseInElement } from '@vueuse/core'export default {  name: 'HelloWorld',  props: {    images: {      type: Array,      default: () => ['https://yanxuan-item.nosdn.127.net/a6939f41c48fa9e9c8f7a7ed855351f1.jpg',        'https://yanxuan-item.nosdn.127.net/0cdfd546f8675669b87716114ad5900a.jpg',        'https://yanxuan-item.nosdn.127.net/240983ccc935146a4795e3990d30468d.jpg',        'https://yanxuan-item.nosdn.127.net/d46e005025a5d3b73c4781d31b327558.jpg',        'https://yanxuan-item.nosdn.127.net/330913911087b44b0d817dd78233165f.png',]    }  },  setup (props) {    // 当前预览图的索引    const currIndex = ref(0)    // 1. 是否显示遮罩和大图    const show = ref(false)    // 2. 遮罩的坐标(样式)    const layerPosition = reactive({      left: 0,      top: 0    })    // 3. 大图背景定位(样式)    const largePosition = reactive({      backgroundPositionX: 0,      backgroundPositionY: 0    })    // 4. 使用useMouseInElement得到基于元素左上角的坐标和是否离开元素数据    const target = ref(null)    const { elementX, elementY, isOutside } = useMouseInElement(target)    watch([elementX, elementY, isOutside], () => {      // 5. 根据得到数据设置样式数据和是否显示数据      show.value = !isOutside.value      // 计算坐标      const position = { x: 0, y: 0 }      if (elementX.value < 100) position.x = 0      else if (elementX.value > 300) position.x = 200      else position.x = elementX.value - 100      if (elementY.value < 100) position.y = 0      else if (elementY.value > 300) position.y = 200      else position.y = elementY.value - 100      // 给样式赋值      layerPosition.left = position.x + 'px'      layerPosition.top = position.y + 'px'      largePosition.backgroundPositionX = -2 * position.x + 'px'      largePosition.backgroundPositionY = -2 * position.y + 'px'    })    return { currIndex, show, layerPosition, largePosition, target }  }}</script><style scoped lang="less">.goods-image {  width: 480px;  height: 400px;  position: relative;  display: flex;  z-index: 500;  .large {    position: absolute;    top: 0;    left: 412px;    width: 400px;    height: 400px;    box-shadow: 0 0 10px rgba(0,0,0,0.1);    background-repeat: no-repeat;    background-size: 800px 800px;    background-color: #f8f8f8;  }  .middle {    width: 400px;    height: 400px;    background: #f5f5f5;    position: relative;    cursor: move;    img{      width: 100%;      height: 100%;    }    //cursor: pointer;    .layer {      width: 200px;      height: 200px;      background: rgba(0,0,0,.2);      left: 0;      top: 0;      position: absolute;    }  }  .small {    width: 80px;    li {      width: 68px;      height: 68px;      margin-left: 12px;      margin-bottom: 15px;      cursor: pointer;      img{        width: 100%;        height: 100%;      }      &:hover,&.active {        border: 2px solid #27BA9B;      }    }  }}</style>

3、使用:在其他的.vue文件中导入组件即可使用,例如:

import HelloWorld from "@/components/HelloWorld.vue";<HelloWorld ></HelloWorld>

4、效果如下: