Vue插槽

1,267 阅读2分钟

Vue插槽

  1. 作用:让父组件可以向子组件指定位置插入内容(可以是HTML结构,也可以是其他组件),这也是一种组件间通信的方式

  2. 分类:默认插槽、具名插槽、作用域插槽

  3. 理解:父组件中把子组件写成双标签形式,在双标签里面写上内容,在子组件定义插槽<slot></slot>后就会将该内容插入到子组件的指定位置(<slot></slot>所在的位置),至于样式,写在父组件或子组件里都可

    • 样式写在父组件中:解析后的结构带着样式插入插槽
    • 样式写在子组件中:解析后只把结构插入插槽,样式在子组件中控制
  4. 使用方式:

    1. 默认插槽:

    父组件中:
            <Child> <!-- Child为子组件标签 -->
               <div>html结构{{父组件中的数据}}</div>
            </Child>
    子组件中:
            <template>
                <div>
                   <!-- 定义插槽  父组件不传递结构时<slot></slot>中显示默认的内容-->
                   <slot>插槽默认内容...</slot> 
                </div>
            </template>
    

    2. 具名插槽:(父组件数据给子组件)

    父组件中:
            <Child>
            <!-- 写法1:slot='插槽名'  不推荐使用,好像2.6之后的版本被废弃了-->
                <template slot-scope="center"> <!-- 如果写多个center也不会覆盖,都会被写到插槽里 -->
                  <div>html结构1{{父组件的数据直接使用}}</div>
                </template>
    
          <!-- 写法2: v-slot:插槽名  推荐使用-->
                <template v-slot:footer> <!-- v-slot这种写法只能写在template里,是新的api -->
                   <div>html结构2{{父组件的数据直接使用}}</div>
                </template>
    
          <!--v-slot简写: #插槽名     
          template中的结构会放到子组件中<slot>的name属性为main的位置-->
                <template #main> <!-- #插槽名是 v-slot:插槽名的简单写法 -->
                   <div>html结构2{{父组件的数据直接使用}}</div>
                </template>
            </Child>
    子组件中:
            <template>
                <div>
                   <!-- 定义插槽 name属性区分不同的插槽-->
                   <slot name="center">插槽默认内容...</slot>
                   <slot name="footer">插槽默认内容...</slot>
                   <slot name="main">插槽默认内容...</slot>
                </div>
            </template>
    

    3. 作用域插槽:(子组件数据给父组件)

    1. 理解:数据在子组件自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Child组件中,但使用数据所遍历出来的结构由App组件决定)把子组件数据给父组件

    2. 语法:

      注:slot-scope是旧api(不推荐使用),v-slot是最新的

      父组件中:
      <!-- 写法1: slot-scope='scope(这是随便取的名字)'  不推荐使用-->
      		<Child>
      			<template slot-scope="scope"> <!-- 或写成slot-scope="{games}解构形式也可以" -->
      				<!-- 生成的是ul列表 -->
      				<ul>
      					<li v-for="g in scope.games" :key="g">{{g}}</li>
      				</ul>
      			</template>
      		</Child>
      <!-- 写法2: v-slot=scope  推荐使用-->
      		<Child>
      			<template v-slot="scope">  <!-- 或写成v-slot="{games}"解构形式也可以 -->
      				
      				<h4 v-for="g in scope.games" :key="g">{{g}}</h4>
      			</template>
      		</Child>
      子组件中:
              <template>
                  <div>
                      <slot :games="games"></slot> <!--可以传多个值,用的时候scope.xxx就行-->
                  </div>
              </template>
      		
              <script>
                  export default {
                      name:'Child',
                      //数据在子组件自身
                      data() {
                          return {
                              games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                          }
                      },
                  }
              </script>
      

4.具名插槽和作用域插槽一起使用:

        <!-- 子组件的插槽中: obj是要传递给父组件的值 name是该插槽的名字--> 
        <slot :obj="{a,b}" name="child">默认要显示的内容</slot>


        <!-- 父组件child组件标签的template标签上: -->
      <child>
        <template v-slot:child="scope">  <!-- 这里如果直接写成v-slot='scope'则不会生效 页面不会展示数据! 
            <h2>{{ scope.obj }}</h2>
        </template>
    </child>
     ```