javascript - 获取父组件事件的 vue 子组件目标

标签 javascript vue.js vuejs2 vue-component dom-events

我正在试验 Vue.js,我有一个带有一些子组件的父组件。我希望能够做的是跟踪“单击并拖动”的组件。

This is an example to understand my problem.

到目前为止,我所拥有的是用户发起一个 mousedown父组件上的事件有条件地激活 mouseover子组件上的监听器,我跟踪哪些子组件被移过。当用户释放鼠标按钮时 mouseover听众被删除。

我已经能够使用这个 method to conditionally add event listeners 做到这一点问题是当初始 mousedown事件触发,下面的子组件不会触发 mouseover事件,因此它不会被跟踪,后续 mouseover子组件上的 s 按预期进行跟踪。我还希望能够在开始“单击和拖动”时跟踪鼠标悬停的子组件。

为了解决这个问题,我得到了 event.target.__vue__mousedown事件访问子组件并显式调用跟踪方法。 (示例中App.vue的第25行)

我的问题是:是否有更适合 Vue.js 的方法来触发初始 mousedown 下的子组件的跟踪方法?除了使用 event.target.__vue__ 发生在父级上?或者通常是否有更好的方法来跟踪哪些子组件被“单击并拖动”?

最佳答案

如果你的父组件和子组件存在强关系(比如子组件必须放在父组件里面),可能你想尝试Vue provide&inject :

  1. 父组件提供一个方法让子组件注册他们的轨迹,然后使用provide 传递它(下面的demo通过this关键字传递实例)给 children 。

  2. 每个子组件只需调用该方法即可将其轨道上传到父组件。

但是对于提供/注入(inject),请注意这一点:

Note: the provide and inject bindings are NOT reactive. This is intentional. However, if you pass down an observed object, properties on that object do remain reactive.

下面是一个简单的演示:

Vue.config.productionTip = false

Vue.component('so-parent', {
  provide() {
    return {
      _tracker: this
    }
  },
  template: `
    <div @mousedown="toggleTrack(true)" @mouseup="toggleTrack(false)"><h3>children count: {{children.length}} - tracking: {{trackState}}</h3><h3>{{tracks}}</h3><slot></slot></div>
  `,
  data() {
    return {
      children: [],
      tracks: [],
      trackState: false
    }
  },
  methods: {
    _registerChild(child) {
      this.children.push(child)
    },
    _registerTracks(track) {
      if (this.trackState) this.tracks.push(track)
    },
    toggleTrack: function(state) {
      this.trackState = state
      if(!this.trackState) {
        this.tracks = []
      }
    }
  }
})

Vue.component('so-child', {
  inject: {
    _tracker: {
      default () {
        console.error('so-child must be child of so-parent')
      }
    }
  },
  data() {
    return {
      childState: false,
      childSeq: 0
    }
  },
  props: ['cid'],
  render(h) {
    return h('div', {
      class: 'child',
      on: {
        mouseover: () => this._tracker._registerTracks(this.cid)
      }
    }, [this.childSeq + ' Child Component ' + this.cid, this.$slots.default])
  },
  mounted() {
    this.childSeq = this._tracker.children.length
    this._tracker._registerChild(this)
  }
})

new Vue({
  el: '#app'
})
div.child {
  border: 1px solid;
  display: inline-block;
  padding: .5em 1em;
  margin: 0 0.5em 1em;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  &:hover {
    background: #b2bde3;
    cursor: pointer;
    color: white;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div id="app">
  <so-parent>
    <so-child cid="A"></so-child>
    <so-child cid="B"></so-child>
    <so-child cid="C"></so-child>
    <so-child cid="D"></so-child>
  </so-parent>
</div>

关于javascript - 获取父组件事件的 vue 子组件目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52360343/

相关文章:

javascript - Vue.js 在组件渲染后是否触发事件?

javascript - 如何在VUE js中的组件之间共享数据(创建列表时)

javascript - 使用 v-slot (scoped-slot) 时访问 this.$slots

javascript - 如果 View Blade laravel 中存在本地存储 javascript,我如何添加调用 vue 组件的条件?

javascript - 图像上的响应式文本区域( Bootstrap )

javascript - 如何仅在单击确定按钮后才使元素 UI 时间选择器设置值?

javascript - 带有 css 选择器的 addRule/insertRule

javascript - 移动 safari 上的粘性元素问题

javascript - 在 Vue 组件内使用 Rangey 恢复文本范围时出现错误消息 "Marker element has been removed"

javascript - Vue.js (v. 1.0.14) Vue Filter 与 Vue Validator