vueJS3 - 如何触发来自兄弟组件的事件的函数

Posted

技术标签:

【中文标题】vueJS3 - 如何触发来自兄弟组件的事件的函数【英文标题】:vueJS3 - How to trigger a function on event from sibling component 【发布时间】:2021-08-01 06:54:06 【问题描述】:

我想触发一个函数,只要按下同级组件中的按钮,GETs 来自组件中的 http 服务器的数据。

SignUpForm.vue有一个按钮触发customSubmit()

customSubmit()
  //POST to API
  const user = 
      method: "POST",
      headers:  "Content-Type": "application/json",
      body: JSON.stringify(newUser: this.newUser)
  ;

  fetch("http://localhost:3080/api/user", user)
      .then(response => response.json())
      .then(data => console.log(data));

  this.$emit('refresh', true)

  this.clearForm();

父组件如下所示:

<template>
  <div>
    <SignUpForm @refresh="triggerRefresh($event)" />
    <!-- <Exp /> -->
    <Datatable :myRefresh="myRefresh" />
  </div>
</template>

<script>
  import SignUpForm from "./components/SignUpForm.vue";
  import Datatable from "./components/Datatable.vue";
  import Exp from "./components/exp copy.vue";

  export default 
    name: "App",
    components:  Datatable, SignUpForm, Exp ,
    data() 
      return 
        myRefresh: false,
      ;
    ,
    methods: 
      triggerRefresh(bool) 
        this.myRefresh = bool;
        console.log(this.myRefresh);
      ,
    ,
  ;
</script>

现在我想要兄弟组件 Datatable.vue 尽快从服务器到fetch 数据,因为this.$emit('refresh', true)SignUpForm.vue 中被触发

这是来自Datatable.vue的脚本

export default 
  data() 
    return 
      //Liste aller User
      userData: null,

      //temporärer User für das Details-Feld
      printUser: [ name: "", email: "", number: "" ],

      //Property für den "read-Button"
      showDetails: false,

      //Property für den "Update-Button"
      readOnly: true,
    ;
  ,

  props: ["myRefresh"],

  methods: 
    pushFunction() 
      fetch("http://localhost:3080/api/users")
        .then((res) => res.json())
        .then((data) => (this.userData = data));
    ,

    readData(k) 
      this.printUser.length = 0;
      this.showDetails = true;
      this.printUser.push(this.userData[k]);
    ,

    editData(rowUser) 
      if (!rowUser.readOnly) 
        rowUser.readOnly = true;
        const user = 
          method: "PATCH",
          headers:  "Content-Type": "application/json" ,
          body: JSON.stringify( userData: this.userData ),
        ;

        fetch("http://localhost:3080/api/users/patch", user)
          .then((response) => response.json())
          .then((data) => console.log(data));
       else 
        rowUser.readOnly = false;
      
    ,

    deleteData(k) 
      fetch("http://localhost:3080/api/users/" + k,  method: "DELETE" ).catch(
        (err) => console.log(err)
      );

      this.pushFunction();
    ,

    //blaue Reihen
    toggleHighlight(rowUser) 
      if (rowUser.readOnly === false) 
        return;
      
      rowUser.isHighlight = !rowUser.isHighlight;
    ,

    scrollDown() 
      window.scrollTo(0, document.body.scrollHeight);
    ,
  ,
  mounted() 
    fetch("http://localhost:3080/api/users")
      .then((res) => res.json())
      .then((data) => (this.userData = data));
  ,
;

我真的希望有人可以帮助新手!

【问题讨论】:

您可以将事件推送到父级,然后更新父级中的模型值,然后将其绑定到另一个组件。您通过父级执行此类操作的次数越多,您的应用程序(并绑定在一起)就越复杂。因此,您通常会为这样的事情使用外部状态,您可以在其中推送值并在另一个组件中自动检索它(通过计算值)。在 Vue2 中,您通常会选择 Vuex,但在 Vue3 中引入了一种非常好的新方法:组合 API,它可以让您外包本地状态。 我会看看组合 API,谢谢!您是否也有针对我的代码的特定解决方案? 在 Datatable 中为 myRefresh 设置一个观察者,并且不要为该值传递布尔值,而是传递一个生成的值(例如 Math.random())。否则,您需要先发出 true,然后等待一个滴答声,然后将其重置为 false。如果值为真,您将需要检查 - 在观察者中。通过设置一个随机值,当值发生变化时,watch 处理程序就会被执行。如果要完全重新加载组件(不仅是重新获取数据),还可以使用组件的 :key="" 属性。一旦这个值改变,组件就会重新渲染。 你没有使用 VueJS3...利用setup... 【参考方案1】:

两个考虑,有可能吗?谨慎吗?

有可能吗?

是的,你可以通过几种不同的方式来实现它。

谨慎吗?

没有。

如果你走这条路,很可能架构是无效的。在理想的设置中,您的组件应该只负责管理视图。这意味着用户看到并收集他们的输入。 业务逻辑不应存在于组件中。因此,如果您有诸如 ajax 调用之类的东西并将它们放入您的组件中,那么您已经将逻辑耦合到了视图中。一个可能的问题是,如果由于某种原因重新添加了组件,则任何正在进行的 ajax 调用都可能以意想不到的方式中断。虽然可以处理这种情况,但恕我直言,更大的问题是,当您将业务逻辑与视图层耦合时,您正在创建一个越来越难以推理的应用程序;在兄弟组件之间发送事件时遇到的这个问题只是一个例子。

其他选项

虽然不是唯一的方法,但最常见的处理方法是通过Vuex 使用全局存储

您可以调用 Vuex 操作,而不是从您的组件初始化 Ajax 请求。

该动作通常会使用单个状态变量(即loadState=STATE.STARTED)或使用isLoading=true 设置加载状态,除了分配变量之外,vuex 会通过突变来完成,所以store.commit('setLoadState', STATE.LOADING)。这将更新所有组件的状态,这些组件直接或使用 getter 侦听存储中的更改。然后发出 ajax 请求,完成后再次更新存储,使用store.commit('setLoadState', STATE.ERROR) 或成功时使用store.commit('setLoadState', STATE.DONE)store.commit('setUsers', response)。那么你的组件只需要监听变化,$store.loadState == STATE.LOADING就可以显示一个spinner

只要后续调用的数据与特定于组件的数据相关(例如特定的用户 ID 或名称),您就可以处理来自组件的下一次调用。您可以让组件watch vuex 存储或数据以进行更改,而不是通过监视来自同级的事件来触发来自组件的第二个 API 请求。然后当$store.loadState 变为STATE.DONE 时,您可以为另一个API 调用触发另一个动作。我只会这样做,但如果有特定于 API 调用的数据的任何部分,否则如果调用在所有情况下都是正确的,您也可以将其作为同一操作的一部分调用

【讨论】:

以上是关于vueJS3 - 如何触发来自兄弟组件的事件的函数的主要内容,如果未能解决你的问题,请参考以下文章

uni-app组件之间的通讯--父子/兄弟组件之间传递数据

uni-app组件之间的通讯--父子/兄弟组件之间传递数据

Vuejs 3 从子组件向父组件发出事件

vue-兄弟组件传值

Vue 组件之间传参!

如何在 vue 上使用 eventBus 触发点击事件?