Vue перезагружает/отправляет запрос XHR при каждом нажатии клавиши в текстовом поле

#javascript #vue.js #vuejs2

Вопрос:

У меня есть текстовое поле для ввода описания, но каждый раз, когда я нажимаю клавишу, оно появляется, и страница перезагружается:

 XHR finished loading: PATCH "http://localhost:3000/ccenter/attachments/51".
 

Я думал, что способ решить эту проблему-установить какой-то тайм-аут для заданного значения, но я очень новичок в JS и не придумал лучшего способа сделать это и был бы признателен за любые указания в правильном направлении.

То, что я пробовал, приводит меня к ошибке:

 [Vue warn]: Error in render: "TypeError: Setter must be a function: 3"

attachmentAccepted: {
  get: function () {
    return !this.attachment.ignoreAttachment;
  },
  set: setTimeout(function (val) {
    return this.updateAttachment([this.attachment.id, { ignoreAttachment: !val }]);
  }, 3000)
},
 

ИЗМЕНИТЬ: Это удаляет перезагрузку, но затем выдает эту ошибку, которая затем останавливает регистрацию значения моего текстового ввода:

 set: function (val) { setTimeout(function(){ return this.updateAttachment([this.attachment.id, { strValue: val }]) }, 3000)  },


 Uncaught TypeError: Cannot read properties of undefined (reading 'id')
 

ПРАВКА 2: Решено.

 set: function (val) { let self = this; setTimeout(function(){ /* your code goes here. change all 'this.' to 'self.' */ }, 3000)  }
 

Комментарии:

1. Вы пробовали это: set: function (val) { setTimeout(function(){ /* your code goes here */ }, 3000) } ?

2. @FarisHan спасибо за ваш ответ, я попробовал (результаты прикреплены в моем редактировании).

3. Попробуй вот это: set: function (val) { let self = this; setTimeout(function(){ /* your code goes here. change all 'this.' to 'self.' */ }, 3000) }

4. Это сработало! Спасибо, я думаю, мне нужно выяснить, что вы там только что сделали.

5. Вместо этого вы можете использовать функцию стрелки setTimeout(() => {}, 3000) . Тогда this.updateAttachment должно сработать.

Ответ №1:

TL;DR

Заменять

 set: setTimeout(function (val) {
  return this.updateAttachment([this.attachment.id, { ignoreAttachment: !val }]);
}, 3000)
 

с

 set: function (val) {
  let self = this;
  setTimeout(function(){
    self.updateAttachment([self.attachment.id, { ignoreAttachment: !val }]); 
  }, 3000)
}
 

[Vue warn]: Error in render: "TypeError: Setter must be a function: 3" означает set: , что свойство attachmentAccepted должно быть функцией. Что-то вроде set: function(){} .

Uncaught TypeError: Cannot read properties of undefined (reading 'id') означает, что программа не может прочитать .id объект. В этом случае this.attachment объект не определен, поэтому вы не можете этого сделать this.attachment.id .

this.attachment не определено, потому что,

 set: function /* <<< SCOPE A function declaration */ (val) {
  
  /* "this" right here is a thing that referring to SCOPE A, and... */
  console.log(this)

  setTimeout(function() /* <<< SCOPE B function declaration */ {
    
    /* ... "this" right here is another thing that referring to SCOPE B. 
      And because of the same name, SCOPE A's "this" cannot be used anymore. */
    console.log(this)

    return this.updateAttachment([this.attachment.id, { strValue: val }])
  }, 3000)
}
 

Так что просто передайте ОБЛАСТЬ A this в ОБЛАСТЬ B. Одним из решений является использование var self = this; внутренней ОБЛАСТИ A. Теперь вы можете использовать ОБЛАСТЬ A this внутри ОБЛАСТИ B с self переменной.

 set: function /* SCOPE A */ (val) {
  let self = this;
  setTimeout(function /* SCOPE B */ (){
    self.updateAttachment([self.attachment.id, { ignoreAttachment: !val }]); 
  }, 3000)
}

// OR

set: function /* SCOPE A */ (val) {
  let SCOPE_A_THIS = this;
  setTimeout(function /* SCOPE B */ (){
    SCOPE_A_THIS.updateAttachment([SCOPE_A_THIS.attachment.id, { ignoreAttachment: !val }]); 
  }, 3000)
}


 

Бонус: Понимание «этого» в javascript с функциями стрелок