vue3中一下全局API的使用(app.component,app.config,app.directive, app.mount,app.unmount,ap

395 阅读4分钟

1. app.component

1.1 基本概念

app.component 用于注册或获取全局组件。

// 注册全局组件
app.component('my-component', {
  // 组件选项
  props: ['title'],
  template: `
    <div class="my-component">
      <h2>{{ title }}</h2>
      <slot></slot>
    </div>
  `
})

// 获取已注册的组件
const MyComponent = app.component('my-component')

1.2 使用场景

  • 注册常用基础组件
  • 注册第三方组件库
  • 创建可复用的通用组件
// 批量注册基础组件
import BaseButton from './components/BaseButton.vue'
import BaseInput from './components/BaseInput.vue'
import BaseCard from './components/BaseCard.vue'

const app = createApp(App)

app.component('BaseButton', BaseButton)
   .component('BaseInput', BaseInput)
   .component('BaseCard', BaseCard)

2. app.config

2.1 基本概念

app.config 用于配置应用级别的选项。

const app = createApp(App)

// 配置全局属性
app.config.globalProperties.$http = axios
app.config.globalProperties.$format = {
  date(value) {
    return new Date(value).toLocaleDateString()
  }
}

// 配置错误处理
app.config.errorHandler = (err, vm, info) => {
  console.error('全局错误:', err)
  // 发送到错误追踪服务
}

// 配置警告处理
app.config.warnHandler = (msg, vm, trace) => {
  console.warn('全局警告:', msg)
}

// 性能追踪
app.config.performance = true

2.2 使用场景

  • 配置全局错误处理
  • 添加全局属性和方法
  • 配置性能追踪
  • 自定义组件选项合并策略

3. app.directive

3.1 基本概念

app.directive 用于注册或获取全局自定义指令。

// 注册全局指令
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// 带参数的指令
app.directive('color', {
  mounted(el, binding) {
    el.style.color = binding.value
  },
  updated(el, binding) {
    el.style.color = binding.value
  }
})

3.2 使用场景

  • DOM 操作封装
  • 复用常见的交互行为
  • 第三方库集成
// 示例:点击外部关闭指令
app.directive('click-outside', {
  mounted(el, binding) {
    el._clickOutside = (event) => {
      if (!(el === event.target || el.contains(event.target))) {
        binding.value(event)
      }
    }
    document.addEventListener('click', el._clickOutside)
  },
  unmounted(el) {
    document.removeEventListener('click', el._clickOutside)
  }
})

4. app.mount

4.1 基本概念

app.mount 用于将应用实例挂载到一个容器元素中。

// 基本用法
const app = createApp(App)
app.mount('#app')

// 带配置的挂载
app.mount('#app', true) // 强制挂载

// 自定义渲染器
const app = createApp(App)
app.mount('#app', false, (container) => {
  // 自定义挂载逻辑
})

4.2 使用场景

  • 应用初始化
  • 动态挂载组件
  • 多应用实例管理

5. app.unmount

5.1 基本概念

app.unmount 用于卸载应用实例。

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

// 卸载应用
app.unmount()

5.2 使用场景

  • 清理应用实例
  • 动态切换应用
  • 单页应用路由切换

6. app.use

6.1 基本概念

app.use 用于安装 Vue.js 插件。

// 基本用法
app.use(VueRouter)
app.use(Vuex)

// 带选项的插件安装
app.use(MyPlugin, {
  option1: true,
  option2: 'value'
})

// 自定义插件
const myPlugin = {
  install(app, options) {
    // 添加全局属性
    app.config.globalProperties.$myPlugin = {
      // 插件方法
    }
    
    // 注册全局组件
    app.component('my-component', {
      // 组件选项
    })
    
    // 注册全局指令
    app.directive('my-directive', {
      // 指令选项
    })
  }
}

app.use(myPlugin, { /* 选项 */ })

6.2 使用场景

  • 安装路由插件
  • 安装状态管理插件
  • 安装UI组件库
  • 安装自定义插件

7. 最佳实践

7.1 插件开发

// 创建插件
export default {
  install(app, options = {}) {
    // 注册全局组件
    app.component('MyGlobalComponent', {/*...*/})
    
    // 添加全局属性
    app.config.globalProperties.$helper = {/*...*/}
    
    // 注册全局指令
    app.directive('my-directive', {/*...*/})
    
    // 扩展应用实例
    app.mixin({
      created() {
        // 混入逻辑
      }
    })
  }
}

7.2 应用配置

// main.js
const app = createApp(App)

// 配置全局错误处理
app.config.errorHandler = (err) => {
  console.error(err)
  // 错误上报逻辑
}

// 注册全局组件
app.component('BaseButton', BaseButton)

// 注册全局指令
app.directive('focus', {/*...*/})

// 使用插件
app.use(router)
app.use(store)

// 挂载应用
app.mount('#app')

8. 注意事项

  1. 全局注册的影响
// ❌ 过度使用全局注册
app.component('MyComponent', {/*...*/})

// ✅ 按需注册
import MyComponent from './components/MyComponent.vue'

export default {
  components: {
    MyComponent
  }
}
  1. 插件的依赖顺序
// ✅ 正确的插件安装顺序
app.use(router)  // 先安装路由
   .use(store)   // 再安装状态管理
   .use(myPlugin) // 最后安装自定义插件
  1. 性能考虑
// ✅ 合理使用全局配置
app.config.performance = process.env.NODE_ENV !== 'production'

9. 在组件中使用全局 API

9.1 使用全局组件

<!-- 使用全局注册的基础组件 -->
<template>
  <div class="user-form">
    <base-input
      v-model="username"
      label="用户名"
    />
    <base-button @click="submit">
      提交
    </base-button>
  </div>
</template>

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

const username = ref('')
const submit = () => {
  // 处理提交逻辑
}
</script>

9.2 使用全局配置

<!-- 使用全局属性和方法 -->
<template>
  <div class="user-profile">
    <p>注册时间: {{ $format.date(user.registerTime) }}</p>
    <button @click="fetchData">刷新数据</button>
  </div>
</template>

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

// 获取全局属性
const { proxy } = getCurrentInstance()
const user = ref({})

const fetchData = async () => {
  try {
    // 使用全局配置的 http 实例
    const response = await proxy.$http.get('/api/user')
    user.value = response.data
  } catch (error) {
    // 全局错误处理会自动捕获
    console.error(error)
  }
}
</script>

9.3 使用全局指令

<!-- 使用全局自定义指令 -->
<template>
  <div class="form-group">
    <!-- 自动聚焦指令 -->
    <input v-focus v-model="searchText">
    
    <!-- 带参数的颜色指令 -->
    <p v-color="'red'">这是红色文本</p>
    
    <!-- 点击外部关闭指令 -->
    <div
      v-click-outside="closeDropdown"
      class="dropdown"
    >
      <button @click="toggleDropdown">
        打开下拉菜单
      </button>
      <div v-if="isOpen" class="dropdown-menu">
        <!-- 下拉菜单内容 -->
      </div>
    </div>
  </div>
</template>

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

const searchText = ref('')
const isOpen = ref(false)

const toggleDropdown = () => {
  isOpen.value = !isOpen.value
}

const closeDropdown = () => {
  isOpen.value = false
}
</script>

9.4 动态组件挂载

<!-- 动态挂载组件示例 -->
<script setup>
import { h, render } from 'vue'
import NotificationComponent from './NotificationComponent.vue'

// 动态创建并挂载通知组件
const showNotification = (message, type = 'info') => {
  // 创建容器
  const container = document.createElement('div')
  document.body.appendChild(container)
  
  // 创建虚拟节点
  const vnode = h(NotificationComponent, {
    message,
    type,
    onClose: () => {
      // 清理组件
      render(null, container)
      container.remove()
    }
  })
  
  // 渲染组件
  render(vnode, container)
}

// 使用方法
const handleClick = () => {
  showNotification('操作成功!', 'success')
}
</script>

9.5 插件功能使用

<!-- 使用插件提供的功能 -->
<template>
  <div class="plugin-demo">
    <!-- 使用插件注册的全局组件 -->
    <my-component />
    
    <!-- 使用插件提供的指令 -->
    <div v-my-directive="options">
      <!-- 内容 -->
    </div>
    
    <!-- 使用插件提供的方法 -->
    <button @click="handleAction">
      执行插件方法
    </button>
  </div>
</template>

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

const { proxy } = getCurrentInstance()

const handleAction = () => {
  // 调用插件提供的方法
  proxy.$myPlugin.doSomething()
}

// 使用插件提供的配置
const options = {
  // 插件选项
}
</script>

9.6 组合式 API 中的使用

<script setup>
import { onMounted, inject } from 'vue'

// 注入插件提供的数据
const theme = inject('theme', 'light')

// 使用插件提供的组合式函数
const { useMyFeature } = inject('myPlugin')
const { data, methods } = useMyFeature()

onMounted(() => {
  // 使用插件功能
  methods.initialize()
})
</script>

9.7 实际应用示例

<!-- 完整的表单组件示例 -->
<template>
  <div class="advanced-form">
    <!-- 使用全局基础组件 -->
    <base-card>
      <template #header>
        <h2>{{ $t('form.title') }}</h2>
      </template>
      
      <base-form
        v-model="formData"
        :rules="validationRules"
      >
        <base-input
          v-model="formData.name"
          v-focus
          :label="$t('form.name')"
        />
        
        <base-select
          v-model="formData.type"
          :options="typeOptions"
        />
        
        <!-- 使用自定义指令 -->
        <div
          v-click-outside="closePopover"
          class="help-section"
        >
          <base-button @click="toggleHelp">
            {{ $t('form.help') }}
          </base-button>
          
          <div v-if="showHelp" class="popover">
            <!-- 帮助内容 -->
          </div>
        </div>
      </base-form>
      
      <template #footer>
        <base-button
          type="primary"
          @click="handleSubmit"
        >
          {{ $t('form.submit') }}
        </base-button>
      </template>
    </base-card>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useForm } from '@/composables/form'

// 使用插件提供的功能
const { t } = useI18n()
const { validateForm } = useForm()

// 表单数据
const formData = ref({
  name: '',
  type: ''
})

// 帮助弹窗状态
const showHelp = ref(false)

// 选项数据
const typeOptions = computed(() => [
  { label: t('options.type1'), value: 'type1' },
  { label: t('options.type2'), value: 'type2' }
])

// 验证规则
const validationRules = {
  name: [
    { required: true, message: t('validation.nameRequired') }
  ],
  type: [
    { required: true, message: t('validation.typeRequired') }
  ]
}

// 方法
const toggleHelp = () => {
  showHelp.value = !showHelp.value
}

const closePopover = () => {
  showHelp.value = false
}

const handleSubmit = async () => {
  try {
    // 验证表单
    await validateForm(formData.value)
    
    // 提交数据
    await proxy.$http.post('/api/submit', formData.value)
    
    // 显示成功提示
    proxy.$notify({
      type: 'success',
      message: t('messages.submitSuccess')
    })
  } catch (error) {
    // 错误会被全局错误处理捕获
    console.error(error)
  }
}
</script>

<style scoped>
.advanced-form {
  max-width: 600px;
  margin: 0 auto;
}

.help-section {
  position: relative;
  margin-top: 1rem;
}

.popover {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  /* 其他样式 */
}
</style>

这个完整示例展示了如何在实际组件中综合使用各种全局 API 和功能,包括:

  • 全局基础组件
  • 自定义指令
  • 全局属性和方法
  • 插件提供的功能
  • 国际化支持
  • 表单验证
  • HTTP 请求
  • 通知提示
  • 错误处理