Vue.js 中的无渲染行为插槽

来源:http://www.chinese-glasses.com 作者:Web前端 人气:77 发布时间:2020-03-24
摘要:时间: 2019-11-05阅读: 66标签: 插槽 时间: 2019-06-08阅读: 164标签: slot 在本文中我们讨论 Vue 中的无渲染插槽模式能够帮助解决哪些问题。 最近发布不久的Vue 2.6,使用插槽的语法变得更加简

时间: 2019-11-05阅读: 66标签: 插槽

时间: 2019-06-08阅读: 164标签: slot

在本文中我们讨论 Vue 中的无渲染插槽模式能够帮助解决哪些问题。

最近发布不久的Vue 2.6,使用插槽的语法变得更加简洁。 对插槽的这种改变让我对发现插槽的潜在功能感兴趣,以便为我们基于Vue的项目提供可重用性,新功能和更清晰的可读性。 真正有能力的插槽是什么?

在 Vue.js 2.3.0 中引入的作用域插槽显著提高了组件的可重用性。无渲染组件模式应运而生,解决了提供可重用行为和可插入表示的问题。

如果你是Vue的新手,或者还没有看到2.6版的变化,请继续阅读。也许学习插槽的最佳资源是Vue自己的文档,但是我将在这里给出一个纲要。

在这里,我们将会看到如何解决相反的问题:怎样提供可重用的外观和可插入的行为。

插槽是什么?

无渲染组件

插槽是Vue组件的一种机制,它允许你以一种不同于严格的父子关系的方式组合组件。插槽为你提供了一个将内容放置到新位置或使组件更通用的出口。从一个简单的例子开始:

这种模式适用于实现复杂行为且具有可自定义表示的组件。

// frame.vuetemplate div  slot/slot /div/template

它满足以下功能:

这个组件最外层是一个div。假设div的存在是为了围绕其内容创建一个样式框架。这个组件可以通用地用于将框架包围在wq你想要的任何内容上,来看看它是怎么用的。这里的frame组件指的是我们刚才做的组件。

该组件实现所有行为作用域的插槽负责渲染后备内容能够确保组件可以直接使用。

// app.vuetemplate frameimg src="an-image.jpg"/frame/template

举个例子:一个执行 Ajax 请求并显示结果的插槽的组件。组件处理 Ajax 请求并加载状态,而默认插槽提供演示。

在开始和结束frame标记之间的内容将插入到插槽所在的frame组件中,替换slot标记。这是最基本的方法。还可以简单地通过填充指定要放入槽中的默认内容

这是一个简化版的实现:

// frame.vuetemplate div  slot如果这里没有指定任何内容,这就是默认内容/slot /div/template
template div slot v-if="loading" name="loading" divLoading .../div /slot slot v-else v-bind={data} /slot /div/templatescriptexport default { props: ["url"], data: () = ({ loading: true, data: null }), async created() { this.data = await fetch(this.url); this.loading = false; }};/script

所以现在如果我们这样使用它:

用法:

// app.vuetemplate frame //template
lazy-loading url="" template #default="{ data }" div{{ data }}/div /template/lazy-loading

如果这里没有指定任何内容,这就是默认内容”是默认内容,但是如果像以前那样使用它,默认文本将被img标记覆盖。

有关这种模式的原始文章,请在这里查看。

多个/命名的插槽

一个相反的问题

可以向组件添加多个插槽,但是如果这样做了,那么除了其中一个之外,其他所有插槽都需要有名称。如果有一个没有名称的槽,它就是默认槽。下面是如何创建多个插槽:

如果问题反过来该怎么办:想象一下,如果一个组件的主要特征就是它的表示形式,另外它的行为应是可自定义的。

// titled-frame.vuetemplate div  headerh2 slot name="header"Title/slot /h2/header slot如果这里没有指定任何内容,这就是默认内容/slot /div/template

假设你想要基于 SVG 创建一个树组件,你想要提供 SVG 的显示和行为,例如在单击时收回节点和突出显示文本。

我们保留了相同的默认槽,但这次我们添加了一个名为header的槽,可以在其中输入标题,用法如下:

当你打算不对这些行为进行硬编码,并且让组件的用户自由覆盖它们时,就会出现问题。

// app.vuetemplate titled-frame template v-slot:header !-- The code below goes into the header slot -- My Image’s Title /template !-- The code below goes into the default slot -- img src="an-image.jpg" /titled-frame/template

暴露这些行为的简单解决方案是向组件添加方法和事件。

就像之前一样,如果我们想将内容添加到默认槽中,只需将其直接放在titled-frame组件中。但是,要将内容添加到命名槽中,我们需要用v-slot指令将代码包裹在在template标记中。在v-slot之后添加冒号(:),然后写出要传递内容的slot的名称。

你可能会这样去实现:

注意,v-slot是Vue 2.6的新版本,所以如果你使用的是旧版本,则需要阅读关于不推荐的slot语法的文档。

scriptexport default { mounted() { // pseudo code nodes.on('click',(node) = this.$emit('click', node)); }, methods: { expandNode(node) { //... }, retractNode(node) { //... }, highlightText(node) { //... }, }};/script

作用域插槽

如果组件的使用者要向组件添加行为,需要在父组件中使用 ref,例如:

还需要知道的另一件事是插槽可以将数据/函数传递给他们的孩子。 为了证明这一点,我们需要一个完全不同的带有插槽的示例组件:创建一个组件,该组件将当前用户的数据提供给其插槽:

template tree ref="tree" @click="onClick"/tree/templatescriptexport default { methods: { onClick(node) { this.$refs.tree.retractNode(node); } }};/script
// current-user.vuetemplate span slot v-bind:user="user" {{ user.lastName }} /slot /span/templatescriptexport default { data () { return { user: ... } }}/script

这种方法有几个缺点:

该组件有一个名为user的属性,其中包含关于用户的详细信息。默认情况下,组件显示用户的姓,但请注意,它使用v-bind将用户数据绑定到slot。这样,我们就可以使用这个组件向它的后代提供用户数据

无法再提供默认行为行为代码最终会被频繁的复制粘贴行为不可重用

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

让我们看看无渲染插槽如何解决这些问题。

为了访问传递给slot的数据,我们使用v-slot指令的值指定作用域变量的名称。

无渲染插槽

这里有几点需要注意:

行为基本上包括证明对事件的反应。所以让我们创建一个插槽,用来接收对事件和组件方法的访问:

我们指定了default的名称,但是不需要为默认槽指定名称。相反,我们可以使用v-slot="slotProps"。不需要使用slotProps作为名称,可以随便叫它什么。如果只使用默认槽,可以跳过内部template标记,直接将v-slot指令放到当前current-user上。可以使用对象解构来创建对作用域插槽数据的直接引用,而不是使用单个变量名。换句话说,可以使用v-slot="{user}"代替v-slot="slotProps",然后可以直接使用user而不是slotProps.user。

template div slot name="behavior" :on="on" :actions="actions" /slot /div/templatescriptexport default { methods: { expandNode(node) { }, retractNode(node) { }, //... }, computed:{ actions() { const {expandNode, retractNode} = this; return {expandNode, retractNode}; }, on() { return this.$on.bind(this); } }};/script

所以,上面的例子可以这样重写

on 属性是父组件的 $on 方法,因此可以监听所有事件。

// app.vuetemplate current-user v-slot="{user}" {{ user.firstName }} /current-user/template

可以将行为实现为无渲染组件。接下来编写点击扩展组件:

还有几点要记住:

export default { props: ['on','action'] render: () = null, created() { this.on("click", (node) = { this.actions.expandNode(node); }); }};

可以使用v-bind指令绑定多个值。也可以将函数传递到作用域槽。许多库使用它来提供可重用的函数组件。v-slot的别名是#。因此,可以用#header="data"来代替v-slot:header="data"。还可以使用#header来代替v-slot:header(前提:不是作用域插槽时)。对于默认插槽,在使用别名时需要指定默认名称。换句话说,需要这样写#default="data"而不是#="data"。

用法:

可以从文档中了解更多的细节,但这足以帮助你理解在本文剩下部分中讨论的内容。

tree template #behavior="{ on, actions }" expand-on-click v-bind="{ on, actions }"/ /template/tree

你能用插槽做什么?

该解决方案的主要优点是:

插槽不是为了一个目的而构建的,或者至少如果它们是,它们已经超越了最初的意图,成为做许多不同事物的强大工具。

通过备用内容来提供默认行为的可能性:

可重用的模式

本文由10bet发布于Web前端,转载请注明出处:Vue.js 中的无渲染行为插槽

关键词:

上一篇:冒烟测试(转)

下一篇:没有了

最火资讯