[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>)

Lorenzo D'Isidoro
źródło
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.

Skrzydło
źródło
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>
tno2007
źródło
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.

frankfurt-laravel
źródło
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>
śliniaki
źródło
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”

Daniel Katz
źródło
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',
});
Hamza Khan
źródło
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ę!

Mahatmanich
źródło
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
 }
}
Chcę odpowiedzi
źródło
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.

learncodes123
źródło
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>
Pwntastic
źródło
2

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

methods: {
...
}

lub

computed: {
...
}

oświadczył dwukrotnie

Chuks Jr.
źródło
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

Jennifer Miranda Beuses
źródło