阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Vue3组件注册变化

Vue3组件注册变化

作者:陈川 阅读数:21361人阅读 分类: Vue.js

Vue3在组件注册方面进行了多项改进,包括全局注册、局部注册和异步组件的调整,同时引入了组合式API带来的新变化。下面从不同角度详细分析这些改动。

全局组件注册的变化

Vue3中全局组件注册方式从Vue.component()改为app.component(),这是为了适应新的应用实例创建方式。创建应用实例后,所有全局组件都挂载到该实例上:

// Vue2写法
Vue.component('my-component', {
  /* 选项 */
})

// Vue3写法
const app = Vue.createApp({})
app.component('my-component', {
  /* 选项 */
})

这种变化使得多个Vue应用可以共存而不会相互影响。例如在一个页面中同时运行两个独立的应用:

const app1 = Vue.createApp({})
app1.component('comp-a', { /* ... */ })

const app2 = Vue.createApp({})
app2.component('comp-b', { /* ... */ })

// 两个应用的组件互不干扰

局部组件注册的改进

局部组件注册语法保持相似,但在组合式API中有了更灵活的使用方式。Vue3允许直接在setup()中使用组件:

// 选项式API
const app = Vue.createApp({
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

// 组合式API
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

export default {
  setup() {
    return {}
  },
  components: {
    ComponentA,
    ComponentB
  }
}

在单文件组件中,Vue3还支持更简洁的局部注册方式:

<script setup>
import ComponentA from './ComponentA.vue'
</script>

<template>
  <ComponentA />
</template>

异步组件的新写法

Vue3重构了异步组件的API,使用defineAsyncComponent方法定义:

// Vue2写法
const AsyncComponent = () => ({
  component: import('./MyComponent.vue'),
  loading: LoadingComponent,
  error: ErrorComponent,
  delay: 200,
  timeout: 3000
})

// Vue3写法
import { defineAsyncComponent } from 'vue'

const AsyncComponent = defineAsyncComponent({
  loader: () => import('./MyComponent.vue'),
  loadingComponent: LoadingComponent,
  errorComponent: ErrorComponent,
  delay: 200,
  timeout: 3000,
  suspensible: false
})

新API提供了更明确的配置项命名,并增加了suspensible选项用于控制是否与<Suspense>组件协同工作。

组件命名约定的变化

Vue3推荐使用PascalCase命名组件,这与大多数现代前端工具链保持一致:

// 推荐
app.component('MyComponent', {
  /* ... */
})

// 仍然支持但不推荐
app.component('my-component', {
  /* ... */
})

在模板中使用时,两种命名方式都可以正常工作:

<template>
  <MyComponent />
  <my-component />
</template>

动态组件的调整

Vue3中动态组件的is属性用法有所调整,现在需要明确区分动态组件和原生HTML元素:

<!-- Vue2中可以直接使用 -->
<component :is="currentComponent" />

<!-- Vue3中需要添加前缀区分 -->
<component :is="currentComponent" /> <!-- 组件 -->
<component is="div" /> <!-- 原生元素 -->

对于保留元素(如table的子元素),需要使用v-is指令:

<table>
  <tr v-is="'my-row-component'"></tr>
</table>

函数式组件的变更

Vue3中函数式组件需要通过函数显式定义,不再支持functional选项:

// Vue2写法
Vue.component('functional-comp', {
  functional: true,
  render(h, context) {
    return h('div', context.props.msg)
  }
})

// Vue3写法
import { h } from 'vue'

const FunctionalComp = (props, context) => {
  return h('div', props.msg)
}

组件v-model的升级

Vue3中v-model经历了重大改进,支持多个v-model绑定和自定义修饰符:

<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />

<!-- 等价于 -->
<ChildComponent
  :title="pageTitle"
  @update:title="pageTitle = $event"
  :content="pageContent"
  @update:content="pageContent = $event"
/>

组件内部的处理方式:

export default {
  props: ['title', 'content'],
  emits: ['update:title', 'update:content'],
  setup(props, { emit }) {
    const updateTitle = (newVal) => {
      emit('update:title', newVal)
    }
    
    const updateContent = (newVal) => {
      emit('update:content', newVal)
    }
    
    return { updateTitle, updateContent }
  }
}

自定义元素交互的改进

Vue3提供了更明确的方式来处理自定义元素(Web Components):

const app = Vue.createApp({
  compilerOptions: {
    isCustomElement: tag => tag.includes('-')
  }
})

这样配置后,所有包含连字符的标签名都会被当作自定义元素处理,不会尝试解析为Vue组件。

组件继承的调整

Vue3中移除了$listeners.native修饰符,改为统一的v-on处理:

<!-- Vue2中需要.native监听原生事件 -->
<my-component @click.native="handleClick" />

<!-- Vue3中统一处理 -->
<my-component @click="handleClick" />

组件内部需要通过emits选项声明触发的事件:

export default {
  emits: ['click'],
  setup(props, { emit }) {
    const handleInternalClick = () => {
      emit('click', payload)
    }
    
    return { handleInternalClick }
  }
}

组件实例属性的变化

Vue3中组件实例的某些属性发生了变化,需要特别注意:

// Vue2
this.$children // 访问子组件
this.$scopedSlots // 访问作用域插槽

// Vue3
setup(props, { slots, attrs, emit }) {
  // 通过context参数访问
}

递归组件的处理

Vue3中递归组件需要显式命名,不能依赖文件名:

// 必须命名
export default {
  name: 'RecursiveComponent',
  setup() {
    // ...
  }
}

组件样式作用域的优化

Vue3改进了scoped样式的工作方式,使用PostCSS的新实现:

<style scoped>
/* 生成的属性选择器更高效 */
.example {
  color: red;
}
</style>

组件类型支持的增强

在TypeScript项目中,Vue3提供了更好的组件类型支持:

import { defineComponent } from 'vue'

export default defineComponent({
  name: 'TypeSafeComponent',
  props: {
    message: {
      type: String,
      required: true
    }
  },
  setup(props) {
    props.message // 类型推断为string
  }
})

组件性能优化相关

Vue3的组件注册机制在性能方面有所优化:

  1. 全局组件注册不再影响所有应用实例
  2. 局部组件注册在编译时进行更多静态分析
  3. 函数式组件创建开销显著降低
// 性能优化的函数式组件示例
import { defineComponent } from 'vue'

const OptimizedComponent = defineComponent(() => {
  // 轻量级的渲染函数
  return () => h('div', 'Hello')
})

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌