Vue新指令:v-slot

栏目: JavaScript · 发布时间: 5年前

内容简介:在有关于

slot 是Vue组件的一个重要机制,因为它使得完全解耦的组件之间可以灵活地被组合。在《Vue组件内容分发》和《Vue的作用域插槽》文章中我们深入的学习了 slot 怎么在Vue中的使用,但在Vue 3.0版本为 slot 引入了一套全新的模版语法。为了更好的从 2.x 过渡到 3.0 ,Vue的 v2.6 版本引入了新的 slot 语法,即 v-slot 。接下来我们来学习新指令 v-slot 的使用。

v-slot 指令简介

v2.6 中,我们为具名插槽和作用域插槽引入了一个新的统一语法,即 v-slot 。它取代了 slotslot-scope 这两个目前已被废弃但未被移除且仍在 文档 中的特性。这是一个较重大的改变,主要包含了:

  • v-slot 指令结合了 slotslot-scope 的功能
  • scoped slots 的简写

有关于 v-slot 指令形成的讨论过程可以阅读 RFC-0001RFC-0002 中的描述。

回顾 slot 的使用

从官网上我们可以获知,Vue中的 slot 主要分为: 单个插槽具名插槽作用域插槽 三种。而其使用也较为简单,比如我们有一个 SlotDemo 组件,可以在该组件中通过 <slot> 元素作为承载分发内容的出口:

<!-- SlotDemo.vue -->
<template>
    <div class="slot">
        <slot />
    </div>
</template>

<script>
    export default {
        name: 'SlotDemo',
    }
</script>

然后它允许你像下面这样使用 SlotDemo 组件,在使用该组件时,可以通过 <slot> 承载你想要的任何内容:

<!-- App.vue -->
<SlotDemo>
    <div class="box">
        <h1>Slot Demo</h1>
        <p>This is slot demo!</p>
    </div>
</SlotDemo>

渲染出来的内容可以看出, div.box 中的内容替代了 <slot> (也可以理解为该内容插入到了 slot )中:

Vue新指令:v-slot

使用 slot 的时候,我们还可以为其设置一个默认的内容,也就是说没有提供内容的时候被渲染。比如下面这个 SubmitButton 组件中,默认情况下该按钮显示的文本内容是" 提交 ",这个时候可以在 <slot> 标签内设置其内容为“提交”:

<!-- SubmitButton.vue -->
<template>
    <button>
        <slot>提交</slot>
    </button>
</template>

<script>
    export default {
        name: 'SubmitButton',
    }
</script>

当我们引用 SubmitButton 并不给 slot 插入任何内容时:

<!-- App.vue -->
<SubmitButton />

这个时候渲染出来的内容就是 slot 标签中的默认内容:

<button data-v-24449ecc="">提交</button>

如果我们想给按钮换成别的内容时,我们可以像下面这样使用:

<SubmitButton>保存</SubmitButton>

这个插入到 slot 中的内容“保存”会替代 slot 中默认的内容“提交”:

<button data-v-24449ecc="">保存</button>

最图如下图所示:

Vue新指令:v-slot

除了 单个插槽 之外,还可以使用 具名插槽 ,具名插槽的简单用法就是给 slot 显式的设置一个 name 值,比如下面这个 BaseLayout 组件:

<!-- BaseLayout.vue -->
<template>
    <div class="container">
        <header>
            <slot name="header">我们希望把页头放在这里~</slot>
        </header>
        <main>
            <slot>我们希望把主要内容放在这里</slot>
        </main>
        <footer>
            <slot name="footer">我们希望把页脚放在这里</slot>
        </footer>
    </div>
</template>

<script>
    export default {
        name: 'BaseLayout',
    }
</script>

调用具名插槽时,在对应的标签上使用 slot="name" ,比如下面这个简单的用例:

<!-- App.vue -->
<BaseLayout>
    <h1 slot="header">我是一个页头</h1>
    <p slot="footer">©w3cplus</p>
</BaseLayout>

Vue新指令:v-slot

有关于Vue 2.6 版本之前 slot 更详细的使用可以阅读早前的学习笔记 《Vue组件内容分发》。

slot 还有另一个特性,那就是作用域插槽,用一个简单的示例来描述作用插槽的使用。先创建一个 ColorList 组件:

<!-- ColorList.vue -->
<template>
    <div class="color-list">
        <h2>{{ title }}</h2>
        <div class="list">
            <div class="list-item" v-for="(item, index) in items" :key="index">
                <slot v-bind="item"></slot>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'ColorList',
        props: {
            title: {
                type: String,
                default: 'Colors'
            },
            items: {
                type: Array
            }
        }
    }
</script>

<!-- App.vue -->
<template>
    <div id="app">
        <img alt="Vue logo" src="./assets/logo.png">

        <ColorList :items="colors" title="Colors">
            <template scope="color">
                <div :style="{background: color.hex}">{{ color.name }}</div>
            </template>
        </ColorList>
    </div>
</template>

<script>
    import ColorList from './components/ColorList'

    export default {
        name: 'app',
        components: {
            ColorList
        },
        data () {
            return {
                colors: [
                    { name: 'Yellow', hex: '#F4D03F', },
                    { name: 'Green', hex: '#229954' },
                    { name: 'Purple', hex: '#9B59B6' }
                ]
            }
        }
    }
</script>

Vue新指令:v-slot

有关于 Vue 2.6 之前作用域插槽更详细的介绍可以阅读早前整理的《Vue的作用域插槽》一文。

上面示例涉及到的Demo代码,可以从 [app-v-slot](//github.com/vuedemos/app-v-slot) 中的 step1 分支中获取。

v-slot 的使用

前面再次回顾了 Vue 2.6 版本之前的 slot 的使用,知道Vue中的 slot 主要有 单个插槽具名插槽作用域插槽 三种。在Vue 2.6版本起对 slot 有所更新,已经废弃了 slotslot-scope 特性。从字面面上的理解就是Vue之后 slotslot-scope 语法有所更改。自己在V3.0.1版本中亲测下面的使用( step1 也是基于该版本测试的),但接下来,主要看 v-slot 的使用。

同样先来看单个插槽,即 没有在 <slot> 标签中显式的设置 name 。比如 SlotDemo 这个组件:

<!-- SlotDemo.vue -->
<template>
    <div class="slot-demo">
        <slot>我是一个slot</slot>
    </div>
</template>

正如前面所述, slot 标签中并没有显式设置 name 值,而且在 slot 标签中提供了一个默认的内容。我们在使用该组件时,可以通过 v-slot:default 来调用未显式设置 nameslot

<!-- App.vue -->
<template>
    <div id="app">
        <img alt="Vue logo" src="./assets/logo.png">
        <SlotDemo />

        <SlotDemo v-slot:default>
            <p>v-slot:default 的使用</p>
        </SlotDemo>
    </div>
</template>

Vue新指令:v-slot

但一般建议 v-slot:default 添加到 <template> 上:

<!-- App.vue -->
<SlotDemo>
    <template v-slot:default>
        <h3>v-slot:default</h3>
    </template>
</SlotDemo>

同样能正常的渲染出我们预期的结果。

一个不带name的<slot>出口会带有隐含的名字default。

另外这里有一个特殊之处, 当被提供的内容只有默认的插槽时,组件的标签上才可以被当作插槽的模板来使用,也就是说 v-slot 可以直接使用在组件上 。正如上面的示例所示:

<SlotDemo v-slot:default>
    <p>v-slot:default 的使用</p>
</SlotDemo>

接着来看一个具名插槽的示例,同样拿 BaseLayout 组件来举例:

<!-- BaseLayout.vue -->
<template>
    <div class="container">
        <header>
            <slot name="header">Header Content</slot>
        </header>
        <main>
            <slot>Main Content</slot>
        </main>
        <footer>
            <slot name="footer">Footer Content</slot>
        </footer>
    </div>
</template>

<script>
    export default {
        name: 'BaseLayout'
    }
</script>

v2.6 之后使用也是采用 v-slot

<!-- V2.6版本之前 具名插槽的使用 -->
<BaseLayout>
    <h1 slot="header">Vue 2.6之前具名插槽</h1>
    <p>我是页面的主内容</p>
    <p slot="footer">©w3cplus</p>
</BaseLayout>

<!-- V2.6之后 具名插槽的使用 -->
<BaseLayout>
    <template v-slot:header>
        <h1>Vue 2.6之后具名插槽</h1>
    </template>
    <template v-slot:default>
        <p>我是页面的主内容</p>
    </template>
    <template v-slot:footer>
        <p>©w3cplus</p>
    </template>
</BaseLayout>

Vue新指令:v-slot

<template> 元素中的所有内容都会被传入相应的插槽中。另外,没有任何被包裹在带有 v-slot<template> 中的内容都会被视为默认插槽的内容。然而,为了使用更具规范或明确一些,仍然可以在一个 <template> 中包裹默认插槽的内容,同时使用 v-slot:default 来表示。

v-slotv-onv-bind 类似,也可以缩写,即 把参数之前的所有内容( v-slot: )替换为字符 # 。例如,上面的示例我们可以改写成:

<BaseLayout>
    <template #header>
        <h1>Vue 2.6之后具名插槽</h1>
    </template>
    <template #default>
        <p>我是页面的主内容</p>
    </template>
    <template #footer>
        <p>©w3cplus</p>
    </template>
</BaseLayout>

接下来,我们再一起来看看作用域插槽中怎么来使用 v-slot 。同样拿一个 List 组件来举例,并且它暴露了一个过滤后的列表数据作为它的作用域插槽。

<!-- List.vue -->
<template>
    <div class="list">
        <div class="item" v-for="(item, index) in items" :key="index">
            <slot v-bind="item" />
        </div>
    </div>
</template>

<script>
    export default {
        name: 'List',
        props: {
            items: {
                type: Array,
            }
        }
    }
</script>

我们可以这样来调用 List 组件:

<!-- App.vue -->

<!-- V2.6版本前 -->
<List :items="colors">
    <template slot-scope="color" slot="default">
        <div :style="{backgroundColor: color.hex}"> {{ color.name }}</div>
    </template>
</List>

<!-- V2.6版本后 -->
<List :items="colors" v-slot="color">
    <div :style="{backgroundColor: color.hex}"> {{ color.name }}</div>
</List>

<script>
    import List from './components/List'

    export default {
        name: 'app',
        components: {
            List
        },
        data () {
            return {
            colors: [
                { name: 'Yellow', hex: '#F4D03F'},
                { name: 'Green', hex: '#229954' },
                { name: 'Purple', hex: '#9B59B6' }
            ]
            }
        }
    }
</script>

Vue新指令:v-slot

从示例上的代码可以看出,使用 v-slot ,避免了额外的嵌套。另外 v-slot 指令也提供了一个绑定 slotscope-slot 指令的方式,但需要使用一个 : 来分割它们。

有关于 v-slot 示例的相关代码,可以把分支切换到 step2

小结

在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slotslot-scope 这两个目前已被废弃但未被移除且仍在文档中的特性。这篇文章主要介绍了Vue中 slot 新老语法两个版本的使用。希望对大家有所帮助。有关于更详细的介绍可以阅读 Vue官网提供的教程

扩展阅读


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Smarter Than You Think

Smarter Than You Think

Clive Thompson / Penguin Press HC, The / 2013-9-12 / USD 27.95

It's undeniable—technology is changing the way we think. But is it for the better? Amid a chorus of doomsayers, Clive Thompson delivers a resounding "yes." The Internet age has produced a radical new ......一起来看看 《Smarter Than You Think》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具