使用 Vue 组件插槽

Flying
2016-11-26 / 0 评论 / 84 阅读 / 正在检测是否收录...

为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个处理称为内容分发,Vue.js 实现了一个内容分发 API,使用特殊的元素作为原始内容的插槽。如果你是 AngularJS 用户,slot 就和的“transclude”差不多。

layout-slots.svg

一、单个 Slot

当子组件模板只有一个没有属性的插槽时,父组件传入的整个内容片段将插入到插槽所在的 DOM 位置,并替换掉插槽标签本身。

假定 my-component 组件有如下模板:

<div id="app">
  <my-component>
    <div>This is the body</div>
  </my-component>
  <hr/>
  <my-component></my-component>
</div>

父组件模板:

<template id="myComponent">
  <h3>This is the title</h3>
  <div class="content">
    <slot>This is the fallback content.</slot>
    <div>This is the footer.</div>
  </div>
</template>

可以看出,第一个标签有一段分发内容 <div>This is the body</div>,渲染组件时显示了这段内容。第二个标签则没有,渲染组件时则显示了 slot 标签中的备用内容。这是因为最初在标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。

二、指定名称的 slot

上面这个示例是一个匿名 slot,它只能表示一个插槽。如果需要多个内容插槽,则可以为 slot 元素指定 name 属性。多个 slot 一起使用时,会非常有用。例如,对话框是 HTML 常用的一种交互方式。在不同的运用场景下,对话框的头部、主体内容、底部可能是不一样的。

模态框

例如,假定我们有一个 modal 组件,它的模板为:

<div class="modal-mask" v-if="shown" transition="modal">
  <div class="modal-wrapper">
    <div class="modal-container">
      <div class="modal-header" name="header">
        <slot name="header">
          default header
        </slot>
      </div>

      <div class="modal-body">
        <slot name="body">
          default body
        </slot>
      </div>

      <div class="modal-footer">
        <slot>
          <button class="btn default-button"
            @click="shown=false">
            OK
          </button>
        </slot>
      </div>
    </div>
  </div>
</div>   

父组件模板:

<div id="app">
  <button class="btn btn-open" id="show-modal" @click="showModal=true">Show Modal</button>
  <modal :shown.sync="showModal">
    <div slot="header">
      <div class="modal-title">
        Put title here
      </div>
      <div class="icon-close" @click="showModal=false">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
          <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
        </svg>
      </div>
    </div>
    <div slot="body">
      <p>Please put some content here</p>
    </div>
  </modal>
</div>

查看效果

访问 Codepen 查看代码及最终效果

指定名称的 slot,仍然可以有一个匿名插槽,它是默认插槽,作为找不到匹配的内容片段的备用插槽。如果没有默认插槽,这些找不到匹配的内容片段将被抛弃。模态框底部的插槽就是这样的插槽。通过插槽,可以在子组件中使用自定义内容来覆盖父组件中默认内容,从而大大提高了组件的可重用性。

参考资源

Component slots

3

评论 (0)

取消