详解vue 2.6 中 slot 的新用法(3)

当使用此组件时,可以向 footer 添加一个可以关闭模​​态的按钮。 通常,在Bootstrap模式的情况下,可以将 data-dismiss =“modal” 添加到按钮来进行关闭。

但我们希望隐藏Bootstrap 特定的东西。 所以我们传递给他们一个他们可以调用的函数,这样使用者就不会知道我们有使用 Bootstrap 的东西。

<!-- 使用 my-modal.vue --> <template> <my-modal> <template #header> <h5>Awesome Interruption!</h5> </template> <template #body> <p>大家加油!</p> </template> <template #footer="{closeModal}"> <button @click="closeModal"> 点我可以关闭烦人的对话框 </button> </template> </my-modal> </template>

无渲染组件

最后,可以利用你所知道的关于使用插槽来传递可重用函数的知识,并剥离所有HTML,只使用插槽。这就是无渲染组件的本质:一个只提供函数而不包含任何HTML的组件。

使组件真正无渲染可能有点棘手,因为需要编写 render 函数而不是使用模板来消除对根元素的依赖,但它可能并不总是必要的。 来看看一个先使用模板的简单示例:

<template> <transition v-bind="$attrs" v-on="$listeners"> <slot></slot> </transition> </template> <style> .fade-enter-active, .fade-leave-active { transition: opacity 0.3s; } .fade-enter, .fade-leave-to { opacity: 0; } </style>

这是一个无渲染组件的奇怪例子,因为它甚至没有任何JavaScript。这主要是因为我们正在创建一个内置无渲染函数的预配置可重用版本: transition 。

是的,Vue有内置的无渲染组件。这个特殊的例子取自Cristi Jora的一篇关于 可重用transition 的文章,展示了一种创建无渲染组件的简单方法,该组件可以标准化整个应用程序中使用的 transition 。

对于我们的另一个示例,我们将创建一个组件来处理切换 Promise 的不同状态中显示的内容: pending、resolved 和 failed。这是一种常见的模式,虽然它不需要很多代码,但是如果没有为了可重用性而提取逻辑,它会使很多组件变得混乱。

<!-- promised.vue --> <template> <span> <slot v-if="error" :error="error"></slot> <slot v-else-if="resolved" :data="data"></slot> <slot v-else></slot> </span> </template> <script> export default { props: { promise: Promise }, data: () => ({ resolved: false, data: null, error: null }), watch: { promise: { handler (promise) { this.resolved = false this.error = null if (!promise) { this.data = null return } promise.then(data => { this.data = data this.resolved = true }) .catch(err => { this.error = err this.resolved = true }) }, immediate: true } } } </script>

这是怎么回事,小老弟?首先,请注意,该组件接收一个Promise 类型参数。在 watch 部分中,监听 promise 的变化,当 promise 发生变化时,清除状态,然后调用 then 并 catch promise,当 promise 成功完成或失败时更新状态。

然后,在模板中,我们根据状态显示一个不同的槽。请注意,我们没有保持它真正的无渲染,因为我们需要一个根元素来使用模板。我们还将 data 和 error 传递到相关的插槽范围。

<template> <div> <promised :promise="somePromise"> <template #resolved="{ data }"> Resolved: {{ data }} </template> <template #rejected="{ error }"> Rejected: {{ error }} </template> <template #pending> 请求中... </template> </promised> </div> </template> ...

我们将 somePromise 传递给无渲染组件。 然后等待它完成,对于 pending 的插槽,显示“请求中...”。 如果成功,显示“Resolved:对应的值”。 如果失败,显示“已Rejected:失败的原因”。 现在我们不再需要跟踪此组件中的 promise 的状态,因为该部分被拉出到它自己的可重用组件中。

那么,我们可以做些什么来绕过 promised.vue 中的插槽? 要删除它,我们需要删除 template 部分并向我们的组件添加 render 函数:

render () { if (this.error) { return this.$scopedSlots['rejected']({error: this.error}) } if (this.resolved) { return this.$scopedSlots['resolved']({data: this.data}) } return this.$scopedSlots['pending']() }

这里没有什么太复杂的。我们只是使用一些 if 块来查找状态,然后返回正确的作用域 slot (通过 this.$ scopedslot ['SLOTNAME'](…) ),并将相关数据传递到 slot 作用域。当你不使用模板时,可以跳过使用 .vue 文件扩展名,方法是将JavaScript从 script 标记中提取出来,然后将其放入 .js 文件中。在编译这些Vue文件时,这应该会给你带来非常小的性能提升。

总结

Vue的插槽将基于组件的开发提升到了一个全新的水平,虽然本文已经展示了许多可以使用插槽的好方法,但还有更多的插槽。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/64bf7fbb7f3a7afa8eb3262d5bacee8e.html