vue.js 如何从一个组件发射到另一个组件?父母和孩子的事让我很困惑

qoefvg9y  于 12个月前  发布在  Vue.js
关注(0)|答案(3)|浏览(69)

我试图制作一个计算器来练习Vuejs,当我点击按钮时,我可以看到一个emit正在浏览器的vue标签中广播,但侦听器没有捕获任何东西。
这里是ButtionIO.vue

<template>
    <button @click="$emit('trigger-emit', value)" class="btn btn-secondary m-2" type="button">{{ value }}</button>
</template>

<script>
export default {
    name: 'ButtonIO',
    props: ['value'],  
}

</script>

字符串
下面是DisplayInput.vue组件,我想在其中监听emit

<template>
<input type="text" class="form-control" @trigger-emit='handleEmit'>
</template>

<script>
export default {
    name: 'DisplayInput',
    data: function() {
        return {

        };
    },
    methods: {
        handleEmit()
        {
            console.log('test');
        }
    }

}
</script>


在App.vue中,我就像这样

<template>
  <div class="container mt-5">
    <div class="col-2">
        <div class="d-flex justify-content-center">
            <DisplayInput />
        </div>
        
        <div class="d-flex justify-content-center">
            <ButtonIO value="1"/>
            <ButtonIO value="2" />
            <ButtonIO value="3" />
        </div>

        <div class="d-flex justify-content-center">
            <ButtonIO value="4" />
            <ButtonIO value="5" />
            <ButtonIO value="6" />
        </div>

        <div class="d-flex justify-content-center">
            <ButtonIO value="7" />
            <ButtonIO value="8" />
            <ButtonIO value="9" />
        </div>

        <div class="d-flex justify-content-center">
          <ButtonIO value="+" />
          <ButtonIO value="-"/>
          <ButtonIO value="*" />
          <ButtonIO value="/" />
        </div>
        <div class="d-flex justify-content-center">
          <ButtonIO value="=" />
        </div>
    </div>
  </div>
</template>

<script>
  import ButtonIO from './components/ButtonIO.vue';
  import DisplayInput from './components/DisplayInput.vue';

  
  
  export default {
      name: 'App',
      components: {
          ButtonIO,
          DisplayInput,
      }, 
  }

</script>

5vf7fwbs

5vf7fwbs1#

正如在其中一条评论中提到的,“EventBus”模式是我最喜欢的。
基本上,您创建了一个单独的Vue示例,您的应用程序将使用该示例订阅事件。
在您的文件目录中

// eventBus.js
const eventBus = new Vue()
export default eventBus

字符串
在您想要对事件做出React的任何组件/页面中(订阅):

// ChildComponent.vue
import eventBus from './eventBus'

export default {
  mounted() {
    // adding eventBus listener
    eventBus.$on('custom-event', () => {
      console.log('Custom event triggered!')
    })
  },
  beforeDestroy() {
    // removing eventBus listener
    eventBus.$off('custom-event')
  }
}


在触发事件的组件中

// ParentComponent.vue
import eventBus from './eventBus'

export default {
  methods: {
    sendCustomEvent() {
      // sending the event
      eventBus.$emit('custom-event')
    }
  }
}


甚至可以传递期望在事件处理程序中接收的参数

eventBus.$emit('update-theme-color', '#000')
eventBus.$on('update-theme-color', (color) => {
  console.log(`Updating theme color ${color}`)
})

的字符串

gwbalxhn

gwbalxhn2#

Vue3 SFC Playground
事件被发送到父组件,因此您不能像尝试的那样直接将其发送到同级组件。
对于您的应用程序,您可以在DisplayInput中定义一个公开的方法,并从App组件调用它,该组件反过来监听按钮单击。由于应用程序知道点击了哪个按钮,因此您不需要单独的按钮组件:
App.vue:

<script setup>
  
  import DisplayInput from './DisplayInput.vue';
  import {ref} from 'vue';

  const rows = '1 2 3 | 4 5 6 | 7 8 9 | + - * / | ='.split(' | ').map(row=>row.split(' '));
  
  const input = ref();
  
</script>

<template>
  <div class="container mt-5">
    <div class="col-2">
        <div class="d-flex justify-content-center">
            <DisplayInput ref="input"/>
        </div>
          <div v-for="row in rows" class="d-flex justify-content-center">
            <button v-for="button in row" @click="input.handleInput(button)" 
             class="btn btn-secondary m-2" type="button">{{ button }}</button>
          </div>  
    </div>
  </div>
</template>

字符串
DisplayInput.vue:

<script setup>
defineExpose({handleInput});
import {ref} from 'vue';

const value=ref('');

function handleInput(_value){
    value.value += _value;
}
</script>
<template>

<input type="text" :value="value" class="form-control" @trigger-emit='handleEmit'>

</template>

llew8vvj

llew8vvj3#

vue很好地记录了发射事件的概念:https://vuejs.org/guide/components/events.html#declaring-emitted-events
使用emits,您可以从子组件触发父组件内的函数并发送数据。你不能神奇地从任何地方监听任何事件,事件是由声明它的组件传播的。
所以在你的代码中,你不能让你的input标记监听一个事件,输入不能发出。只有在其上声明了emit的组件才会在定义的操作上发出事件。因此,在您的示例中,只要有人单击ButtonIO组件中的按钮,该组件就会触发父组件的emit。
在本例中,您可以在App.vue文件中监听按钮单击,如下所示:

<template>
  <div class="container mt-5">
    <div class="col-2">
        <div class="d-flex justify-content-center">
            <DisplayInput />
        </div>
        
        <div class="d-flex justify-content-center">
            <ButtonIO value="1" @trigger-emit='handleEmit'/>
            <ButtonIO value="2" @trigger-emit='handleEmit'/>
            <ButtonIO value="3" @trigger-emit='handleEmit'/>
        </div>
    </div>
  </div>
</template>

<script>
  import ButtonIO from './components/ButtonIO.vue';
  import DisplayInput from './components/DisplayInput.vue';

  
  
  export default {
      name: 'App',
      components: {
          ButtonIO,
          DisplayInput,
      },
      methods: {
          handleEmit(data) {
            console.log("Clicked", data); // prints "Clicked 3" if you clicked on button 3, because that value is emitted and taken by the function
          }
      }
  }

</script>

字符串
希望能帮上忙!

相关问题