Vue插槽(slot-scope):困扰我多年的心头恨,今天终于搞定了。

一、正常状况下,咱们在父组件中使用子组件的方式:
父组件引入子组件,而且传递给子组件数据,而后就能够显示出来了javascript

// Prarent.vue
<template>
  <div class="hello">
    <child :items="programList"></child>
  </div>
</template>

<script>
import child from './child'
export default {
  name: 'Prarent',
  components: {
    child
  },
  data() {
    return {
      programList: [
        {
          id: 1,
          name: '节目A',
          width: 800,
          height: 800
        },
        {
          id: 2,
          name: '节目B',
          width: 500,
          height: 500
        }
      ]
    }
  },
  created() {},
  mounted() {},
  methods: {}
}
</script>
// child.vue
<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{item.name}}</li>
  </ul>
</template>

<script>
export default {
  name: 'Child',
  components: {},
  props: {
    items: [Array, Object]
  },
  data() {
    return {}
  },
  created() {},
  mounted() {},
  methods: {}
}
</script>

浏览器显示结果:vue

节目A
节目B

二、默认插槽:就是光秃秃的slot,身上啥都没有。
我在子组件添加一对标签作占位,而后在父组件对应的地方写点东西,就能够连起来显示出来。java

// child.vue
<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{item.name}}<slot></slot></li>
  </ul>
</template>
// parent.vue
<template>
  <div class="hello">
    <child :items="programList">——我是多余的</child>
  </div>
</template>

浏览器显示:web

节目A ——我是多余的
节目B——我是多余的

三、具名插槽:就是带了一个名字name的slot,方便别人好找。
就算带名字的占位的,父组件派过去的小弟,大家本身按照名字去找座位坐下来。浏览器

// child.vue
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <div>
        <slot name="header"></slot>
      </div>
      {{item.name}}
      <slot></slot>
    </li>
  </ul>
</template>
<template>
  <div class="hello">
    <child :items="programList">
      ——我是多余的默认插槽
      <template slot="header">我是具名插槽,我要坐我本身的位置。</template>
    </child>
  </div>
</template>

浏览器显示:svg

我是具名插槽,我要坐我本身的位置。
节目A——我是多余的默认插槽
我是具名插槽,我要坐我本身的位置。
节目B——我是多余的默认插槽

备注:v2.6新增v-slot替代老方法, 就是在template标签上用v-slot:插槽名来绑定具名插槽。学习

// partent.vue
<template>
  <div class="hello">
    <!--具名插槽-->
    <child :items="programList">
      <template v-slot:header>我是向具名插槽提供的数据</template>
    </child>
  </div>
</template>

四、做用域插槽:就是身上绑定了数据data的slote。spa

// child.vue
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :data="item"></slot>
       {{item.width}} - {{item.height}} // 在这里加工数据了
    </li>
  </ul>
</template>
// parent.vue
<template>
  <div class="hello">
    <child :items="programList">
      <template slot-scope="slotProps">
        <span>***</span> // 父组件在这里自定义了东西
        {{slotProps.data.name}}
      </template>
    </child>
  </div>
</template>

显示器结果:code

// ***是父组件拿到传回来的数据后加工显示的,
// 800-800,500-500这种是子组件在里面加工了。
*** 节目A 800 - 800
*** 节目B 500 - 500

这里有几点说明:
1)slotProps是能够随便取名的, slot-scope=“xxx”,
那么 {{xxx.data.name}}里面就用xxx。
2)slotProps.data这里为何是data呢? 由于child.vue中<slot :data="item">{{item.name}}</slot>这里绑定的是data。
若是<slot :HaHa="item">{{item.name}}</slot>绑定的是HaHa,那么,父组件用的时候,就须要改为{{slotProps.HaHa.name}}component

备注:v2.6新增v-slot替代slot-scope老方法,

// parent.vue
<template>
  <div class="hello">
    <child :items="programList">
      <template v-slot:default="slotProps">
        <span>***</span>
        {{slotProps.data.name}}
      </template>
    </child>
  </div>
</template>

这里的default指默认插槽,能够对应其余的header、footer等插槽名称。若是只有默认插槽,default能够省略,简写成v-slot="slotProps

parent.vue
<template>
  <div class="hello">
    <child :items="programList">
      <template v-slot="slotProps">
        <span>***</span>
        {{slotProps.data.name}}
      </template>
    </child>
  </div>
</template>

就算这么简单,so easy, 麻麻不再用担忧个人学习。

补充说明:为何有做用域插槽这个奇葩呢?别人写好了一个组件,该组件已经封装好了,但他以为,数据的显示风格让用户本身定义,一开始最初的数据是咱们传进去的,通过别人写好的组件转了一圈,被别人改造了一下(譬如洗了个头,刮了个胡子),再传出来,给用户本身用,用户你再给他穿红色的衣服仍是粉色的衣服,用户本身决定吧。