我正在试验Vue.js,并且我有一个父组件和一些子组件。我想要做的是跟踪“点击并拖动”到其上的组件。
This is an example to understand my problem.
到目前为止,我所拥有的是用户在父组件上发起一个mousedown
事件,该事件有条件地激活了子组件上的mouseover
侦听器,我在其中跟踪移动了哪些子组件。当用户释放鼠标按钮时,mouseover
侦听器将被删除。
我已经可以使用此method to conditionally add event listeners来执行此操作,问题是当初始mousedown
事件触发时,下面的子组件不会触发mouseover
事件,因此它不会为了得到跟踪,将按预期跟踪子组件上的后续mouseover
。我还希望能够跟踪鼠标在启动“单击并拖动”时所在的子组件。
要解决此问题,我获得了event.target.__vue__
事件的mousedown
来访问子组件并显式调用跟踪方法。 (示例中App.vue的第25行)
我的问题是:除了使用mousedown
之外,还有一种Vue.js合适的方式来触发对父组件上的初始event.target.__vue__
下的子组件的跟踪方法吗?还是通常有更好的方法来跟踪哪些子组件被“单击并拖动”了?
答案 0 :(得分:2)
如果您的父组件和子对象存在牢固的关系(例如子组件必须放置在父组件内部),那么您可能想尝试Vue provide&inject:
父组件提供了一种方法,允许子级注册其音轨,然后使用provide
将其传递给孩子(在演示中,通过this
关键字将实例传递给子级)。
每个子组件只需要调用该方法即可将其曲目上传到父组件。
但是要提供/注入,请注意以下事项:
注意:Provide和Inject绑定不是反应性的。这是 故意的。但是,如果您向下传递观察对象,则属性 在那个物体上确实保持反应性。
下面是一个简单的演示:
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>