繁体   English   中英

VUE 2+访问子方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM