[Ostrzeżenie Vue]: Właściwość lub metoda nie jest zdefiniowana w instancji, ale odwołuje się do niej podczas renderowania


106
var MainTable = Vue.extend({
  template: "<ul>" +
    "<li v-for='(set,index) in settings'>" +
    "{{index}}) " +
    "{{set.title}}" +
    "<button @click='changeSetting(index)'> Info </button>" +
    "</li>" +
    "</ul>",
  data: function() {
    return data;
  }
});

Vue.component("main-table", MainTable);

data.settingsSelected = {};
var app = new Vue({
  el: "#settings",
  data: data,
  methods: {
    changeSetting: function(index) {
      data.settingsSelected = data.settings[index];
    }
  }
});

W przypadku powyższego kodu poniższy błąd występuje po kliknięciu przycisku.

[Ostrzeżenie Vue]: Właściwość lub metoda „changeSetting” nie jest zdefiniowana w instancji, ale odwołuje się do niej podczas renderowania. Pamiętaj, aby zadeklarować reaktywne właściwości danych w opcji danych. (znaleziono w <MainTable>)


Twój komponent nie ma dostępu do metod zdefiniowanych w Twoim Vue. Musisz dodać metodę changeSettingdo MainTablekomponentu.
Bert

Odpowiedzi:


103

Problem

[Vue warn]: Property or method "changeSetting" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in <MainTable>)

Błąd występuje, ponieważ changeSettingw MainTablekomponencie występuje odwołanie do metody :

    "<button @click='changeSetting(index)'> Info </button>" +

Jednak changeSettingmetoda nie jest zdefiniowana w MainTablekomponencie. Jest definiowany w głównym komponencie tutaj:

var app = new Vue({
  el: "#settings",
  data: data,
  methods: {
    changeSetting: function(index) {
      data.settingsSelected = data.settings[index];
    }
  }
});

Należy pamiętać, że do właściwości i metod można się odwoływać tylko w zakresie, w którym zostały zdefiniowane.

Wszystko w szablonie nadrzędnym jest kompilowane w zakresie nadrzędnym; wszystko w szablonie podrzędnym jest kompilowane w zakresie podrzędnym.

Możesz przeczytać więcej o zakresie kompilacji komponentów w dokumentacji Vue .

Co mogę z tym zrobić?

Jak dotąd dużo się mówiło o definiowaniu rzeczy we właściwym zakresie, więc rozwiązaniem jest po prostu przeniesienie changeSettingdefinicji do MainTablekomponentu?

Wydaje się to takie proste, ale oto co polecam.

Prawdopodobnie chciałbyś, aby Twój MainTablekomponent był elementem głupim / prezentacyjnym. ( Tutaj jest coś do przeczytania, jeśli nie wiesz, co to jest, ale tl; dr mówi, że komponent jest po prostu odpowiedzialny za renderowanie czegoś - bez logiki). Za logikę odpowiada element smart / container - w przykładzie podanym w pytaniu głównym komponentem byłby komponent smart / container. Dzięki tej architekturze możesz używać metod komunikacji rodzic-dziecko Vue do interakcji komponentów. Przekazujesz dane do MainTablevia props i emitujesz akcje użytkownika z MainTabledo jego rodzica poprzez zdarzenia . Może to wyglądać mniej więcej tak:

Vue.component('main-table', {
  template: "<ul>" +
    "<li v-for='(set, index) in settings'>" +
    "{{index}}) " +
    "{{set.title}}" +
    "<button @click='changeSetting(index)'> Info </button>" +
    "</li>" +
    "</ul>",
  props: ['settings'],
  methods: {
    changeSetting(value) {
      this.$emit('change', value);
    },
  },
});


var app = new Vue({
  el: '#settings',
  template: '<main-table :settings="data.settings" @change="changeSetting"></main-table>',
  data: data,
  methods: {
    changeSetting(value) {
      // Handle changeSetting
    },
  },
}),

Powyższe informacje powinny wystarczyć, aby zorientować się, co należy zrobić i zacząć rozwiązywać problem.


3
Czy jest to obecnie najbardziej preferowane podejście? W Vue sprawy wciąż się rozwijają, więc pomyślałem, że zapytam
Aseem

Nie jestem ekspertem w Vue, ale stackoverflow.com/questions/43292810/ ... sugeruje, że możesz wywołać funkcję aplikacji ze swojego komponentu za pośrednictwem $root. Np. this.$root.changeSetting(value)Bezpośrednio z komponentu changeSetting(..)w tym przypadku.
Wydaje

@Aseem: oddzielanie zagadnień związanych z kodem, aby ułatwić zrozumienie i zmianę, jest ponadczasowe. Metoda opisana w odpowiedzi oddziela troskę o dane od troski o przedstawienie tych danych i jest tylko jednym przykładem tego, jak można to zrobić. Nie oceniałbym tego podejścia pod kątem tego, czy jest „aktualne”, ale czy ułatwia zmianę i zrozumienie kodu.
Skrzydło

1
@FlasHfromRu: Możesz odwoływać się do rzeczy z, $rootale generalnie nie jest to dobry pomysł. Zobacz tę uwagę na temat uzyskiwania dostępu do instancji root z dokumentacji Vue : „Może to być wygodne w przypadku wersji demonstracyjnych lub bardzo małych aplikacji z kilkoma komponentami. Jednak wzorzec nie skaluje się dobrze do aplikacji o średniej lub dużej skali, więc zdecydowanie zalecamy używanie Vuex do zarządzania stanem w większości przypadków. "
Skrzydło

20

Jeśli ktoś wyląduje z tym samym głupim problemem, co ja, upewnij się, że komponent ma poprawnie napisaną właściwość „ data ”. (np. dane , a nie data )

<template>
    <span>{{name}}</span>
</template>

<script>
export default {
  name: "MyComponent",
  data() {
    return {
      name: ""
    };
  }
</script>

2
stary, poważnie, mam na myśli serio Dzięki
Noni

3
Ja tutaj w 2020 roku napisałem DATA
Paaksing

lmfao ten komentarz właśnie mnie uratował
Cris Ravazzano

Powoduje to ten sam błąd, gdy błędnie wpiszesz nazwy właściwości. U mnie stało się tak, ponieważ użyłem liczby mnogiej datasw szablonie.
totymedli

Should anybody land with the same silly problem I had, make sure your component has the 'data' property spelled correctly.Lol naprawdę bardzo poważny problem :) dzięki stary
TarangP

10

W moim przypadku powód był taki, że zapomniałem tylko o zamknięciu

</script>

etykietka.

Ale to spowodowało ten sam komunikat o błędzie.


Koleś ... to było to! Nigdy bym tego nie znalazł.
KyleFarris

4

Prawdopodobnie jest to spowodowane błędem w pisowni

Dostałem literówkę w tagu zamykającym skrypt

</sscript>

3

Dodając również mój bit, jeśli ktoś ma problemy jak ja, zauważ, że w metodach rozróżniana jest wielkość liter:

<template>
    <span>{{name}}</span>
</template>

<script>
export default {
  name: "MyComponent",
  Methods: {
      name() {return '';}
  }
</script>

„Metody” powinny być „metodami”


1
w moim przypadku miałem metodę LOL
Kick Buttowski

3

Jeśli używasz dwa razy vue. Wtedy da ci ten błąd. Na przykład w app.js i własnym tagu skryptu w pliku widoku. Po prostu użyj jeden raz

 const app = new Vue({
    el: '#app',
});

2

Najprawdopodobniej jest to błąd w pisowni zarezerwowanych zmiennych vuejs. Dotarłem tutaj, ponieważ błędnie computed:napisałem, a vuejs nie rozpoznałby moich obliczonych zmiennych właściwości. Więc jeśli masz taki błąd, najpierw sprawdź pisownię!


2

Wystąpił ten błąd, gdy próbowałem przypisać właściwość komponentu do właściwości stanu podczas tworzenia instancji

export default {
 props: ['value1'],
 data() {
  return {
   value2: this.value1 // throws the error
   }
  }, 
 created(){
  this.value2 = this.value1 // safe
 }
}

2

Miałem dwa methods:w <script>, po to aby pokazać, że można spędzić wiele godzin szukając czegoś, co było takie proste pomyłka.


2

Mój problem polegał na tym, że umieszczałem metody wewnątrz mojego obiektu danych. po prostu sformatuj to w ten sposób i będzie dobrze działać.

<script>
module.exports = {
    data: () => {
        return {
            name: ""
        }
    },
    methods: {
        myFunc() {
            // code
        }
    }
}
</script>

2

Jeśli masz ten problem, sprawdź, czy nie

methods: {
...
}

lub

computed: {
...
}

oświadczył dwukrotnie


1

W moim przypadku była to właściwość, która dała mi błąd, poprawne pisanie i nadal dała mi błąd w konsoli. Szukałem tak dużo i nic dla mnie nie działało, dopóki nie dałem mu Ctrl + F5 i Voilá! błąd został usunięty. : „v

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.