[英]VUE 2+ accessing child methods
我遇到一種情況,在VUE中,我需要從子級以及父級中訪問子級功能。 我有一個有效的示例,但是必須有一種更好的方法來從父級訪問子級功能。
該示例包含幾個事件偵聽器,在單擊或按鍵時應將其展開。 我想將父級的child.do_something
方法與全局EventListener
。
有沒有比這更好的方法來使用孩子了?
// CHILD is a component that needs access to its own click method var child = { props: ['item'], data: function() { return { isActive: false } }, template: ` <div class="key" :class="{playing: isActive}" v-on:click='do_something'> <kbd class="noselect">{{ item.kbd }}</kbd> </div> `, methods: { do_something: function(event) { this.isActive = !this.isActive // DO OTHER STUFF too }, }, } //PARENT also need to access do_something for the right object when a key is pressed var parent = new Vue({ el: '#parent', data: { keysList: [{ keyCode: "65", kbd: "A" }, { keyCode: "83", kbd: "S" }, ], }, components: { 'child': child, }, methods: { keystroke: function(keyCode) { //FIND THE CHILD AND EXECUTE...THIS IS THE TERRIBLE PART const child = this.$children.find(child => { return child.$vnode.data.key === keyCode.toString() }); child.do_something() } }, created: function() { window.addEventListener('keydown', (e) => this.keystroke(e.keyCode)); } })
.keys { display: flex; flex: 1; min-height: 100vh; align-items: center; justify-content: center; } .key { margin: 1rem; transition: all .07s ease; color: white; background: rgba(0, 0, 0, 0.77); } .playing { transform: scale(1.1); border-color: #ffc600; box-shadow: 0 0 1rem #ffc600; } kbd { display: block; font-size: 4rem; }
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div class="keys" id='parent'> <child v-for="(item,index) in keysList" :item="item" :key="item.keyCode"></child> </div>
您可以使用ref,然后通過索引引用所需的特定孩子。 這樣可以避免使用內部值。
<child v-for="(item,index) in keysList" :item="item" :key="item.keyCode" ref="children"></child>
在keystroke
:
const index = this.keysList.findIndex(k => k.keyCode == evt.keyCode)
this.$refs.children[index].do_something()
在這里,您的代碼已修改。
// CHILD is a component that needs access to its own click method var child = { props: ['item'], data: function() { return { isActive: false } }, template: ` <div class="key" :class="{playing: isActive}" v-on:click='do_something'> <kbd class="noselect">{{ item.kbd }}</kbd> </div> `, methods: { do_something: function(event) { this.isActive = !this.isActive // DO OTHER STUFF too }, }, } //PARENT also need to access do_something for the right object when a key is pressed var parent = new Vue({ el: '#parent', data: { keysList: [{ keyCode: "65", kbd: "A" }, { keyCode: "83", kbd: "S" }, ], }, components: { 'child': child, }, methods: { keystroke: function(evt) { const index = this.keysList.findIndex(k => k.keyCode == evt.keyCode) this.$refs.children[index].do_something() } }, created: function() { window.addEventListener('keydown', this.keystroke); } })
.keys { display: flex; flex: 1; min-height: 100vh; align-items: center; justify-content: center; } .key { margin: 1rem; transition: all .07s ease; color: white; background: rgba(0, 0, 0, 0.77); } .playing { transform: scale(1.1); border-color: #ffc600; box-shadow: 0 0 1rem #ffc600; } kbd { display: block; font-size: 4rem; }
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div class="keys" id='parent'> <child v-for="(item,index) in keysList" :item="item" :key="item.keyCode" ref="children"></child> </div>
或者,為每個孩子使用不同的引用的更直接的方法。
<child v-for="(item,index) in keysList" :item="item" :key="item.keyCode" :ref="item.keyCode"></child>
在keystroke
:
this.$refs[evt.keyCode][0].do_something()
這里不幸的是,因為ref被設置為循環的一部分,所以每個ref都是一個元素的數組。 如果我想辦法解決該問題,請對其進行編輯。
這就是工作。
// CHILD is a component that needs access to its own click method var child = { props: ['item'], data: function() { return { isActive: false } }, template: ` <div class="key" :class="{playing: isActive}" v-on:click='do_something'> <kbd class="noselect">{{ item.kbd }}</kbd> </div> `, methods: { do_something: function(event) { this.isActive = !this.isActive // DO OTHER STUFF too }, }, } //PARENT also need to access do_something for the right object when a key is pressed var parent = new Vue({ el: '#parent', data: { keysList: [{ keyCode: "65", kbd: "A" }, { keyCode: "83", kbd: "S" }, ], }, components: { 'child': child, }, methods: { keystroke: function(evt) { this.$refs[evt.keyCode][0].do_something() } }, created: function() { window.addEventListener('keydown', this.keystroke); }, })
.keys { display: flex; flex: 1; min-height: 100vh; align-items: center; justify-content: center; } .key { margin: 1rem; transition: all .07s ease; color: white; background: rgba(0, 0, 0, 0.77); } .playing { transform: scale(1.1); border-color: #ffc600; box-shadow: 0 0 1rem #ffc600; } kbd { display: block; font-size: 4rem; }
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div class="keys" id='parent'> <child v-for="(item,index) in keysList" :item="item" :key="item.keyCode" :ref="item.keyCode"></child> </div>
您可以通過向父數據keys中的項添加另一個active屬性來實現此目的,並為匹配的擊鍵更新active屬性。 將物品作為道具傳遞給孩子時,可以使用道具中的item.active。 您不需要孩子中的isActive數據。
家長:
var parent = new Vue({
el: '#parent',
data: {
keysList: [{
keyCode: "65",
kbd: "A",
active: false
},
{
keyCode: "83",
kbd: "S",
active: false
}
],
},
components: {
'child': child,
},
methods: {
keystroke: function(keyCode) {
this.keysList.forEach(key => {key.active = key.keyCode === keyCode.toString()});
}
},
created: function() {
window.addEventListener('keydown', (e) => this.keystroke(e.keyCode));
}
})
<div class="keys" id='parent'>
<child v-for="(item,index) in keysList" :item="item" :key="item.keyCode" :isActive="item.active"></child>
</div>
兒童:
var child = {
props: ['item'],
template: `
<div class="key" :class="{playing: item.active}" v-on:click='do_something'>
<kbd class="noselect">{{ item.kbd }}</kbd>
</div>
`,
methods: {
do_something: function(event) {
// DO OTHER STUFF too
},
},
}
這樣,您就可以在一個地方管理狀態,而無需從父母那里訪問孩子
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.