$scopedSlots, $props, $attrs, $listeners

$scopedSlots

因为父页面使用了 header slot 所以会有打印
因为父页面没有使用了 footer slot 所以会有打印undefined

image.png

parent 页面

<template>
  <div>
    <h1>父页面</h1>
    <TestSlot>
      <template #header="{ data }">
        父页面定义的头部{{ data }}
      </template>
      <template #default="{ first }">
        {{ first }}
      </template>
    </TestSlot>
  </div>
</template>

<script>
import TestSlot from './components/TestSlot'
export default {
  components: {
    TestSlot
  }
}
</script>

child 页面

<template>
  <div style="border: 1px solid red;">
    <h1>子页面</h1>
    <div>
      <slot name="header" :data="user">我是头部</slot>
    </div>
    <div>
      <slot name="footer">我是底部</slot>
    </div>
    <slot :first="user"></slot>
  </div>
</template>

<script>
export default {
  data(){
    return {
      user:{
        name: 'userName',
        age: 18
      }
    }
  },
  mounted() {
    // 父页面 使用的 插槽 可以打印出
    console.log(this.$scopedSlots.header) // Fun
    console.log(this.$scopedSlots.content) // undefined
  }
}
</script>


$attrs, $props, $listeners

image.png

$attrs:将父页面的 v-bind绑定数据穿透传递至下级页面,如果你在某一个组件中注册了props 那么后续的组件就无法通过$attrs 来获取你已经注册过props的属性

$props:当此页面有注册的props 你可以在 template 中 使用 $props 来获取你注册的props属性

$listeners:使$emit 可以跨越更多的层级,也可以在中间的组件中进行监听,让每一个组件都可以监听到事件

注意
$attrs是可以在 template与 script 中使用的
$props 只可以在 template 中 使用

$attrs与$props可以使用在三级组件通信, 如果更多 还是推荐使用 provide / inject 来传递

下面是以上三种API的demo

page 页面

<template>
  <div class="page">
    page
    <Parent
      :age="18"
      @clickGreatGrandson="clickGreatGrandson"
    />
  </div>
</template>

<script>
import Parent from './components/Parent'

export default {
  components: { Parent },
  methods: {
    clickGreatGrandson(e) {
      console.log('page', e)
    }
  }
}
</script>

<style scoped>
  .page {
    margin: 50px auto;
    border: 1px solid red;
    width: 800px;
    height: 700px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
</style>

Parent 页面

<template>
  <div class="parent">
    Parent Components
    <span style="color: red;">$props: {{ $props }}</span>
    <span style="color: red;">$attrs: {{ $attrs }}</span>
    <Son
      v-bind="$attrs"
      v-on="$listeners"
      @clickGreatGrandson="clickGreatGrandson"
    />
  </div>
</template>

<script>
import Son from './Son'

export default {
  inheritAttrs: true,
  // props: [ 'age' ],
  components: { Son },
  mounted() {
    console.log('Parent', this.$attrs)
  },
  methods: {
    clickGreatGrandson(e) {
      console.log('Parent', e)
    }
  }
}
</script>

<style scoped>
  .parent {
    border: 1px solid red;
    margin: 10px;
    width: 600px;
    height: 500px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
</style>

Son 页面

<template>
  <div class="son">
    Son Components
    <span style="color: red;">$props: {{ $props }}</span>
    <span style="color: red;">$attrs: {{ $attrs }}</span>
    <GreatGrandson
      v-bind="$attrs"
      v-on="$listeners"
      @clickGreatGrandson="clickGreatGrandson"
    />
  </div>
</template>

<script>
import GreatGrandson from './GreatGrandson'

export default {
  components: { GreatGrandson },
  mounted() {
    console.log('Son', this.$attrs)
  },
  methods: {
    clickGreatGrandson(e) {
      console.log('Son', e)
    }
  }
}
</script>

<style scoped>
  .son {
    border: 1px solid red;
    width: 500px;
    height: 300px;
    margin: 10px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
</style>

GreatGrandson 页面

<template>
  <div class="great-grandson">
    GreatGrandson Components
    <span style="color: red;">$props: {{ $props }}</span>
    <span style="color: red;">$attrs: {{ $attrs }}</span>
    <el-button type="primary" @click="clickGreatGrandson">GreatGrandson</el-button>
  </div>
</template>

<script>
export default {
  mounted() {
    console.log('GreatGrandson', this.$attrs)
  },
  methods: {
    clickGreatGrandson() {
      this.$emit('clickGreatGrandson', 'hello i\'m clickGreatGrandson')
    }
  }
}
</script>

<style scoped>
  .great-grandson {
    border: 1px solid red;
    width: 400px;
    height: 200px;
    margin: 10px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
</style>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。