程序员让前端飞Web前端之路

大前端之vue插槽slot

2020-04-21  本文已影响0人  裸泳的小熊

什么是插槽?
在vue中通过slot可以向组件中指定位置插入内容。

正常情况下调用一个组件<com-form></com-form>的时候,组件显示的内容为com-input组件中模板的内容。可是想在调用组件的时候给组件添加内容,该怎么办呢?

//父组件
<com-form>
  <span>我是插槽内容</span>
</com-form>
//子组件com-form
<templete>
<div>
  我是组件内容
  <slot></slot>
</div>
</templete>
//显示---我是组件内容 我是插槽内容

插槽的通俗理解就是是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中<slot>位置),当插槽也就是坑<slot name=”mySlot”>有命名时,组件标签中使用属性slot=”mySlot”的元素就会替换该对应位置内容。

一、单个插槽/默认插槽/匿名插槽

首先是单个插槽,单个插槽是vue的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。
单个插槽可以放在组件任意位置,但是一个组件有且只能有一个单个插槽,相对应的,具名插槽就可以有很多个。

父组件:
<template>
    <div class="father">
        <h3>这里是父组件</h3>
        <child>
            <div class="tmpl">
              <span>菜单1</span>
              <span>菜单2</span>
              <span>菜单3</span>
              <span>菜单4</span>
              <span>菜单5</span>
              <span>菜单6</span>
            </div>
        </child>
    </div>
</template>
子组件:
<template>
    <div class="child">
        <h3>这里是子组件</h3>
        <slot></slot>
    </div>
</template>
最终显示

二、具名插槽

匿名插槽没有name属性,所以是匿名插槽,那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次,出现在不同的位置。下面的例子,就是一个有两个具名插槽和单个插槽的组件,这三个插槽被父组件用同一套css样式显示了出来,不同的是内容上略有区别。

父组件:
<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <child>
      <div class="tmpl" slot="up">
        <span>菜单1</span>
        <span>菜单2</span>
        <span>菜单3</span>
        <span>菜单4</span>
        <span>菜单5</span>
        <span>菜单6</span>
      </div>
      <div class="tmpl" slot="down">
        <span>菜单-1</span>
        <span>菜单-2</span>
        <span>菜单-3</span>
        <span>菜单-4</span>
        <span>菜单-5</span>
        <span>菜单-6</span>
      </div>
      <div class="tmpl">
        <span>菜单->1</span>
        <span>菜单->2</span>
        <span>菜单->3</span>
        <span>菜单->4</span>
        <span>菜单->5</span>
        <span>菜单->6</span>
      </div>
    </child>
  </div>
</template>
子组件:
<template>
  <div class="child">
    // 具名插槽
    <slot name="up"></slot>
    <h3>这里是子组件</h3>
    // 具名插槽
    <slot name="down"></slot>
    // 匿名插槽
    <slot></slot>
  </div>
</template>
最终显示

三、作用域插槽

匿名插槽和具名插槽都是在父组件中定义内容与样式,子组件只是负责放在哪。但是如果子组件提供数据,那这样的话需要子组件的<slot>把数据传递给父组件,父组件只需要提供样式即可。

子组件child
<template>
  <div class="child">

    <h3>这里是子组件</h3>
    // 作用域插槽
    <slot  :data="data"></slot>
  </div>
</template>

 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    }
}
父组件
<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <!--第一次使用:用flex展示数据-->
    <child>
      <template slot-scope="user">
        <div class="tmpl">
          <span v-for="item in user.data">{{item}}</span>
        </div>
      </template>

    </child>

    <!--第二次使用:用列表展示数据-->
    <child>
      <template slot-scope="user">
        <ul>
          <li v-for="item in user.data">{{item}}</li>
        </ul>
      </template>

    </child>

    <!--第三次使用:直接显示数据-->
    <child>
      <template slot-scope="user">
       {{user.data}}
      </template>

    </child>

    <!--第四次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
    <child>
      我就是模板
    </child>
  </div>
</template>
最终展示

四、v-slot

在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slotslot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。

// 根组件
<template>
    <div>
        <mo>
            <template v-slot:header="slotProps">
                <h1>{{slotProps.header + ' ' + msg}}</h1>
            </template>
            <p>A paragraph for the main content.</p>
            <p>And another one.</p>
            <template v-slot:footer>
                <p>Here's some contact info</p>
            </template>
        </mo>
    </div>
</template>
<script>
    import mo from './module.vue'
    export default {
        components: {
            mo
        },
        data() {
            return {
                msg: '这是根组件的消息'
            }
        }
    }
</script>
// 子组件
<template>
    <div>
        --header start--
        <header>
            <slot name="header" :header="header"></slot>
        </header>
        --header over--
        <div></div>
        --default start--
        <slot></slot>
        --default over--
        <div></div>
        --footer start--
        <footer>
            <slot name="footer"></slot>
        </footer>
        --dooter over--
    </div>
</template>
<script>
    export default {
        data() {
            return {
                header: '来自子组件的头部消息'
            }
        }
    }
</script>
<style scoped>
</style>
最终显示
上一篇 下一篇

猜你喜欢

热点阅读