Vue插槽理解

Posted Clover‘s Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue插槽理解相关的知识,希望对你有一定的参考价值。

Vue插槽理解

插槽

slot又名插槽,vue内容分发机制,组件内部的模板引擎使用slot元素作为承载分发内容的出口
插槽slot是子组件的一个模板标签元素,而这一个元素是否显示,以及怎么显示是由父组件决定的
slot分为三类:默认插槽、具名插槽、作用域插槽

  • 默认插槽

父组件代码详情


<template>
	<div class="parent">
		<h1>这里是parent组件</h1>
		<Child>
			<h3>这是parent组件传递给child组件的值</h3>
		</Child>
	</div>
</template>
<script>
import Child from "../component/Child.vue"
</script>

子组件代码详情

<template>
	<div class="child">
		<h1>这里是child组件</h1>
		<Child>
			<h3>这是child组件</h3>
			<slot></slot>
		</Child>
	</div>
</template>

运行结果:

又叫匿名插槽,当插槽slot没有指定name属性值的时候一个默认显示一个插槽,一个组件内只有一个匿名插槽

  • 具名插槽

带有具体名字的插槽,也就是带有name属性的slot,一个组件可以出现多个具名插槽
父组件代码详情

<template>
	<div class="parent">
		<h1>这里是parent组件</h1>
		<Child>
			<div slot="header">给header内容</div>
			<div slot="main">给main内容</div>
			<div slot="footer">给footer内容</div>
		</Child>
	</div>
</template>

子组件代码详情

<template>
	<div class="child">
		<h1>这里是parent组件</h1>
		<Child>
			<div name="header">给header内容</div>
			<div name="main">给main内容</div>
			<div name="footer">给footer内容</div>
		</Child>
	</div>
</template>

运行结果:

  • 作用域插槽

在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件传递过来的数据如何渲染该插槽
父组件代码详情

<template>
  <button @click="show">显示隐藏</button>
  <div class="home" v-show="isShow">
    <Dialog title="商品选择">
      <!-- 匿名插槽的使用 -->
      <!-- 写法一 -->
      <!-- 12243 -->

      <!-- 写法二 -->
      <template #default>
        <!-- 666666666666666666 -->
        <FruitList>
          <template #default="goods"> goods </template>
        </FruitList>
      </template>


      <!-- 具名插槽使用 -->
      <!-- 写法一 -->
      <!-- <template v-slot:footer>
        <Rbutton>取消</Rbutton>
        <Rbutton>确认</Rbutton>
      </template> -->

      <!-- 写法二 -->
      <template #footer>
        <Rbutton style=" display: inline-block;border-radius: 5px;margin-right: 10px;">取消</Rbutton>
        <Rbutton style="background-color: #1890ff; display: inline-block; border-radius: 5px;">确认</Rbutton>
      </template>
    </Dialog>
  </div>
</template>

<script>
import Dialog from '@/components/Dialog.vue'
import Rbutton from '@/components/Rbutton.vue';
import FruitList from '@/components/FruitList.vue';
export default 
  data()
    return
      isShow:false
    
  ,
  name: 'DialogParent',
  components: 
    Dialog,
    Rbutton,
    FruitList
  ,
  methods:
    onAddCart(gid,gname)
      console.log(gid,gname);
    ,
    show()
      this.isShow=!this.isShow
    
  
  

</script>
<style lang="scss" scoped>
.home
  // position: relative;
  background-color: yellow;

</style>

子组件代码详情

<template>
    <div class="fruit">
        <table class="ftable">
            <thead>
                <tr>
                    <td>ID</td>
                    <td>名字</td>
                    <td>价格</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="f in fruits" :key="f.id" @click="onAddCart([f.id,f.name])">
                    <td> f.id </td>
                    <td> f.name </td>
                    <td> f.price </td>
                </tr>
                <slot :goods="f"></slot>
            </tbody>
        </table>
    </div>
</template>

<script>
export default 
    data()
        return
            fruits:[
                
                    id:'01',
                    name:'苹果~~🍎',
                    price:'3.90'
                ,
                
                    id:'01',
                    name:'西瓜~~🍉',
                    price:'3.70'
                ,
                
                    id:'01',
                    name:'葡萄~~🍇',
                    price:'3.80'
                ,                
                
                    id:'01',
                    name:'橙子~~🍊',
                    price:'3.50'
                ,                
                
                    id:'01',
                    name:'香蕉~~🍌',
                    price:'3.30'
                ,
            ]
        
    ,
    methods:
        onAddCart(params)
            this.$emit('add-cart',...params)
        
    

</script>

<style lang="scss" scoped>
.fruit
    // li
    //     list-style: none;
    // 
    width: 100%;
    // height: 100%;
    // background-color: plum;
    table
        width: 95%;
        // border-radius: 20px;
        margin: 0 auto;
        border: 1px bolid black;
        thead
            width: 100%;
            // border-radius: 20px;
            // background-color: blue;
            text-align: center;
        
        tbody
            // border-radius: 20px;
            width: 100%;
            background-color: aliceblue;
            text-align: center;
        
    

</style>

**原理:**当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm. s l o t 中,默认插槽为 v m . slot中,默认插槽为vm. slot中,默认插槽为vm.slot.default,具名插槽为vm. s l o t . x x x , x x x 是插槽的名字,当组件执行渲染函数时候,遇到 s l o t 标签,使用 slot.xxx,xxx是插槽的名字,当组件执行渲染函数时候,遇到slot标签,使用 slot.xxx,xxx是插槽的名字,当组件执行渲染函数时候,遇到slot标签,使用slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则就是作用域插槽

以上是关于Vue插槽理解的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用 vue js Web 组件内部的插槽并应用样式

vue.js的插槽 - slot 是啥?要我说,它就是个“形参”

Vue.js 插槽 - 如何在计算属性中检索插槽内容

将插槽传递到 Vue.js 中的插槽

Vue.js(17)之 插槽

Vue.js 如何在插槽上使用属性