Vue插槽的理解和使用

1.什么是插槽

插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

代码如下:

1.1.在子组件中放一个占位符

<template>
  <div class="app-container">
    <div>这是子组件</div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  name:'SlotChild'
}
</script>

1.2.在父组件中给这个占位符填充内容

<template>
  <div class="app-container">
    <div>这是父组件</div>

    <slot-child>
      <template>
        <span>这是插入到插槽的内容</span>
      </template>
    </slot-child>

  </div>
</template>

<script>
import SlotChild from './slotchild'
export default {
  name: 'Index',
  components: { SlotChild }

}
</script>

1.3.展示效果:

 

现在来看看,如果插槽中没有放入插槽,同样的父组件中在子组件中填充内容,会是啥样的:

<template>
  <div class="app-container">
    <div>这是子组件</div>
    <!-- <slot></slot> -->
  </div>
</template>

<script>
export default {
  name:'SlotChild'
}
</script>

总结:如果子组件没有使用插槽,父组件如果需要往子组件中填充模板或者html, 是没法做到的

2.插槽的使用

插槽的最最简单使用,上面已有例子,这里就不写了,接下来看看,插槽其他使用场景

2.1.具名插槽

描述:具名插槽其实就是给插槽取个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。代码如下:

2.1.1.子组件的代码,设置了两个插槽(header和footer):

<template>
  <div class="app-container" style="margin-top:40px;">
    <div>这是引入的slotname子组件</div>
    <div>
      <div style="margin-top:30px;">
        <span>header:</span>
        <span style="color:red;">
      <slot name="header"></slot>
     </span> </div> </div> <div style="margin-top:20px;"> <span>footer:</span> <span style="color:red;">
      <slot name="footer"></slot>
     </span> </div> </div> </div> </template> <script> export default { name:'SlotName' } </script>

2.1.2.父组件填充内容, 父组件通过 v-slot:[name] 的方式指定到对应的插槽中

<template>
  <div class="app-container">
    <div>这是父组件</div>

    <slot-name>
      <template v-slot:header>
        <span>这是插入到header插槽的内容</span>
      </template>

      <template v-slot:footer>
        <h1span>这是插入到footer插槽的内容</h1span>
      </template>
    </slot-name>

  </div>
</template>

<script>
import SlotName from './slotname'
export default {
  name: 'Index',
  components: { SlotName }
}
</script>

2.1.3.展示效果

 2.1.4.即使父组件对插槽的填充的顺序打乱,只要名字对应上了,就可以正确渲染到对应的插槽中。即: 父组件填充内容时,是可以根据这个名字把内容填充到对应插槽中的

2.2.默认插槽

默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。

2.2.1.子组件的代码,设置了三个插槽(header和footer和默认):

<template>
  <div class="app-container" style="margin-top:40px;">
    <div>这是引入的子组件</div>

    <div style="margin-top:30px;">
      <div>
        <span>header:</span>
        <span style="color:red;"><slot name="header"></slot></span>
      </div>
    </div>

    <div style="margin-top:30px;">
      <div>
        <span>这是默认插槽:</span>
        <span style="color:red;"><slot></slot></span>
      </div>
    </div>

    <div style="margin-top:20px;">
      <div>
        <span>footer:</span>
        <span style="color:red;"><slot name="footer"></slot></span>
      </div>
    </div>

  </div>
</template>

<script>
export default {
  name:'SlotDefault'
}
</script>

2.2.2.父组件填充默认插槽内容内容

<template>
  <div class="app-container">
    <div>这是父组件</div>

    <slot-default>

      <template v-slot:header>
        <span>这是插入到header插槽的内容</span>
      </template>


      <template>
        <span>这是插入到默认插槽的内容</span>
      </template>

      <template v-slot:footer>
        <span>这是插入到footer插槽的内容</span>
      </template>
    </slot-default>

  </div>
</template>

<script>
import SlotDefault from './slotdefault'
export default {
  name: 'Index',
  components: { SlotDefault }

}
</script>

2.2.3.展示效果

 

2.2.4.总结

1.  父级的填充内容如果指定到子组件的没有对应名字插槽,那么该内容不会被填充到默认插槽中。

2.  如果子组件没有默认插槽,而父级的填充内容指定到默认插槽中,那么该内容就“不会”填充到子组件的任何一个插槽中。

3.  如果子组件有多个默认插槽,而父组件所有指定到默认插槽的填充内容,将“” “全都”填充到子组件的每个默认插槽中。

2.3.作用域插槽

作用域插槽:<slot :自定义name=data中的属性或对象></slot>

通过上边的默认插槽和具名插槽的使用过程中,发现,基本都是父组件中决定要插入到子组件中的内容,而子组件自行决定插槽的位置。

作用域插槽,就是实现在子组件中自行决定自己要显示什么内容。

作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。

2.3.1.作用域插槽使用场景之一(常用)

如果子组件中的某一部分的数据,每个父组件都会有自己的一套对该数据的不同的呈现方式,这时就需要用到作用域插槽。

2.3.2.子组件的代码

<template>
  <div class="app-container">

    <div>这是slotzuoyongyu子组件</div>

    <slot :adata="adata"></slot>

  </div>
</template>

<script>
export default {
  name:'SlotZuoyongyu',
  data(){
    return {
      adata:[
        'zhangsan',
        'lisi',
        'wangwu',
        'zhaoliu',
        'tianqi',
        'xiaoba'
      ]
    }
  }

}
</script>

2.3.3.父组件代码

<template>
  <div class="app-container">
    <div>这是父组件</div>

    <slot-zuoyongyu>

      <template slot-scope="auser">
        <span v-for="(item, index) in auser.adata" :key="index"> {{item}}--- {{index}}</span>
      </template>

    </slot-zuoyongyu>

  </div>
</template>

<script>
import SlotZuoyongyu from './slotzuoyongyu'
export default {
  name: 'Index',
  components: { SlotZuoyongyu }
}
</script>

2.3.4.展示的效果

参考---https://www.cnblogs.com/mandy-dyf/p/11528505.html

参考---https://blog.csdn.net/qq_44166697/article/details/108274625?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-1&spm=1001.2101.3001.4242

原文地址:https://www.cnblogs.com/pwindy/p/14768020.html