Vue.js(六)—— 组件:slot用法

目录

一、默认情况下(不使用slot)

二、单个slot

三、具名slot

四、编译作用域

五、默认插槽的内容

六、作用域插槽

七、访问slot


Vue 实现了一套内容分发的 API,将 <slot> 元素作为承载分发内容的出口。

简单来讲:默认情况下我们在父组件中加入到子组件的DOM是不会显示的,但是如果我们需要插入一段DOM,那么这段DOM是否显示,如何显示,显示在什么位置,就需要使用slot内容分发。

一、默认情况下(不使用slot)

正常情况下我们在引用子组件时另加的标签是不会展示的,举例说明:

<!-- 这是父组件 father.vue 的内容 -->
<template>
    <div class='app-container'>
       <son>
          <p>这是父组件想要放到子组件里面的内容</p>
       </son>
    </div>
</template>
<script>
import son from './son';
export default {
  components: {
    son
  },
};
</script>


<!-- 这是子组件 son.vue 的内容 -->
<template>
    <div class='app-container'>
        <p>这是一个子组件--start--</p>
        <p>这是一个子组件--end--</p>
    </div>
</template>

虽然我们在<son></son>标签内部加入了一段HTML代码,但是在渲染的过程中,这段代码是不会显示的。渲染结果如下:

怎么才能显示出父组件想要放在子组件的内容呢?这就需要用到slot内容分发。

二、单个slot

如果我们在子组件内部添加了一个<slot></slot>标签做一个占位,就可以将父组件想要放在子组件的内容,放到想让他显示的地方(即slot标签所在的地方);也就是说:父组件放在子组件里的内容,插入到了子组件的<slot></slot>位置。

注意,即使有多个标签,也会一起被插入,相当于用父组件放在子组件里的所有标签,替换了<slot></slot>这个标签。

如:在上述示例的 son.vue 文件中加入slot,具体如下:

此时的渲染结果就变成了如下的结果,成功的将父组件插入在子组件内的DOM显示了出来。

三、具名slot

给<slot>元素指定一个name后可以分发多个内容,具名slot可以和单个slot共存。

<!-- 这是父组件 father.vue 的内容 -->
<template>
    <div class='app-container'>
       <son>
          <p slot="header">这是父组件想要插入到具名slot:header的内容</p>
          <p slot="footer">这是父组件想要插入到具名slot:footer的内容</p>
       </son>
    </div>
</template>
<script>
import son from './son';
export default {
  components: {
    son
  },
};
</script>


<!-- 这是子组件 son.vue 的内容 -->
<template>
    <div class='app-container'>
        <p>这是一个子组件--start--</p>
        <slot name="header"></slot>
        <p>这是子组件本身的内容</p>
        <slot name="footer"></slot>
        <p>这是一个子组件--end--</p>
    </div>
</template>

渲染结果如下,多个标签分别渲染到了其对应的具名slot指向的位置,而父组件中没有指定 slot="xxx" 的标签会被统一渲染到不单个<slot></slot>位置: 

四、编译作用域

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

<p slot="header"></p>受父组件的控制,如果想要调用某个方法,则该方法需要被定义在父组件的methods当中。 

五、默认插槽的内容

很多时候,我们可以为 slot 设置默认内容,当父组件中有内容传入的时候,会替换该默认内容;若是父组件中不传入任何内容,则默认内容显示。

<!-- 这是父组件 father.vue 的内容 -->
<template>
    <div class='app-container'>
       <son>
            <!-- 父组件什么都不传入 -->
       </son>
    </div>
</template>
<script>
import son from './son';
export default {
  components: {
    son
  },
};
</script>


<!-- 这是子组件 son.vue 的内容 -->
<template>
    <div class='app-container'>
        <p>这是一个子组件--start--</p>
        <button>
            <slot>默认为submit按钮</slot>
        </button>
        <p>这是一个子组件--end--</p>
    </div>
</template>

结果如下: 

 若有传入内容,则会替换掉默认内容:

六、作用域插槽

作用域插槽是一个特殊的slot,使用一个可以复用的模板替换已渲染的元素。

6.1 具体用法:

(1)在父组件中传入由一个 <template></template> 标签包裹的DOM元素,并且这个 template 标签拥有 slot-scope="props" 属性;(props 相当于一个临时变量,有点类似于 v-for 里面的 item,一般叫props,可以换成任何名称)

(2)通过props就可以访问来自子组件slot的数据;

<!-- 这是父组件 father.vue 的内容 -->
<template>
    <div class='app-container'>
        <son>
            <template slot-scope="props">
                <p>父组件传入的内容</p>
                <p>{{props.msg}}</p>
            </template>
        </son>
    </div>
</template>
<script>
import son from './son';
export default {
    components: {
        son
    },
};
</script>


<!-- 这是子组件 son.vue 的内容 -->
<template>
    <div class='app-container'>
        <p>这是一个子组件--start--</p>
        <slot msg="子组件传过来的msg"></slot>
        <p>这是一个子组件--end--</p>
    </div>
</template>

结果如下:

 在 2.5.0+,slot-scope 不再限制在 <template> 元素上使用,而可以用在插槽内的任何元素或组件上。

七、访问slot

在子组件中可以通过 this.$slots 来获取被 slot 访问的内容(貌似没有用到过这个==)

<!-- 子组件 son.vue -->
<template>
    <div class='app-container'>
        <p>这是一个子组件--start--</p>
        <slot name="header">123</slot>
        <slot name="footer">123</slot>
        <slot></slot>
        <p>这是一个子组件--end--</p>
    </div>
</template>
<script>
export default {
  mounted() {
    console.log(this.$slots);    // Object 所有的slot
    console.log(this.$slots.header);       // 获取name=header的slot
    console.log(this.$slots.footer);
    console.log(this.$slots.default);      // 获取所有具名slot之外的slot
  }
};
</script>

猜你喜欢

转载自blog.csdn.net/xiaomajia029/article/details/83056024