vue组件化-插槽

目录

为什么要使用插槽?

匿名插槽

具名插槽

 作用域插槽

 编译作用域

 默认的插槽内容

访问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代码,但是在渲染的过程中,这段代码是不会显示的。渲染结果如下: 

总结

正常情况下,父组件调用子组件是没问题的。但是如果父组件调用子组件需要往子组件插入内容,就需要用到插槽,否则插入内容无效


匿名插槽

如果按上面的例子往子组件中放入匿名插槽

 

很显然,父组件插入的内容显示出来了。所以,如果需要在父组件往调用的子组件当中插入内容。使用插槽是很有用的 


具名插槽

看完匿名插槽的简单使用,再来看看具名插槽

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>具名插槽</title>
</head>

<body>
  <div id="app">
    <!-- 3.使用子组件 -->
    <App></App>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>

  <script>
    // 只要匹配到slot标签的name值 template中的内容就会被插入到这个槽中
    Vue.component('MBtn', {
      template: `
                <button>
                     <slot name='submit'></slot>
                     <slot name='login'></slot>
                     <slot name='register'></slot>
                </button>
            `
    })

    const App = {
      data() {
        return {
          title: "老爹"
        }
      },

      template: `
                <div>
                     <m-btn>
                         <template slot='submit'>
                             提交
                         </template>
                     </m-btn>
                    
                    <m-btn>
                        <template slot='login'>
                            <a href="#">登录</a>
                        </template>
                    </m-btn>
                   
                    <m-btn>
                        <template slot='register'>
                            注册
                        </template>
                    </m-btn>
                </div>
            `,
    }
    new Vue({
      el: '#app',
      data: {

      },
      components: {
        // 2.挂载子组件
        App
      }

    })
  </script>
</body>

</html>

看看效果:


 作用域插槽

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <!-- 3.使用子组件 -->
        <App></App>
        
    </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>

    <script>
        // 已经开发了一个待办事项列表的组件,很多模块都在
        // A B
        // 1.之前数据格式和引用接口不变,正常显示
        // 2.新功能模块增加对勾
        const todoList = {
            data() {
                return {

                }
            },
            props: {
                todos: Array,
                defaultValue: []
            },
            template: `
        <ul>
            <li v-for='item in todos' :key='item.id'>
                <slot :row='item'>
                   
                 </slot>
                    {{item.title}}
               
            </li>
        </ul>
        `
        }
        const App = {
            data() {
                return {
                    todoList: [{
                            title: '大哥你好么',
                            isComplate: true,
                            id: 1
                        },
                        {
                            title: '小弟我还行',
                            isComplate: false,
                            id: 2
                        },
                        {
                            title: '你在干什么',
                            isComplate: false,
                            id: 3
                        },
                        {
                            title: '抽烟喝酒烫头',
                            isComplate: true,
                            id: 4
                        }
                    ]
                }
            },
            components: {
                todoList
            },
            template: `
            	  <todoList :todos='todoList'>
                     <template v-slot='{row}'>
                        <input type="checkbox" v-model='row.isComplate' />
                    </template>
            	  </todoList>
        `,
        }
        new Vue({
            el: '#app',
            data: {

            },
            components: {
                App
            }

        })
    </script>
</body>

</html>

以下是效果图


 编译作用域

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


 默认的插槽内容

顾名思义就是在子组件添加默认插槽内容,父组件默认传入这些内容

<!-- 这是父组件 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 

通过this.$slots.name获取具名插槽

this.$slots是vue里面的一个只读的api,用来访问被插槽分发的内容。每个具名插槽有其相应的 property (例如:v-slot:foo 中的内容将会在 vm.$slots.foo 中被找到)。default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容。

this.$slots其实会去寻找DOM元素对应的插槽只有在mounted的阶段,DOM才被挂载成功

<!-- 子组件 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 {
//只有在Dom加载完毕之后才能使用this.$slots获取到相应插槽
  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>


插槽内容其实挺简单的,就是有点绕。梳理一下就行,学习愉快!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值