vue抽离自定义指令的方法

方法1:创建单独的指令文件

创建文件 src/directives/mouseParallax.js

复制代码
import { nextTick } from 'vue'

export const mouseParallax = {
  mounted(el, binding) {
    initParallax(el, binding.value)
  },
  
  updated(el, binding) {
    // 图片切换时重新初始化
    nextTick(() => {
      initParallax(el, binding.value)
    })
  },
  
  unmounted(el) {
    cleanupParallax(el)
  }
}

// 初始化视差效果
const initParallax = (el, options = {}) => {
  // 清理之前的监听器
  cleanupParallax(el)
  
  // 获取当前显示的图片
  const currentImg = el.querySelector('img:not([style*="display: none"])')
  if (!currentImg) return
  
  let isHovered = false
  const moveFactor = options.moveFactor || 20
  
  const handleMouseEnter = () => {
    isHovered = true
    currentImg.style.transform = 'scale(1.05)'
  }
  
  const handleMouseLeave = () => {
    isHovered = false
    currentImg.style.transform = 'translate(0, 0) scale(1)'
  }
  
  const handleMouseMove = (event) => {
    if (!isHovered || !currentImg) return
    
    const rect = el.getBoundingClientRect()
    const mouseX = event.clientX - rect.left
    const mouseY = event.clientY - rect.top
    
    const centerX = rect.width / 2
    const centerY = rect.height / 2
    
    const offsetX = (mouseX - centerX) / centerX
    const offsetY = (mouseY - centerY) / centerY
    
    const transformX = offsetX * moveFactor
    const transformY = offsetY * moveFactor
    
    currentImg.style.transform = `translate(${transformX}px, ${transformY}px) scale(1.05)`
  }
  
  // 绑定事件
  el.addEventListener('mouseenter', handleMouseEnter)
  el.addEventListener('mouseleave', handleMouseLeave)
  el.addEventListener('mousemove', handleMouseMove)
  
  // 保存引用
  el._mouseParallaxHandlers = {
    mouseenter: handleMouseEnter,
    mouseleave: handleMouseLeave,
    mousemove: handleMouseMove,
    currentImg: currentImg
  }
}

// 清理函数
const cleanupParallax = (el) => {
  if (el._mouseParallaxHandlers) {
    el.removeEventListener('mouseenter', el._mouseParallaxHandlers.mouseenter)
    el.removeEventListener('mouseleave', el._mouseParallaxHandlers.mouseleave)
    el.removeEventListener('mousemove', el._mouseParallaxHandlers.mousemove)
    
    // 重置图片transform
    if (el._mouseParallaxHandlers.currentImg) {
      el._mouseParallaxHandlers.currentImg.style.transform = 'translate(0, 0) scale(1)'
    }
    
    delete el._mouseParallaxHandlers
  }
}

修改 src/main.js

复制代码
import { createApp } from 'vue'
import App from './App.vue'
import { mouseParallax } from './directives/mouseParallax'

const app = createApp(App)

// 全局注册指令
app.directive('mouse-parallax', mouseParallax)

app.mount('#app')

方法2:作为插件注册

创建文件 src/directives/index.js

复制代码
import { mouseParallax } from './mouseParallax'

const MouseParallaxPlugin = {
  install(app) {
    app.directive('mouse-parallax', mouseParallax)
  }
}

export default MouseParallaxPlugin

// 或者直接导出指令
export { mouseParallax }

main.js 中使用:

复制代码
import { createApp } from 'vue'
import App from './App.vue'
import MouseParallaxPlugin from './directives'

const app = createApp(App)
app.use(MouseParallaxPlugin)
app.mount('#app')

修改后的组件文件

修改 YourComponent.vue

复制代码
<template>
  <div class="left" v-mouse-parallax="{ moveFactor: 30 }" :style="{ background: bgc }">
    <img v-for="n in 18" 
         :key="n" 
         :src="`../assets/img/itemImg${n.toString().padStart(2, '0')}.jpg`" 
         :alt="`图片${n}`"
         v-show="imgMessage === n"
         class="parallax-image">
  </div>
</template>

<script setup>
import { ref } from 'vue'

const imgMessage = ref(1)
const bgc = ref('#ffffff')

// 切换图片的方法
const changeImage = (index) => {
  imgMessage.value = index
}
</script>

<style scoped>
.left {
  position: relative;
  width: 100%;
  height: 500px;
  overflow: hidden;
  cursor: pointer;
}

.parallax-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  transition: transform 0.15s ease-out;
}
</style>

可选:在组件中局部注册

如果你只需要在特定组件中使用:

复制代码
<script setup>
import { ref } from 'vue'
import { mouseParallax } from '../directives/mouseParallax'

const imgMessage = ref(1)
const bgc = ref('#ffffff')

// 切换图片的方法
const changeImage = (index) => {
  imgMessage.value = index
}

// 局部注册指令
const vMouseParallax = mouseParallax
</script>

使用参数

你可以通过指令的值传递参数:

复制代码
<template>
  <!-- 基本使用 -->
  <div v-mouse-parallax>
  
  <!-- 传递参数 -->
  <div v-mouse-parallax="{ moveFactor: 30, scale: 1.1 }">
  
  <!-- 动态参数 -->
  <div v-mouse-parallax="parallaxConfig">
</template>

<script setup>
const parallaxConfig = ref({
  moveFactor: 25,
  scale: 1.08
})
</script>

然后在指令文件中:

复制代码
const initParallax = (el, options = {}) => {
  // ...
  const moveFactor = options.moveFactor || 20
  const scale = options.scale || 1.05
  // 使用这些参数
}
复制代码
// 全局注册指令
app.directive('mouse-parallax', mouseParallax)
// 基本使用
v-mouse-parallax

部分css样式

复制代码
  h1 {
      font-size: 2.8rem;
      margin-bottom: 10px;
      background: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      text-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
    }

 li {
      flex: 1;
      min-width: 300px;
      max-width: 350px;
      height: 350px;
      border-radius: 20px;
      overflow: hidden;
      box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
      transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
      position: relative;
    }


img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform 0.2s ease-out;
      will-change: transform;
    }
相关推荐
2601_949575862 小时前
Flutter for OpenHarmony艺考真题题库+个人信息管理实现
java·前端·flutter
CC码码2 小时前
基于WebGPU实现canvas高级滤镜
前端·javascript·webgl·fabric
懒羊羊不懒@2 小时前
Web前端开发HTML
前端
水淹萌龙2 小时前
Iconify 的离线加载
开发语言·前端·javascript
GDAL2 小时前
Electron 快速入门教程
前端·javascript·electron
外派叙利亚2 小时前
uniapp canvas 自定义仪表盘 可滑动 可点击 中间区域支持自定义
前端·javascript·uni-app·html
比特森林探险记2 小时前
React基础:语法、组件与JSX
前端·javascript·react.js
宁雨桥3 小时前
Vue项目中iframe嵌入页面实现免登录的完整指南
前端·javascript·vue.js
css趣多多3 小时前
Elment UI 布局组件
javascript