Vue基础篇:组件中slot插槽和作用域插槽

858 阅读3分钟
一、什么时候会用到插槽

当父组件需要向子组件传递dom内容时:

<!DOCTYPE html>
<html>
<head>
    <title>插槽</title>
    <script type="text/javascript" src="./vue-dev.js"></script>
</head>
<body>
    <div id="app">
        <child content="<div><p>chonglou</p></div>"></child>
    </div>
    <script type="text/javascript">

     Vue.component('child', {
         props: ["content"],
         template: '<div v-html="this.content"></div>',
    })

    var vm = new Vue({
        el: '#app',
       
    })
    </script>
</body>
</html>

二、如何使用插槽slot

当父组件向子组件传递的数据含有较多dom内容,无法只用一个div包裹时,需要借助于Vue框架提供的内置语法slot,在slot里插入父组件向子组件传递的dom内容。

<!DOCTYPE html>
<html>
<head>
    <title>插槽</title>
    <script type="text/javascript" src="./vue-dev.js"></script>
</head>
<body>
    <div id="app">
        <child>
        	<!-- 插入要写入的html内容 -->
            <div><p>chonglou</p></div>
        </child>
    </div>
    <script type="text/javascript">

     Vue.component('child', {
         props: ["content"],
         template: `<div>
                     <p>Hello</p>
                     <slot>默认内容</slot> //重点
                   </div>`,
    })

    var vm = new Vue({
        el: '#app',
      
    })
    </script>
</body>
</html>
slot标签之间,可以设置默认内容,当有内容传入时,则会被替代
三、具名插槽slot的使用

问题: 如果没定义父组件插入子组件的内容的唯一性,那么子组件接收多个插入内容,就会被一个slot同时占用并使用

<!DOCTYPE html>
<html>
<head>
    <title>插槽</title>
    <script type="text/javascript" src="./vue-dev.js"></script>
</head>
<body>
    <div id="app">
        <child>
            <div class="header">header</div>
            <div class="footer">footer</div>
        </child>
    </div>
    <script type="text/javascript">
    Vue.component('child', {
        props: ["content"],
        template: `<div>
                     <slot></slot> 
                     <p>Hello</p>
                     <slot></slot> 
                   </div>`,
    })

    var vm = new Vue({
        el: '#app',

    })
    </script>
</body>
</html>

如图:

解决办法 - 具名插槽的使用

slot: 分别命名父组件和子组件的插槽名,对传递内容进行唯一性的标识

<!DOCTYPE html>
<html>
<head>
    <title>插槽</title>
    <script type="text/javascript" src="./vue-dev.js"></script>
</head>
<body>
    <div id="app">
        <child>
            <div class="header" slot="header">header</div>
            <div class="footer" slot="footer">footer</div>
        </child>
    </div>
    <script type="text/javascript">
    Vue.component('child', {
        props: ["content"],
        template: `<div>
                     <slot name="header"></slot> 
                     <p>Hello</p>
                     <slot name="footer"></slot> 
                   </div>`,
    })

    var vm = new Vue({
        el: '#app',

    })
    </script>
</body>
</html>

如图:

注意,具名插槽具有默认性,当没有定义对于名称的插槽时,如果有默认内容会显示默认内容,没有的话,则不会展示该dom标签

四、作用域插槽

当子组件做循环显示列表 或 某一部分由外部传递进来 时,则使用 作用域插槽

<!DOCTYPE html>
<html>
<head>
    <title>作用域插槽</title>
    <script type="text/javascript" src="./vue-dev.js"></script>
</head>
<body>
    <div id="app">
        <child>
        	<!--  slot-scope 指定接收数据名称 -->
            <template slot-scope="props">
                   <li>{{props.item}}</li>
            </template>
        </child>
    </div>
    <script type="text/javascript">
    Vue.component('child', {
        props: ["content"],
        data(){
        	return{
                 list:['1','2','3','4']
        	}
        },
        template: `<div>
                     <ul>
                        <slot v-for="item in list" :item=item></slot> //传递数据
                     </ul>
                   </div>`,
    })

    var vm = new Vue({
        el: '#app',

    })
    </script>
</body>
</html>

如图:

注:

 1. 子组件向父组件插槽里传数据,如 :item=item

 2. 父组件接收数据并需在外层使用作用域插槽(必须用) <template></template>,同时声明属性名 接收子组件传递的数据,如 slot-scope="props" , 然后在dom标签使用该数据,通常用插值表达式接收具体数据。