【问题标题】:Vue.js - using functions in component methodsVue.js - 在组件方法中使用函数
【发布时间】:2020-01-02 19:11:13
【问题描述】:

我有一个 vue2 组件,其中一些方法很长,有很多回调,我想更好地结构化它。我尝试按照callbackhell.com 遵循指导方针,但在 vue 方法中事情看起来并不那么容易。

以下是我目前所处位置的示例,它有效,但我对以下内容感到困惑:

  1. Function hoisting 似乎在这里不起作用,我需要先定义我的函数,然后再运行它们,否则会触发错误。为什么会这样,我是不是漏掉了什么?

  2. 当我像这样定义内部函数时,我丢失了其中绑定到 Vue 组件的“this”。我在函数定义之后通过.bind(this) 修复它,它可以工作但看起来相当晦涩。有没有更好的方法在方法中定义实用函数,同时仍然保留“this”的上下文?

  3. 这通常是在 Vue 中将函数添加到方法中的一种好方法吗?我知道我可以直接在 methods: {} 对象中使它们成为同级方法,这解决了我的大部分问题,但由于它们仅与 saveFavourites() 方法相关而不与组件中的任何其他内容相关,因此将它们包装在我看来更干净?

非常感谢

methods: {
    saveFavourites() {
        var promptName = function() {
            return this.$swal({
                text: 'Enter name'),
                content: 'input',
                button: {
                    text: 'Save'),
                    closeModal: true,
                },
            })
        }.bind(this);

        var storePlan = function(name) {
            if(!name || (name = name.trim()) === '' ) return;
            axios.post('/api/user-store-daily-favourites', { meals: this.mealIds, name: name })
                .then(response => {
                    if(response.data.status === 'success') {
                        this.$emit('dailyFavouritesUpdated');
                    }
                });
        }.bind(this);

        // running it - if I move this above functions definitions, I get error
        promptName()
            .then( (name) => storePlan(name) );
    },

【问题讨论】:

    标签: vue.js vue-component hoisting


    【解决方案1】:

    对于问题 1,提升仅适用于函数声明,不适用于函数表达式。比较:

    // Expression
    var promptName = function() {
    

    到:

    // Declaration
    function promptName() {
    

    更多阅读请看:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function

    对于问题 2,使用 bind 很好,但您可能会发现使用箭头函数更容易,它保留了周围的 this 值。

    var promptName = () => {
      return this.$swal({
        ...
      })
    }
    

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

    对于问题 3,这似乎是个人喜好问题,但通常我会将它们移至单独的 Vue methods。您需要考虑通常的权衡。也许你觉得间接的代价太高了,你宁愿把所有的代码都放在一个地方。没关系。

    在这种特定情况下,我建议您查看async/await,而不是使用所有这些额外的功能。但是,请注意,在尝试使用 async/await 之前,请确保您充分理解了 Promise,因为 async/await 的大多数问题都来自于不了解用于实现它的底层机制。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

    async/await 版本看起来像这样:

    async saveFavourites() {
      const name = await this.$swal({
        text: 'Enter name',
        content: 'input',
        button: {
          text: 'Save',
          closeModal: true,
        },
      });
    
      if(!name || (name = name.trim()) === '' ) return;
    
      const response = await axios.post('/api/user-store-daily-favourites', {
        meals: this.mealIds,
        name: name
      });
    
      if(response.data.status === 'success') {
        this.$emit('dailyFavouritesUpdated');
      }
    }
    

    【讨论】:

    • 非常感谢!只是想知道 - 如果我使用函数声明来允许按 1 进行托管,我还能使用箭头语法还是使用 .bind?
    • @Ziki 如果您使用函数声明,那么它不能是箭头函数。使用bind 也很棘手,因为您不能只在声明的末尾标记它:将bind 放在末尾会立即使其成为表达式,而不是声明。使用call 调用函数可以设置this 值,但在周围范围内使用const that = this 技巧并在函数内部使用that 会更简单。为了清楚起见,我并不是在提倡使用函数声明,只是解释为什么提升不适用于您的原始代码。
    猜你喜欢
    • 2017-09-21
    • 2021-02-25
    • 2021-01-24
    • 1970-01-01
    • 2020-02-27
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    相关资源
    最近更新 更多