Vue新指令:v-slot

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

内容简介:在有关于

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官网提供的教程

扩展阅读


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

查看所有标签

猜你喜欢:

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

Web 2.0 Heroes

Web 2.0 Heroes

Bradley L. Jones / Wiley / 2008-04-14 / USD 24.99

Web 2.0 may be an elusive concept, but one thing is certain: using the Web as merely a means of retrieving and displaying information is history. Today?s Web is immediate, interactive, innovative. It ......一起来看看 《Web 2.0 Heroes》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具