Vue插槽详解 | 什么是插槽?

作者 | Jeskson

来源 | 达达前端小酒馆

什么是插槽?插槽的指令为v-slot,它目前取代了slot和slot-scope,插槽内容,vue实例一套内容分发的api,将slot元素作为承载分发内容的出口。

组件的书写:

<my-link url="/profile">
dada
</my-link>

运用组件模板,可以在里面书写:

<a v-bind:href="url" class="css-link">
<slot></slot>
</a>

<slot></slot>会替换dada

插槽内可以写任何模板代码:

<my-link url="/profile">
<span class=“weixin"> </span>
dada
</my-link>
<my-link url="/profile">
<my-icon name="user"></my-icon>
dada
<my-link>
// 添加图标组件

如果my-link没有包含一个slot元素,之间的任何内容都会消失。

什么是插槽,它是vue提出的一个概念,插槽用于决定将所携带的内容,插入到指定的某个位置,使得模块分块,具有模块化特质。

插槽怎么用?

// 父组件
<template>
<div>
我是父组件
<slotda>
<p style="color:red">我是父组件得插槽内容</p>
</slotda>
<div>
</template>

在父组件中引用子组件中写入想要得显示内容

子组件slotda

<template>
<div class="slotda">
 <div>我是slotda组件</div>
 <slot></slot>
 </idv>
</template>

在子组件中写入slot,所在位置就是父组件要显示得内容

// 父组件
<template>
<div>
我是父组件
<slotda>
<p style="color:red">我是父组件插槽内容</p>
<slotdd></slotdd>
</div>
</template>

子组件

<template>
<div class="slotdd">
我是slotdd组件
</div>
</template>

具名插槽

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

子组件

父组件

<template>
<div>
我是父组件
<slotdadada>
 <p>dada</p>
 <template slot="header">
 <p>da</p>
 </template>
 <p slot="footer">我是footer</p>
</slotdadada>
</div>
</template>

插槽默认内容

// 父组件
<template>
<div>
我是父组件
<slotdd></slotdd>
</div>
</template>

子组件

<template>
<div class="slotdd">
 <slot>ddd</slot>
 </div>
</template>

作用域

<template>
<div>
我是父组件
<slot-d>
<p>{{name}}</p>
</slot-d>
</div>
</template>

<script>
export default {
 data() {
  return {
   name: 'dada'
  }
}}
</script>

子组件

<template>
<div class="slot-d">
<slot></slot>
</div>
</template>

插槽可以是任意内容:

插槽就是Vue实现的一套内容分发的API,将元素作为承载分发内容的出口。

没有插槽的情况下,在组件标签内些一些内容是不起任何作用的,当我在组件中声明了slot元素后,在组件元素内写的内容就会跑到它这里了!

<div id="app">
<child-component></child-component>
</div>

</script>
Vue.component('child-component', {
 template: `
 <div>Hello,World!</div>
 `
 })
 let vm = new Vue({
 el: '#app',
 data:{
 }
})
</script>

<child-component>你好</child-component>

组件之间得内容没有显示,使用插槽就有显示了,看看如何用:

Vue.component('child-component',{
        template:`
            <div>
            Hello,World!
            <slot></slot>
            </div>
        `
    })

具名插槽,就是给这个插槽起个名字,slot属性对应的内容都会和组件中name一一对应。

child-component,没有名字得就是默认得。

<div id="app">
    <child-component>
        <template slot="girl">
            购物、逛街
        </template>
        <template slot="boy">
            帅气
        </template>
        <div>
            我是人
            我是默认的插槽
        </div>
    </child-component>
</div>
<script>
    Vue.component('child-component',{
        template:`
            <div>
            <h4>这个世界有男人和女人</h4>

            <slot name="girl"></slot>

            <div style="height:1px;background-color:red;"></div>

            <slot name="boy"></slot>

            <div style="height:1px;background-color:red;"></div>

            <slot></slot>
            </div>
        `
    })
    let vm = new Vue({
        el:'#app',
        data:{
        }
    })
</script>

作用域插槽,在组件上的属性,可以在组件元素内使用!

在template元素上添加属性slot-scope

<div id="app">
    <child>
        <template slot-scope="a">
      <!-- {"say":"你好"} -->
            {{a}}
        </template>
    </child>
</div>
Vue.component('child',{
        template:`
            <div>
                <slot say="你好"></slot>
            </div>
        `
    })
<div id="app">
    <child :lists="nameList">
        <template slot-scope="a">
            {{a}}
        </template>
    </child>
</div>
Vue.component('child',{
        props:['lists'],
        template:`
            <div>
                <ul>
                    <li v-for="list in lists">
                        <slot :bbbbb="list"></slot>
                    </li>
                </ul>
            </div>
        `
    })

在一个组件中使用 标签,就是定义一个插槽。

如果组件中没包含任何被传入的东西都会被抛弃。

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
<base-layout>
  <template slot="header">
    <h1>d</h1>
  </template>

  <p>dd.</p>
  <p>dd.</p>

  <template slot="footer">
    <p> ddd </p>
  </template>
</base-layout>
<base-layout>
  <h1 slot="header">H</h1>

  <p>A.</p>
  <p>A.</p>

  <p slot="footer">H</p>
</base-layout>

在没有指定slot属性的时候 都会放在slot没有name属性的插槽当中。

编译作用域

插槽中的内容不能访问父级作用域

<navigation-link url="/profile">
  Logged in as {{ user.name }}
</navigation-link>
// 部分不能访问 url

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

<ul>
  <li
    v-for="todo in todos"
    v-bind:key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>

合成组件:

<div id="app1">
  <navigation-link url="/profile">
    Your Profile
  </navigation-link>
</div>

然后你在 <navigation-link> 的模板中可能会写为:

Vue.component('navigation-link', {
    template: `
      <a
        v-bind:href="url" rel="external nofollow"
        class="nav-link"
      >
      <slot></slot>
      </a>
    `
  });

当组件渲染的时候,这个 元素将会被替换为“Your Profile”。

插槽内可以包含任何模板代码

<navigation-link url="/profile">
 <!-- 添加一个 Font Awesome 图标 -->
 <span class="fa fa-user"></span>
 Your Profile
</navigation-link>

也可以是组件:

<navigation-link url="/profile">
 <!-- 添加一个图标的组件 -->
 <font-awesome-icon name="user"></font-awesome-icon>
 Your Profile
</navigation-link>

但是如果在navigation-link中没有包含一个slot元素,都会让之间得内容都消失得。

具名插槽

需要多个插槽

<div class="container">
 <header>
  <!-- 我们希望把页头放这里 -->
 </header>
 <main>
  <!-- 我们希望把主要内容放这里 -->
 </main>
 <footer>
  <!-- 我们希望把页脚放这里 -->
 </footer>
</div>

<div class="container">
 <header>
  <slot name="header"></slot>
 </header>
 <main>
  <slot></slot>
 </main>
 <footer>
  <slot name="footer"></slot>
 </footer>
</div>

<base-layout>
 <template slot="header">
  <h1></h1>
 </template>
 <p></p>
 <p></p>
 <template slot="footer">
  <p></p>
 </template>
</base-layout>

作用域插槽


Vue.component('todo-list',{
    template:`
    <ul>
      <li
        v-for="todo in todos"
        v-bind:key="todo.id">
        {{ todo.text }}
      </li>
    </ul>
    `
  });

  <ul>
 <li
  v-for="todo in todos"
  v-bind:key="todo.id"
 >
  <!-- 我们为每个 todo 准备了一个插槽,-->
  <!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
  <slot v-bind:todo="todo">
   <!-- 回退的内容 -->
   {{ todo.text }}
  </slot>
 </li>
</ul>

看代码后,插槽内容基本了解。对于编译作用域:

<navigation-link url="/profile">
  Logged in as {{ user.name }}
</navigation-link>

该插槽和模板得其他地方一样都可以访问相同的实例属性,就是相同的”作用域“,但不能访问navigation-link标签的作用域。

<navigation-link url="/profile">
  Clicking here will send you to: {{ url }}
  <!--
  这里的 `url` 会是 undefined,因为 "/profile" 是
  _传递给_ <navigation-link> 的而不是
  在 <navigation-link> 组件*内部*定义的。
  -->
</navigation-link>

我了解了呢。
后备内容

<button type="submit">
  <slot></slot>
</button>
<button type="submit">
  <slot>Submit</slot>
</button>
<submit-button></submit-button>

<button type="submit">
  Submit
</button>

作用域插槽

<span>
  <slot>{{ user.lastName }}</slot>
</span>

<current-user>
  {{ user.firstName }}
</current-user>

然而上述代码不会正常工作,因为只有 <current-user>
组件可以访问到 user 而我们提供的内容是在父级渲染的。

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

绑定在 元素上的特性被称为插槽 prop

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>
<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

默认插槽的缩写语法不能和具名插槽混用

<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

多个插槽的写法:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>

解构插槽 Prop

function (slotProps) {
  // 插槽内容
}

<current-user v-slot="{ user }">
  {{ user.firstName }}
</current-user>

<current-user v-slot="{ user: person }">
  {{ person.firstName }}
</current-user>

动态插槽名

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

?? 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]

作者Info:

【作者】:Jeskson
【原创公众号】:达达前端小酒馆。
【福利】:公众号回复 “资料” 送自学资料大礼包(进群分享,想要啥就说哈,看我有没有)!
【转载说明】:转载请说明出处,谢谢合作!~

大前端开发,定位前端开发技术栈博客,PHP后台知识点,web全栈技术领域,数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。谢谢支持,承蒙厚爱!!!



若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的CSDN!

这是一个有质量,有态度的博客

原文地址:https://www.cnblogs.com/dashucoding/p/12026391.html

时间: 2024-08-30 13:16:28

Vue插槽详解 | 什么是插槽?的相关文章

关于Vue.use()详解

关于Vue.use()详解 问题 相信很多人在用Vue使用别人的组件时,会用到 Vue.use() .例如:Vue.use(VueRouter).Vue.use(MintUI).但是用 axios时,就不需要用 Vue.use(axios),就能直接使用.那这是为什么呐? 答案 因为 axios 没有 install. 什么意思呢?接下来我们自定义一个需要 Vue.use() 的组件,也就是有 install 的组件,看完之后就明白了. 定义组件 生成模版 vue init webpack-si

Vue 实例详解与生命周期

Vue 实例详解与生命周期 Vue 的实例是 Vue 框架的入口,其实也就是前端的 ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个 Vue 实例生成.编译.挂着.销毁等过程进行 js 控制. Vue 实例初始化的选项配置对象详解 前面我们已经用了很多次 new Vue({...})的代码,而且 Vue 初始化的选项都已经用了data.methods.el.computedd等,估计您看到这里时,应该已经都明白了他们的作

Vue入门系列(五)Vue实例详解与生命周期

[入门系列] [本文转自] http://www.cnblogs.com/fly_dragon Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成.编译.挂着.销毁等过程进行js控制. 5.1. Vue实例初始化的选项配置对象详解 前面我们已经用了很多次 new Vue({...})的代码,而且Vue初始化的选项都已经用了data.methods.el.comp

Vue.js 源码分析(二十六) 高级应用 作用域插槽 详解

普通的插槽里面的数据是在父组件里定义的,而作用域插槽里的数据是在子组件定义的. 有时候作用域插槽很有用,比如使用Element-ui表格自定义模板时就用到了作用域插槽,Element-ui定义了每个单元格数据的显示格式,我们可以通过作用域插槽自定义数据的显示格式,对于二次开发来说具有很强的扩展性. 作用域插槽使用<template>来定义模板,可以带两个参数,分别是: slot-scope    ;模板里的变量,旧版使用scope属性 slot              ;该作用域插槽的nam

Vuejs之Component slot 插槽详解

Vuejs的component的数据进行了沙箱隔离,除js全局变量如Math, Date之类外无法访问用户自定义的变量,所以使用component写组件或嵌套组件时明白变量的访问非常重要 编译作用域 在看componnent的使用之前,来看下component编译作用域,明白作用域范围才能顺利写出想要的组件 假设我们有一个组件child-component,在父组件中代码如下: <child-component> {{ message }} </child-component> 编

【Vue】详解Vue生命周期

Vue实例的生命周期全过程(图) (这里的红边圆角矩形内的都是对应的Vue实例的钩子函数) 在beforeCreate和created钩子函数间的生命周期 在beforeCreate和created之间,进行数据观测(data observer) ,也就是在这个时候开始监控data中的数据变化了,同时初始化事件 created钩子函数和beforeMount间的生命周期 对于created钩子函数和beforeMount间可能会让人感到有些迷惑,下面我就来解释一下: el选项的有无对生命周期过程

【Vue】详解Vue组件系统

Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用 通过Vue.component()去注册一个组件,你就可以全局地使用它了,具体体现在每个被new的 Vue 实例/注册组件, 的template选项属性或者对应的DOM模板中,去直接使用 注册组件 全局注册 例如,放在通过new创建的Vue实例当中: Vue.component('my-component', { template:

vue组件详解(一)——组件与复用

一.什么是组件 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码. 二.组件用法 组件需要注册后才可以使用,注册有全局注册和局部注册两种方式. 2.1 全局注册后,任何V ue 实例都可以使用.如: <div id="app1"> <my-component></my-component> </div> Vue.component('my-component',{ templ

vue组件详解(三)——组件通信

组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. 一.自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件. 子组件用$emit ()来触发事件,父组件用$on()来监昕子组件的事件. 父组件可以直接在子组件的自定义标签上使用v-on 来监昕子组件触发的自定义事件,如: <div id="app9"> <p>总数:{{total}}</p> <my-component9 @add="ge