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;
    }
相关推荐
yuanyxh1 天前
Mac 软件推荐
前端·javascript·程序员
万少1 天前
AtomCode开发微信小程序《谁去呀》 全流程
前端·javascript·后端
某人辛木1 天前
Web自动化测试
前端·python·pycharm·pytest
Kagol1 天前
Superpowers GSD gstack AgentSkills深度测评
前端·人工智能
excel1 天前
JavaScript 字符串与模板字面量:从表象到本质理解
前端
京东云开发者1 天前
当AI成为导演-如何用AI创作动漫短剧
前端
李白的天不白1 天前
使用 SmartAdmin 进行前后端开发
java·前端
乘风gg1 天前
🤡PUA AI Coding 工具 的 10 条终极语录
前端·ai编程·claude
学Linux的语莫1 天前
Vue 3 入门教程
前端·javascript·vue.js
怕浪猫1 天前
第一章、Chrome DevTools Protocol (CDP) 详解
前端·javascript·chrome