Vue组件化开发全攻略:从基础到进阶实战

本文系统讲解Vue组件化开发的核心技术,涵盖组件通信、动态组件、插槽等实用特性,并提供可直接运行的代码示例。

一、组件基础:全局与局部组件

全局组件(可在任意位置使用)
Vue.component('navbar', {
  template: `
    <div class="navbar">
      <button>后退</button>
      <h3>导航栏组件</h3>
      <button>前进</button>
    </div>
  `,
  data() {
    return { myAge: 25 }
  }
})
局部组件(仅在当前Vue实例中使用)
new Vue({
  el: '#app',
  components: {
    local: {
      template: `
        <div class="local-comp">
          <h3>局部组件</h3>
        </div>
      `
    }
  }
})

二、组件通信三大核心方式

1. 父传子(Props)
<!-- 父组件 -->
<navbar :my-name="name"></navbar>

<!-- 子组件 -->
<script>
Vue.component('navbar', {
  props: ['myName'], // 接收父组件数据
  template: `<p>接收的名字: {{ myName }}</p>`
})
</script>
2. 子传父(自定义事件)
<!-- 父组件 -->
<navbar @getage="handleAge"></navbar>

<!-- 子组件 -->
<script>
Vue.component('navbar', {
  methods: {
    sendAge() {
      this.$emit('getage', this.myAge) // 触发事件
    }
  }
})
</script>
3. Ref获取组件实例
<navbar ref="mynavbar"></navbar>
<button @click="getChildData">获取子组件数据</button>

<script>
new Vue({
  methods: {
    getChildData() {
      // 访问子组件数据
      console.log(this.$refs.mynavbar.myAge)
    }
  }
})
</script>

三、动态组件与状态保持

基础实现
<button @click="currentView = 'home'">首页</button>
<button @click="currentView = 'goods'">商品</button>

<component :is="currentView"></component>

<script>
Vue.component('home', { template: '<h3>首页组件</h3>' })
Vue.component('goods', { template: '<h3>商品组件</h3>' })

new Vue({
  data: {
    currentView: 'home'
  }
})
</script>
使用keep-alive保持状态
<keep-alive>
  <component :is="currentView"></component>
</keep-alive>

应用场景:表单填写、多步骤操作等需要保存状态的场景


四、插槽:内容分发机制

1. 默认插槽
<!-- 组件定义 -->
<template>
  <div class="card">
    <h3>卡片标题</h3>
    <slot></slot> <!-- 内容分发位置 -->
  </div>
</template>

<!-- 使用组件 -->
<my-card>
  <p>这是插入的内容</p> 
</my-card>
2. 具名插槽
<!-- 组件定义 -->
<template>
  <div class="layout">
    <header><slot name="header"></slot></header>
    <main><slot name="body"></slot></main>
    <footer><slot name="footer"></slot></footer>
  </div>
</template>

<!-- 使用组件 -->
<my-layout>
  <template v-slot:header>
    <h2>页面标题</h2>
  </template>
  
  <template v-slot:body>
    <p>主要内容区域</p>
  </template>
</my-layout>

五、组件通信高级场景

1. 非父子组件通信
// 事件总线模式
const bus = new Vue()

// 组件A发送事件
bus.$emit('data-update', newData)

// 组件B接收事件
bus.$on('data-update', data => {
  console.log('收到数据:', data)
})
2. Provide/Inject(跨层级通信)
// 祖先组件
export default {
  provide() {
    return {
      appContext: this // 提供整个实例
    }
  }
}

// 后代组件
export default {
  inject: ['appContext'],
  mounted() {
    console.log(this.appContext.someData)
  }
}

六、组件设计最佳实践

  1. 命名规范

    // 推荐
    components/
      ├── BaseButton.vue
      ├── AppHeader.vue
      └── UserProfile.vue
    
  2. Props验证

    props: {
      userData: {
        type: Object,
        required: true,
        validator: value => value.id && value.name
      }
    }
    
  3. 单向数据流

    • 父组件通过props传递数据
    • 子组件通过事件通知变化
    • 避免直接修改props
  4. 作用域插槽

    <!-- 组件 -->
    <template>
      <ul>
        <li v-for="item in items">
          <slot :item="item"></slot>
        </li>
      </ul>
    </template>
    
    <!-- 使用 -->
    <my-list :items="users">
      <template v-slot:default="slotProps">
        {{ slotProps.item.name }} - {{ slotProps.item.age }}
      </template>
    </my-list>
    

七、实战案例:可复用的模态框组件

<!-- Modal.vue -->
<template>
  <div class="modal" v-show="visible">
    <div class="modal-header">
      <slot name="header">
        <h3>默认标题</h3>
      </slot>
    </div>
    
    <div class="modal-body">
      <slot></slot>
    </div>
    
    <div class="modal-footer">
      <slot name="footer">
        <button @click="close">关闭</button>
      </slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  methods: {
    close() {
      this.$emit('close')
    }
  }
}
</script>
<!-- 使用示例 -->
<modal :visible="showModal" @close="showModal = false">
  <template #header>
    <h3>自定义标题</h3>
  </template>
  
  <p>这是模态框内容...</p>
  
  <template #footer>
    <button @click="submit">提交</button>
    <button @click="showModal = false">取消</button>
  </template>
</modal>
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐