Vue2:传递函数作为prop触发警告已经设置了prop

时间:2018-06-14 08:51:12

标签: javascript vue.js vuejs2

我是Vue的新手,我到目前为止还在享受单一文件组件。

在做我真正想做的事情之前,我想我会尝试一些小事来看看我是否掌握了这个概念。

所以我开始创建一个用于打开XMLHttpRequest的组件,带有一个进度条。

enter image description here

<template >
  <div  v-if="showQ">
    <div class="text-muted">
      <span>{{humanReadableLead}}</span>
      <span :class="'text-'+color">{{humanReadableMessage}}</span>
      <span>{{humanReadableEnd}}</span>
    </div>
    <div class="progress">
      <div
        class="progress-bar progress-bar-striped progress-bar-animated"
        :class="'bg-'+color"
        role="progressbar"
        :style="{width: String(percent)+'%'}"
        :aria-valuenow="percent"
        aria-valuemin="0"
        aria-valuemax="100"
      ></div>
    </div>

    <div class="text-right text-muted form-text text-small">
      <span class="float-left">{{xhrMessage}}</span>
      <span
        class="badge"
        :class="'badge-'+color"
        data-toggle="tooltip"
        data-placement="right"
        :title="readyStateTooltip"
        >
          {{xhr.readyState}}
        </span>
      <span
        class="badge"
        :class="'badge-'+color"
        data-toggle="tooltip"
        data-placement="right"
        :title="statusTooltip"
      >
        {{xhr.status}}
      </span>
      <span
        v-if="transferComplete"
        @click="goodbye"
        class="badge badge-secondary"
        data-toggle="tooltip"
        data-placement="right"
        title="Dismiss progress bar"
      >
        &times;
      </span>
    </div>
  </div>

</template>

<script>

import {httpStatusCodes, httpReadyStateCodes} from './http-responses';

export default {
  props: {
    method: {
      type: String,
      default: "GET",
      validator: function(value) {
        return ["GET", "POST", "PUT", "DELETE"].includes(value)
      }
    },
    url: {
      type: String,
      required: true
    },
    async: {
      type: Boolean,
      default: true
    },
    success: {
      type: Function,
      default: function() {
        console.log(this.xhr.response)
      }
    },
    readystatechange: {
      type: Function,
      default: function(event) {
      }
    },
    automaticCloseQ: {
      type: Boolean,
      default: false
    }
  },
  data: function() {
    return {
      xhr: new XMLHttpRequest(),
      httpStatusCodes:httpStatusCodes,
      httpReadyStateCodes:httpReadyStateCodes,
      color: "primary",
      percent: 0,
      humanReadableLead: "",
      humanReadableMessage: "",
      humanReadableEnd: "",
      xhrMessage: "",
      showQ: true,
      completeQ: false
    }
  },
  computed: {
    readyStateTooltip: function() {
      var rs = this.xhr.readyState,
      rsc = httpReadyStateCodes[rs]
      return `Ready state ${rs}: ${rsc}`
    },
    statusTooltip: function() {
      var s = this.xhr.status
      // s = s == 0 ? 218 : s
      var sc = httpStatusCodes[s]
      return `Status ${s}: ${sc}`
    },
    transferComplete: function() {
      return this.completeQ
    }
  },
  methods: {
    open: function() {
      this.xhr.open(this.method, this.url, this.async)
    },
    send: function() {
      this.xhr.send()
    },
    goodbye: function() {
      this.showQ = false
    }
  },

  created: function() {
    var that = this
    that.open()

    that.xhr.addEventListener("error", function(event) {
      that.color = "danger"
      that.xhrMessage = "An error has occured."
    })

    this.xhr.addEventListener("progress", function(event) {
      if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total * 100;
        that.percent = percentComplete
      } else {
        that.percent = 100
        that.xhrMessage = "Unable to compute progress information since the total size is unknown."
      }
    })

    that.xhr.addEventListener("abort", function(event) {
      that.color = "danger"
      that.xhrMessage = "The transfer has been canceled by the user."
    });

    that.xhr.addEventListener("load", function(event) {
      that.color = "success"
      that.xhrMessage = "Transfer complete."
      that.completeQ = true
      if (that.automaticCloseQ) { that.showQ = false }
      that.success()
    })

    that.xhr.addEventListener("readystatechange", function(event) {
      that.readystatechange(event)
    })

    that.send()
  }
}
</script>

<style scoped>
</style>

并在 index.html

<div id="request" style="width:50%;" >
  <http-request :url="'./<some-file>'"/>
</div>

使用JS

var progress = new Vue({
  el: '#request',
  components: { httpRequest }
})

这很好用......

然而,在我的生活中有一些小错误,我无法弄清楚:

  • 我想定义一个函数onSuccess,我将其传递给道具success,但这会引发Vue的错误
  • statusTooltip的计算属性未更新
  • 尝试将automaticCloseQ设置为默认值,无论我如何尝试绑定

e.g。

var onSuccess = function() {console.log('here')}

<http-request :url="'./<some-file>'" :success="onSuccess" :automaticCloseQ="true"/>

我错过了什么?

1 个答案:

答案 0 :(得分:0)

希望这会有所帮助。

我想定义一个函数onSuccess,我传递给prop成功,但这会引发Vue的错误

您在Vue之外定义onSuccess。它应该在Vue的methods

中定义

statusTooltip的计算属性未更新

在Javascript中,对象通过引用传递。 xhr始终引用同一个对象。这就是计算值不会更新的原因。见https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats。解决问题的一种方法是使用另一个名为xhrStatus的被动数据,并在xhr的事件监听器中手动更新此状态。

尝试将automaticCloseQ设置为默认值,无论我如何尝试绑定

(我不知道这意味着什么......)