0.什么是插槽

插槽(slot)的出现主要是为了父组件向子组件中加入内容。类似一个占位符,我们常说的“一个萝卜一个坑”,slot就是那个坑,在子组件中给你挖好了坑,然后在通过父组件来填坑。

1.默认插槽

我们创建一个vue项目。App.vue作为父组件参考如下:

<template>
  <div id="app">
    <div>我是父组件APP</div>
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

子组件HelloWorld组件,一开始没有引入插槽,参考如下:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
   
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

效果图如下:

我们在子组件中加入slot标签:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
        <!-- 引入插槽 -->
    <slot></slot>     
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

此时刷新页面发现没有效果,因为我们只是挖好了坑,还没有填充内容。我们在父组件中引入子组件时填充内容:

<template>
  <div id="app">
    <div>我是父组件APP</div>
    <HelloWorld msg="Welcome to Your Vue.js App">
        <h5>我是在父组件,填充子组件内容</h5>
    </HelloWorld>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

效果如下:

这就是基础用法。

2.具名插槽

什么是具名插槽,其实就是给slot起个名字,在父组件调用时,根据名字对应插入信息。

我们在子组件中定义两个具名插槽。

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
        <!-- 引入插槽 -->
    <slot name="type1"></slot>     
    <slot name="type2"></slot> 
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

然后在父组件中分别使用具名插槽:

<template>
  <div id="app">
    <div>我是父组件APP</div>
    <HelloWorld msg="Welcome to Your Vue.js App">
        <template slot="type1">
        <p>type1</p>
      </template>
      <template slot="type2">
        <p>type2</p>
      </template>
    </HelloWorld>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

效果如下:

上面也可以写成下面这种形式:

  <template  v-slot:type1>
        <p>type1</p>
      </template>
3.作用域插槽

作用域插槽就是在父组件调用子组件时,由父组件决定显示的具体内容。

我们修改子组件内容:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <slot :obj="info">{{info}}</slot>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      info: "默认信息"
    }
  }

}
</script>

然后父组件直接使用插槽的话就会显示子组件的默认内容:

<template>
  <div id="app">
    <div>我是父组件APP</div>
    <HelloWorld msg="Welcome to Your Vue.js App">
  
    </HelloWorld>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

效果:

我们修改子组件:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <slot name='type1' :value1="info1">{{info1}}</slot>
    <br>
    <slot :value2="info2">{{info2}}</slot>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      info1: "默认信息1",
      info2: "默认信息2"
    }
  }
}
</script>

第一个插槽我们起名了,叫type1,第二个插槽没有没名字,这样就站好了两个坑。

然后我们在父组件里直接填充数据:

<template>
  <div id="app">
    <div>我是父组件APP</div>
    <HelloWorld msg="Welcome to Your Vue.js App">
      <!-- 有名字的 -->
      <template v-slot:type1>  
           修改信息1
      </template>
      <!-- 没有名字默认 -->
      <template>  
           修改信息2
      </template>
    </HelloWorld>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

效果:

可以看到,填充了数据。

4.简单总结

作用域插槽实际开发用的可能多一些,一般都是初始加载时显示子组件一个默认页面,等待后台数据返回后再填充数据到子组件中。