Vue.js中插槽的使用

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

一、单个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>

请查看效果:https://codepen.io/riafan/pen/JLRgNd

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

二、指定名称的slot

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

Dialog

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

<script type="x/template" id="modal-template">
  <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>
</script>    

父组件模板:

<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>

请查看效果:https://codepen.io/riafan/pen/JLRgNd

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

参考资源: https://v1.vuejs.org/guide/components.html#Compilation-Scope

发表评论

电子邮件地址不会被公开。 必填项已用*标注