vue插槽的使用

什么是插槽?

插槽就是子组件中提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

插槽又分为匿名插槽、具名插槽以及作用域插槽。

1、匿名插槽

匿名插槽,又可以叫它单个插槽或者默认插槽。与具名插槽相对,它不需要设置name属性。(它隐藏的name属性为default。)

<!-- 子组件 -->
<template>
  <div class="hello">
     <div class="slotText">
       <slot></slot>
     </div>
  </div>
</template>
<!-- 父组件 -->
<template>
  <div class="home">
    <child>
      <h1>我是子组件中的插槽啊</h1>  
    </child>
  </div>
</template>

2、具名插槽

插槽有一个name属性。与匿名插槽相对,加了name属性的匿名插槽就是具名插槽。

<!-- 子组件 -->
<template>
  <div class="hello">
    <div class = 'slotLeft'>
       <slot name='left'></slot>
     </div>
     <div class = 'slotRight'>
       <slot name='right'></slot>
     </div>
  </div>
</template>
<!-- 父组件 -->
<!-- 父组件中通过在template上写v-slot:name来使用具名插槽 -->
<template>
  <div class="home">
    <child>
        <template v-slot:left>
            <h1>name属性为left</h1> 
         </template>
         <template v-slot:right>
            <h1>name属性为right</h1> 
         </template>
    </child>
  </div>
</template>

注意:

  • v-slot 只能添加在template标签上 (只有一种例外情况)。
  • 例外情况(被废弃的slot=‘name’)
  • 带slot属性的具名插槽自 2.6.0 起被废弃,vue3.x被完全废弃。只有vue3之前的cli可以使用。

语法:

  • v-slot:header="data",这一句首先是让该标签渲染到name属性为(header)的slot标签上,然后data就是保存的整个子组件在slot上的属性.
  • 它还有个语法糖简写形式v-slot:name等价于#name,也就是用一个#号代替v-slot:
<!-- 父组件 -->
<template>
    <div class="home">
      <child>
        <h1 slot='left'>name属性为left</h1>  
        <h1 slot='right'>name属性为right</h1> 
      </child>
    </div>
</template>

3、作用域插槽

作用域插槽其实就是可以传递数据的插槽。子组件中的一些数据想在父组件中使用,必须通过规定的方法来传递。

含义:父组件对子组件的值进行加工处理。

作用域插槽不是父传子,而是子传父。通常是子组件将数据传给父组件,父组件接收到数据做处理。

使用步骤:

1. 子组件的模板template中,使用slot标签,在标签上通过一个自定义属性,将数据作为属性的值。

2. 在父组件的视图中,子组件对应的自定义标签中,添加一个标签,使用slot-scope属性接收所有子组件绑定的数据,因为这个属性在子组件的自定义标签上,所以父组件的方法中是可以操作到这个数据的

在官方文档中提出了一条规则,父级模板里的所有内容都是在父级作用域中编译的。子模板里的所有内容都是在子作用域中编译的。如果你在父组件直接使用子组件中的值,是会报错的。 

① 匿名插槽的作用域插槽

<!-- 子组件 -->
<template>
  <div class="hello">
    <div class='slotLeft'>
        <slot name='helloWorld' v-bind:users="user"></slot>
    </div> 
  </div>
</template>
<script>
    export default {
      data(){
        return{
          user:{
            name:'hello world',
            age:18
          }
        }  
      }
    }
</script>
<!-- 父组件 -->
<template>
    <div class="home">
      <child>
        <template  v-slot:helloWorld="slotProps">
           <h1>{{slotProps.users.name}}</h1> 
        </template>
      </child>
    </div>
</template>
  
<script>
import child from '@/components/child.vue'
export default {
    name: 'home',
    components: {
        child
    }
}
</script>

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

注意:

  • 默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确。

上面的写法是不是觉得有些麻烦?别着急,我们来看一看解构插槽 Prop。

② 解构插槽 Prop

作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:

function (slotProps) {
  // 插槽内容
}

这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop。

语法:v-slot="{ users }"

子组件:

<!-- 子组件 -->
<template>
    <div class="hello">  
       <div class='slotLeft'>
         <slot v-bind:users="user"></slot>
       </div>
    </div>
</template>
  
<script>
  export default {
    data(){
      return{
        user:{
          name:'hello world',
          age:18
        }
      }  
    }
  }
</script>
父组件:
<!-- 父组件 -->
<template>
  <div class="home">
    <child>
      <template  v-slot="{ users }">
         <h1>{{users.name}}</h1> 
      </template>
    </child>
  </div>
</template>

<script>
import child from '@/components/child.vue'
export default {
  name: 'home',
  components: {
    child
  }
}
</script>

重命名----更改users这个名字:

<template>
    <div class="home">
      <child>
        <template  v-slot="{ users:person }">
           <h1>{{person.name}}</h1> 
        </template>
      </child>
    </div>
</template>
  
<script>
  import child from '@/components/child.vue'
  export default {
    name: 'home',
    components: {
        child
    }
  }
</script>

 

posted @ 2022-02-22 17:50  小阿飞ZJF  阅读(101)  评论(0编辑  收藏  举报