Vue之插槽【贵组件因此得以延伸】

简介: Vue之插槽【贵组件因此得以延伸】

一小池勺❤️❤️❤️ ❤️❤️❤️❤️胸有惊雷而面如平湖者,可拜上将军也。



一、引言

介绍 Vue 插槽的背景和作用

在 Vue 中,插槽(Slot)是一个非常重要的概念,它允许我们在组件中定义一些可供父组件填充内容的区域。

当我们在组件中使用 元素时,父组件可以通过 元素来提供内容,这些内容会被渲染到对应的插槽中。

插槽的作用主要有以下几个方面:

  1. 内容重用:通过使用插槽,我们可以在不同的组件中重用相同的内容,从而提高代码的可维护性和重用性。
  2. 自定义布局:通过使用插槽,我们可以在组件中定义自定义的布局,然后让父组件根据需要填充内容。
  3. 灵活性:使用插槽可以让我们更加灵活地控制组件的渲染内容,从而满足不同的需求。

总之,插槽是 Vue 中一个非常重要的概念,它提供了一种灵活的方式来定义组件的内容和布局,从而提高了代码的可维护性和重用性。


二、 Vue 插槽的基本概念

什么是 Vue 插槽

Vue 插槽是 Vue 中的一个特性,允许我们在组件中定义一些可供父组件填充内容的区域。在组件中使用<slot>元素时,父组件可以通过<template>元素来提供内容,这些内容会被渲染到对应的插槽中。


Vue 插槽的类型

Vue 插槽有三种类型:默认插槽、具名插槽和作用域插槽。

  • 默认插槽是最基本的类型,当父组件没有提供任何内容时,默认插槽中的内容将会被渲染。
  • 具名插槽允许父组件为每个插槽提供一个唯一的名称,然后通过这个名称将内容传递给对应的插槽。
  • 作用域插槽则允许父组件在传递内容时,同时传递一些数据给子组件,子组件可以使用这些数据来渲染插槽的内容。

这三种类型的插槽可以满足不同的需求,让我们更加灵活地控制组件的渲染内容。


三、使用 Vue 插槽

Vue 插槽的类型有默认插槽、具名插槽和作用域插槽。它们可以实现组件的自定义模板内容,提高组件的可重用性和可维护性。同时,它们也可以实现组件的动态内容和交互效果,从而提高组件的可用性和用户体验。


Vue 插槽有三种类型:默认插槽、具名插槽和作用域插槽。它们的作用和使用方法如下:

  1. 默认插槽:默认插槽是指在组件的模板中使用 标签定义的插槽,它没有具名,也没有提供任何默认内容。默认插槽的内容取决于组件的子元素。如果组件的子元素没有提供内容,那么默认插槽的内容将为空。
<template>
 <div>
   <slot></slot>
 </div>
</template>

<script>
export default {
 name: 'MyComponent'
};
</script>
  1. 具名插槽:具名插槽是指在组件的模板中使用 标签并为其指定 name 属性定义的插槽。具名插槽可以被父组件通过 标签的 name 属性来指定,从而实现插槽的动态切换。
<template>
 <div>
   <slot name="header"></slot>
   <slot name="content"></slot>
   <slot name="footer"></slot>
 </div>
</template>

<script>
export default {
 name: 'MyComponent'
};
</script>

在这个例子中,<slot name="header"></slot>、<slot name="content"></slot> 和 <slot name="footer"></slot> 是具名插槽,它们可以被父组件通过<slot>标签的name属性来指定。如果父组件使用了具名插槽,那么组件中的相应插槽内容将会被替换为父组件提供的内容。

  1. 作用域插槽:作用域插槽是指在组件的模板中使用<slot>标签并为其指定v-slot指令定义的插槽。作用域插槽可以访问组件的属性和方法,从而实现更复杂的插槽内容。
<template>
 <div>
   <slot v-slot="{ item }">
     {{ item.name }}
     {{ item.price }}
   </slot>
 </div>
</template>

<script>
export default {
 name: 'MyComponent',
 data() {
   return {
     items: [
       { name: 'Item 1', price: 10 },
       { name: 'Item 2', price: 20 },
       { name: 'Item 3', price: 30 }
     ]
   };
 }
};
</script>

<slot v-slot="{ item }"> 是作用域插槽,其可以通过 item 访问组件的属性 name 和 price。如果父组件使用了作用域插槽,那么组件中的相应插槽内容将会被替换为父组件提供的 item 对象的内容。


四、 Vue 插槽的优势

Vue 插槽的优势主要表现在灵活性和可重用性、组件的自定义性以及提高代码的可维护性等方面。通过插槽,开发者可以实现更加灵活和可重用的组件,从而提高代码的可维护性和可扩展性。同时,插槽也可以提高组件的可用性和用户体验,从而提高组件的性能和质量。


五、常见的 Vue 插槽使用场景

动态内容加载

插槽常常用于异步加载数据,如加载列表数据。可以在父组件中调用异步方法来获取数据,并通过插槽将数据传递给子组件。子组件再根据传入的数据渲染出相应的内容

子组件 Item.vue

<template>
  <li>
    <slot></slot>
  </li>
</template>

父组件

<template>
  <ul>
    <Item v-for="(item, index) in items" :key="index">
      {{ item.name }}
    </Item>
  </ul>
</template>

<script>
import Item from './Item.vue'
export default {
  data() {
    return {
      items: []
    }
  },
  components: {
    Item
  },
  created() {
    this.loadData()
  },
  methods: {
    async loadData() {
      // 假设 fetchData 是返回 promise 的函数
      const { data } = await fetchData()
      this.items = data
    }
  }
};
</script>

布局定制

假如我们公司正在创建一个给开发者使用的通用组件库,插槽则是非常有用的。通过提供插槽,可以使组件更加灵活,并允许用户定制组件的布局。

例如,我们在正在创建的一个Modal组件,这里是一个基本的架子:

Modal.vue

<template>
  <div class="modal">
    <header>
      <slot name="header"></slot>
    </header>
    <slot></slot>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

使用Modal的父组件

<template>
  <Modal>
    <template v-slot:header>
      <h1>这是标题</h1>
    </template>

    <p>这是一些主体内容...</p>

    <template v-slot:footer>
      <button @click="close">关闭</button>
    </template>
  </Modal>
</template>

<script>
import Modal from './Modal.vue';

export default {
  components: {
    Modal
  },
  methods: {
    close() {
      // 关闭modal
    }
  }
};
</script>

构建复杂的 UI 组件

使用插槽,可以将一个大的 UI 组件拆分为几个更小的组件。这些小的组件可以独立工作也可以通过插槽互相通信

例如,有一个“用户列表”组件,每个列表项都需要展示一些用户的信息。这个信息包括用户的姓名、地址、社交媒体链接等等。

通过插槽,则可以将这个大的部分拆分为几个独立的、可复用的组件。

首先,创建几个基本的组件,姓名组件(NameComponent.vue地址组件(AddressComponent.vue社交媒体链接组件(SocialLinksComponent.vue)

NameComponent.vue

<template>
  <div>{{ name }}</div>
</template>

<script>
export default {
  props: ['name']
}
</script>

AddressComponent.vue

<template>
  <div>{{ address }}</div>
</template>

<script>
export default {
  props: ['address']
}
</script>

SocialLinksComponent.vue

<template>
  <div>
    <a :href="`https://twitter.com/${twitter}`">Twitter</a>
    <a :href="`https://facebook.com/${facebook}`">Facebook</a>
  </div>
</template>

<script>
export default {
  props: ['twitter', 'facebook']
}
</script>

然后,创建一个名为 UserListItem.vue 的组件,会使用到以上三个组件,并通过插槽来暴露相应的数据:

<template>
  <li class="user-item">
    <slot name="name" :name="user.name">
      <NameComponent :name="user.name" />
    </slot>

    <slot name="address" :address="user.address">
      <AddressComponent :address="user.address" />
    </slot>

    <slot name="social-links" :twitter="user.twitter" :facebook="user.facebook">
      <SocialLinksComponent :twitter="user.twitter" :facebook="user.facebook" />
    </slot>
  </li>
</template>

<script>
import NameComponent from './NameComponent.vue';
import AddressComponent from './AddressComponent.vue';
import SocialLinksComponent from './SocialLinksComponent.vue';

export default {
  props: ['user'],
  components: {
    NameComponent,
    AddressComponent,
    SocialLinksComponent
  }
};
</script>

接着,我们在父组件 UserList.vue 中使用 UserListItem.vue:

<template>
  <ul>
    <UserListItem 
      v-for="(user, index) in users" 
      :key="index" 
      :user="user">

      <template v-slot:name="slotProps">
        <strong>{{ slotProps.name }}</strong>
      </template>

      <template v-slot:address="slotProps">
        <em>{{ slotProps.address }}</em>
      </template>
    </UserListItem>
  </ul>
</template>

<script>
import UserListItem from "./UserListItem.vue";

export default {
  components: {
    UserListItem
  },
  data() {
    return {
      users: [
        { 
          name: '张三', 
          address: '北京市', 
          twitter: 'zhangsan1990', 
          facebook: 'zhangsan1990' 
        },
        { 
          name: '李四', 
          address: '上海市', 
          twitter: 'lisi2000', 
          facebook: 'lisi2000' 
        },
        { 
          name: '胡昌城', 
          address: '上海市', 
          twitter: 'huchangceng', 
          facebook: 'hiif9922' 
        }
      ]
    }
  }
}
</script>


六、最佳实践和注意事项

在使用 Vue 插槽时,有一些最佳实践和注意事项可以遵循,包括:

  • 命名约定:为了提高代码的可读性和可维护性,我们应该遵循一些命名约定。例如,可以使用具名插槽来为每个插槽提供一个有意义的名称,这样可以更方便地理解每个插槽的作用。
  • 避免过度使用插槽:虽然 Vue 插槽非常灵活,但过度使用可能会导致组件的结构变得过于复杂,难以理解和维护。因此,我们应该只在需要的时候使用插槽,避免过度使用。


  • 处理默认内容:在使用默认插槽时,我们应该确保在没有父组件提供内容的情况下,插槽中有合适的默认内容。这样可以避免在某些情况下出现空白或无效的内容。


目录
打赏
0
0
0
0
8
分享
相关文章
Vue实现动态数据透视表(交叉表)
Vue实现动态数据透视表(交叉表)
78 13
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
本文介绍了使用 Vue Flow 绘制流程图的方法与技巧。Vue Flow 是一个灵活强大的工具,适合自定义复杂的流程图。文章从环境要求(Node.js v20+ 和 Vue 3.3+)、基础入门案例、自定义功能(节点与连线的定制、事件处理)到实际案例全面解析其用法。重点强调了 Vue Flow 的高度灵活性,虽然预定义内容较少,但提供了丰富的 API 支持深度定制。同时,文中还分享了关于句柄(handles)的使用方法,以及如何解决官网复杂案例无法运行的问题。最后通过对比 mermaid,总结 Vue Flow 更适合需要高度自定义和复杂需求的场景,并附带多个相关技术博客链接供进一步学习。
属性描述符初探——Vue实现数据劫持的基础
属性描述符还有很多内容可以挖掘,比如defineProperty与Proxy的区别,比如vue2与vue3实现数据劫持的方式有什么不同,实现效果有哪些差异等,这篇博文只是入门,以后有时间再深挖。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
131 12
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
iframe嵌入页面实现免登录思路(以vue为例)
通过上述步骤,可以在Vue.js项目中通过 `iframe`实现不同应用间的免登录功能。利用Token传递和消息传递机制,可以确保安全、高效地在主应用和子应用间共享登录状态。这种方法在实际项目中具有广泛的应用前景,能够显著提升用户体验。
420 8
Vue 组件化开发:构建高质量应用的核心
本文深入探讨了 Vue.js 组件化开发的核心概念与最佳实践。
119 1
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等