Web全栈探索,Vue基础系列,组件化开发(四)组件插槽

组件插槽 slot

1.作用

父组件向子组件传递内容(这里的内容指模板,而并非数据)

2.示例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <!--添加的值替换了默认插槽的内容-->
    <!--信息通过插槽的数据动态改变-->
    <my-slot>出现BUG</my-slot>
    <my-slot>出现警告</my-slot>
    <my-slot></my-slot>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">

    /*
      组件插槽:父组件向子组件传递内容
    */
    Vue.component('my-slot', {
        // 模拟一个提示功能
        // 第一个数据为 ERROR,有提示作用
        // 第二个参数需要根据业务动态改变,因此采用插槽 slot
        template: `
        <div>
          <strong>插槽标签:</strong>
          <slot>插槽内容</slot>
        </div>
      `
    });
    let vm = new Vue({
        el: '#app',
        data: {}
    });
</script>
</body>
</html>

3.具名插槽 ===> 有名字的插槽

(1)插槽定义

<div>
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>

(2)插槽使用

<base-layout>
    <h1 slot="header">标题内容</h1>
    <p>主要内容1</p>
    <p>主要内容2</p>
    <p slot="footer">底部内容</p>
</base-layout>

(3)示例代码1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <my-layout>
        <!--将 插槽名为 header 的插槽内容填充为 标题信息 -->
        <p slot='header'>标题信息</p>
        <p>正文内容</p>
        <p slot='footer'>底部信息信息</p>
    </my-layout>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">
    /*
      具名插槽
    */
    Vue.component('my-layout', {
        template: `
        <div>
          <header>
            <slot name='header'></slot>
          </header>
          <main>
            <slot></slot>
          </main>
          <footer>
            <slot name='footer'></slot>
          </footer>
        </div>
      `
    });
    let vm = new Vue({
        el: '#app',
        data: {
        }
    });
</script>
</body>
</html>

(4)示例代码2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <my-layout>
        <!--template的作用为临时性的包裹信息,而不会产生新的 html标签-->
        <template slot='header'>
            <p>章标题</p>
            <p>节标题</p>
        </template>
        <p>第一部分内容</p>
        <p>第二部分内容</p>
        <template slot='footer'>
            <p>底部页码</p>
            <p>底部页脚</p>
        </template>
    </my-layout>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">
    /*
      具名插槽
    */
    Vue.component('my-layout', {
        template: `
        <div>
          <header>
            <slot name='header'></slot>
          </header>
          <main>
            <slot></slot>
          </main>
          <footer>
            <slot name='footer'></slot>
          </footer>
        </div>
      `
    });
    let vm = new Vue({
        el: '#app',
        data: {
        }
    });
</script>
</body>
</html>

4.作用域插槽

应用场景: 父组件对子组件的内容进行加工处理

(1)定义与使用方法

<ul>
    <li v-for="item in list" v-bind:key="item.id">
        <!--子组件利用 v-bind 绑定一个自定义名称,该自定义名称后面的 item 为上面遍历出来的单一元素-->
        <slot v-bind:item="item">
            {{item.name}}
        </slot>
    </li>
</ul>


<my-list v-bind:list="list">
    <!--父组件可以利用 slot-scope 标签得到子组件中绑定的属性,即上面的 key 属性-->
    <template slot-scope="slotProps">
        <strong v-if="slotProps.item.current">
            {{ slotProps.item.text }}
        </strong>
    </template>
</my-list>

(2)示例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style type="text/css">
    .current {
        color: red;
    }
</style>
<body>
<div id="app">
    <!--父组件给子组件传递fruit_list_data数据-->
    <fruit-list v-bind:list='fruit_list_data'>
        <!--slot-scope 属性用于得到被 v-bind 绑定的属性值,其中参数my_slot_data为自定义名称-->
        <template slot-scope='my_slot_data'>
            <!--将 id 为 3 的数据指定样式类为 current 类 -->

            <!--利用 if else 语句将 id 为 3 的水果名字高亮 -->
            <strong v-if='my_slot_data.info.id === 3' class="current">{{my_slot_data.info.name}}</strong>
            <!--其他水果名字正常显示 -->
            <span v-else>{{my_slot_data.info.name}}</span>
        </template>
    </fruit-list>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">

    /*
      作用域插槽
    */
    Vue.component('fruit-list', {
        props: ['list'],
        template: `
        <div>
          <li :key='item.id' v-for='item in list'>
            <slot v-bind:info='item'>{{item.name}}</slot>
          </li>
        </div>
      `
    });

    let vm = new Vue({
        el: '#app',
        data: {
            fruit_list_data: [{
                id: 1,
                name: '苹果'
            },{
                id: 2,
                name: '橙子'
            },{
                id: 3,
                name: '香蕉'
            },{
                id: 4,
                name: '西瓜'
            }]
        }
    });
</script>
</body>
</html>


 

作者:蓝月

-------------------------------------------

个性签名:能我之人何其多,戒骄戒躁,脚踏实地地走好每一步

原文地址:https://www.cnblogs.com/viplanyue/p/13573722.html