Skip to content

[vue] 说下$attrs和$listeners的使用场景 #461

Open
@haizhilin2013

Description

@haizhilin2013
Collaborator

[vue] 说下$attrs和$listeners的使用场景

Activity

xixileng

xixileng commented on Jul 1, 2019

@xixileng

创建高级组件

maozhuo123

maozhuo123 commented on Jul 3, 2019

@maozhuo123

组件传值,祖孙组件有跨度的传值。

webread

webread commented on Jul 17, 2019

@webread

组件传值的时候会用到 爷爷在父亲组件传递值,父亲组件会通过$attrs获取到不在父亲props里面的所有属性,父亲组件通过在孙子组件上绑定$attrs 和 $listeners 使孙组件获取爷爷传递的值并且可以调用在爷爷那里定义的方法

sky124380729

sky124380729 commented on Oct 16, 2019

@sky124380729

一般我对一些UI库进行二次封装用,比如element-ui,里面的组件不能满足自己的使用场景的时候,会二次封装,但是又想保留他自己的属性和方法,那么这个时候时候$attrs和$listners是个完美的解决方案。
简单的例子,对el-button二次封装

<template>
    <el-button v-on="$listeners" v-bind="$attrs" :loading="loading" @click="myClick">
        <slot></slot>
    </el-button>
</template>

<script>
export default {
    name: 'mButton',
    inheritAttrs: false,
    props: {
        debounce: {
            type: [Boolean, Number]
        }
    },
    data() {
        return {
            timer: 0,
            loading: false
        }
    },
    methods: {
        myClick() {
            if (!this.debounce) return
            this.loading = true
            clearTimeout(this.timer)
            this.timer = setTimeout(
                () => {
                    this.loading = false
                },
                typeof this.debounce === 'boolean' ? 500 : this.debounce
            )
        }
    }
}
</script>
radio-qq

radio-qq commented on Dec 31, 2020

@radio-qq

祖孙传值,这也太难了

violet-mio

violet-mio commented on Jun 24, 2021

@violet-mio

对element-ui一些组件进行简易二次封装

  • 穿梭框组件disabled禁用属性,实现禁用功能
<template>
  <el-form :disabled="disabled">
    <el-transfer
      v-bind="$attrs"
      v-on="$listeners"
    />
  </el-form>
</template>
<script>
export default {
  // 自定义穿梭框
  name: 'CustomTransfer',
  props: {
    // 禁用属性
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>
  • 图片预览组件
<template>
  <div>
    <el-image-viewer
      ref="elImageViewer"
      v-bind="$attrs"
      v-on="$listeners"
    />
  </div>
</template>

<script>
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'

export default {
  name: 'ImagePreview',
  components: { ElImageViewer },
  props: {
    // 点击mask是否隐藏大图
    maskhide: {
      type: Boolean,
      default: true
    }
  },
  mounted() {
    if (this.maskhide) {
      this.addHideToMask()
    }
  },
  methods: {
    addHideToMask() {
      this.$viewer = this.$refs.elImageViewer
      if (this.$viewer) {
        // 获取遮罩层元素
        const mask = this.$viewer.$el.querySelector('.el-image-viewer__mask')
        if (mask) {
          // 遮罩层增加点击事件,关闭预览
          mask.addEventListener('click', this.hide)
          // hook卸载事件,移除之前添加在mask元素的事件
          this.$once('hook:beforeMount', () => {
            mask && mask.removeEventListener('click', this.hide)
          })
        }
      }
    },
    hide() {
      this.$viewer && this.$viewer.hide()
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-image-viewer__btn.el-image-viewer__close {
  color: #fff;
}
</style>

sc950828

sc950828 commented on Sep 23, 2022

@sc950828

vue2中 $attrs是父组件传递的属性,但是没在子组件用props接收的。

vue2中$listeners是父组件监听的自定义事件,不包括原生事件。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @haizhilin2013@xixileng@violet-mio@sky124380729@maozhuo123

        Issue actions

          [vue] 说下$attrs和$listeners的使用场景 · Issue #461 · haizlin/fe-interview