【vue3】vue3基础--全局混入

Vue3全局混入及推荐替代方案

在 Vue 3 中,全局混入(Global Mixin)的使用方式与 Vue 2 有所不同。以下是 Vue 3 中全局混入的几种实现方式:

方法一:使用 app.mixin()(主要方式)

1. 基本全局混入

// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// 定义全局混入
app.mixin({
  data() {
    return {
      globalMessage: '这是全局数据'
    }
  },
  methods: {
    $globalMethod() {
      console.log('这是全局方法')
    }
  },
  created() {
    console.log('全局混入的 created 钩子')
  }
})

app.mount('#app')

2. 更复杂的全局混入示例

// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// 全局混入对象
const globalMixin = {
  data() {
    return {
      appName: 'My Vue 3 App',
      version: '1.0.0'
    }
  },
  computed: {
    // 全局计算属性
    $isMobile() {
      return window.innerWidth < 768
    },
    $currentYear() {
      return new Date().getFullYear()
    }
  },
  methods: {
    // 全局工具方法
    $formatDate(date) {
      return new Date(date).toLocaleDateString()
    },
    $showToast(message, type = 'success') {
      // 模拟 toast 提示
      console.log(`[${type.toUpperCase()}] ${message}`)
    },
    // 防抖函数
    $debounce(func, wait) {
      let timeout
      return function executedFunction(...args) {
        const later = () => {
          clearTimeout(timeout)
          func(...args)
        }
        clearTimeout(timeout)
        timeout = setTimeout(later, wait)
      }
    }
  },
  // 生命周期钩子
  mounted() {
    console.log(`组件 ${this.$options.name || '匿名'} 已挂载`)
  }
}

app.mixin(globalMixin)
app.mount('#app')

方法二:使用 Composition API 的全局属性

Vue 3 推荐使用 app.config.globalProperties 替代部分混入功能:

// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// 设置全局属性
app.config.globalProperties.$appName = 'My Vue 3 App'
app.config.globalProperties.$filters = {
  formatCurrency(value) {
    return new Intl.NumberFormat('zh-CN', {
      style: 'currency',
      currency: 'CNY'
    }).format(value)
  },
  truncate(text, length = 50) {
    return text.length > length ? text.substring(0, length) + '...' : text
  }
}

app.config.globalProperties.$api = {
  async get(url) {
    const response = await fetch(url)
    return await response.json()
  },
  async post(url, data) {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
    return await response.json()
  }
}

app.mount('#app')

在组件中使用全局属性:

<template>
  <div>
    <h1>{{ $appName }}</h1>
    <p>价格: {{ $filters.formatCurrency(price) }}</p>
    <p>描述: {{ $filters.truncate(description) }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      price: 99.99,
      description: '这是一个很长的描述文本,需要被截断显示'
    }
  },
  async mounted() {
    const data = await this.$api.get('/api/data')
    console.log(data)
  }
}
</script>

方法三:组合式函数(推荐方式)

创建可复用的组合式函数:

// composables/useGlobal.js
import { ref, onMounted } from 'vue'

// 全局工具函数
export function useGlobalUtils() {
  const formatDate = (date) => {
    return new Date(date).toLocaleDateString('zh-CN')
  }
  
  const debounce = (func, wait) => {
    let timeout
    return (...args) => {
      clearTimeout(timeout)
      timeout = setTimeout(() => func.apply(this, args), wait)
    }
  }
  
  return {
    formatDate,
    debounce
  }
}

// 全局状态管理
export function useGlobalState() {
  const appName = ref('My Vue 3 App')
  const version = ref('1.0.0')
  const isMobile = ref(window.innerWidth < 768)
  
  const updateMobileStatus = () => {
    isMobile.value = window.innerWidth < 768
  }
  
  onMounted(() => {
    window.addEventListener('resize', updateMobileStatus)
  })
  
  return {
    appName,
    version,
    isMobile
  }
}

在组件中使用:

<template>
  <div>
    <h1>{{ appName }} v{{ version }}</h1>
    <p>设备: {{ isMobile ? '移动端' : '桌面端' }}</p>
    <p>日期: {{ formatDate(today) }}</p>
  </div>
</template>

<script>
import { useGlobalUtils, useGlobalState } from '@/composables/useGlobal'

export default {
  setup() {
    const { formatDate } = useGlobalUtils()
    const { appName, version, isMobile } = useGlobalState()
    
    const today = new Date()
    
    return {
      appName,
      version,
      isMobile,
      formatDate,
      today
    }
  }
}
</script>

方法四:插件方式

创建全局插件:

// plugins/globalMixin.js
export default {
  install(app) {
    // 全局混入
    app.mixin({
      created() {
        if (this.$options.name) {
          console.log(`组件 ${this.$options.name} 已创建`)
        }
      }
    })
    
    // 全局方法
    app.config.globalProperties.$notify = (message) => {
      alert(message)
    }
    
    // 全局属性
    app.config.globalProperties.$appConfig = {
      apiBaseUrl: process.env.VUE_APP_API_URL,
      maxFileSize: 10 * 1024 * 1024 // 10MB
    }
  }
}

在 main.js 中注册:

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import globalMixin from './plugins/globalMixin'

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

注意事项

  1. 谨慎使用全局混入:会影响所有组件,可能导致命名冲突
  2. 优先级:组件内的选项会覆盖混入的选项
  3. Composition API 优先:Vue 3 推荐使用组合式函数替代混入
  4. 类型支持:如果使用 TypeScript,需要为全局属性添加类型定义

最佳实践建议

  • 对于工具函数,使用 app.config.globalProperties
  • 对于可复用的逻辑,使用组合式函数
  • 只在确实需要影响所有组件时才使用全局混入
  • 为全局属性和方法添加明确的命名前缀(如 $

选择哪种方式取决于你的具体需求,组合式函数是 Vue 3 最推荐的代码复用方式。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝莓味的口香糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值