【问题标题】:Vue custom event handling with watchers带有观察者的 Vue 自定义事件处理
【发布时间】:2019-10-27 14:39:01
【问题描述】:

我想在 ajax 调用运行时显示一些代理文本。此外,当通话完成时,我想隐藏文本。所以我编写了两个组件,一个是 AppBody,它将在其插槽中保存一个用于模拟 ajax 调用的按钮。另一个是 DownloadBtn,其中 execute 方法将执行 ajax 调用。在 ajax 调用之前和之后,我更改了一个名为 loaderStatus 的变量的值并观察该变量的变化。每当变量发生更改时,它都会发出名为下载的自定义事件。在从子组件 DownloadBtn 接收到事件后,AppBody 组件在 vue 实例的 doSomething 方法中确认了此事件,并且另一个名为 loadSpinner 的变量被更改。我将此 loadSpinner 变量绑定到 AppBody 道具,因此每当此 loadSpinner 发生更改时,文本值应相应地显示/隐藏。但问题是文本出现但没有按预期隐藏。但是,如果我删除道具,那么控制台日志会返回预期的输出,但我没有文本,因为文本取决于该道具值。任何帮助将不胜感激。小提琴链接:jsfiddle

我有一个这样的js代码sn-p:

Vue.component("app-body", {
    template : 
  `
   <div> 
      <div v-if="loader">
         <p>Please Wait Ajax Call is Running</p>
      </div>
      <div v-else>
         <slot></slot>
      </div>
   </div>
  `,
  data () {
    return {}
  },
  props : {
    loader : Boolean,
  }
});

Vue.component("download-btn", {
    template : `
    <div >
        <button type="button"  @click="execute"> Download </button>
    </div>
  `,
  data () {
    return {
        loaderStatus : false,
    }
  },
  props : {

  },
  methods : {
    execute () {
        //ajax call
        this.loaderStatus = true;
        console.log("Starting ajax call");

        fetch("https://jsonplaceholder.typicode.com/users")
        .then(res=>{
            console.log(res);
            this.loaderStatus = false;
            console.log("ajax call completed")
            /* this.$emit("download", true); */
        }).catch(err=>console.log(err));
    }
  },
  watch : {
    loaderStatus() {
        console.log("in watch::loaderStatus=>"+ this.loaderStatus);
        this.$emit("download", this.loaderStatus);
    }
  } 
});


new Vue({
  el: "#app",
  data: {
   loadSpinner : false
  },
  methods: {
    doSomething(newLoadSpinnerValue) {
        console.log("in doSomething::newLoadSpinnerValue=>" + newLoadSpinnerValue);
        this.loadSpinner = newLoadSpinnerValue;
    }
  },

})

和html部分是这样的:

<div id="app">


 <app-body :loader=loadSpinner>
     <download-btn @download="doSomething"></download-btn>
   </app-body>
</div>

【问题讨论】:

  • 对于一个简单的问题似乎是一个相当复杂的解决方案,你真的只需要在 2 个组件之间进行通信,不需要你的app 和使用插槽,只需从按钮传递到app-body loader 道具应该可以解决您的问题。
  • @Michael 我应该将按钮传递给 appbody 一个道具吗?或发出事件?按钮选项卡在这里是 AppBody 的子组件。你能分享一个小提琴吗?
  • 我会制作一个加载器组件,然后将其作为来自父级的道具loading 提供,这将是进行 api 调用的组件。看这里的例子:stackoverflow.com/questions/52682506/vuejs-vue-spinner 那里的微调器是自定义的,但你可以制作自己的加载器(然后你可以在应用程序或其他应用程序的任何地方重复使用)

标签: vue.js vuejs2 vue-component


【解决方案1】:

问题是您的slot 仅在加载未进行时才挂载。当加载开始时,slot 被删除,这意味着加载器组件将被卸载,并且其中发生的任何事情都不会运行任何观察者或事件。该值永远不会被报告回来,并且插槽永远不会重新激活。

如果您想让下载发生在按钮内部,您需要以不同的方式处理下载按钮的隐藏。

请参阅fiddle,其中子项在加载时未移除,属性正常工作。

【讨论】:

    猜你喜欢
    • 2014-12-12
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    相关资源
    最近更新 更多