Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
haizhilin2013 opened this issue Jun 22, 2019 · 7 comments
Open

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

haizhilin2013 opened this issue Jun 22, 2019 · 7 comments
Labels
vue vue

Comments

@haizhilin2013
Copy link
Collaborator

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

@haizhilin2013 haizhilin2013 added the vue vue label Jun 22, 2019
@xixileng
Copy link

xixileng commented Jul 1, 2019

创建高级组件

@maozhuo123
Copy link

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

@webread
Copy link

webread commented Jul 17, 2019

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

@sky124380729
Copy link

sky124380729 commented Oct 16, 2019

一般我对一些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>

@qq-radio
Copy link

祖孙传值,这也太难了

@violet-mio
Copy link

对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
Copy link

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
vue vue
Projects
None yet
Development

No branches or pull requests

8 participants