[Vue warn]: Propriedade ou método não é definido na instância, mas referenciado durante a renderização

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];
    }
  }
});

Com o código acima, o erro abaixo ocorre quando o botão é clicado.

[Vue warn]: A propriedade ou método "changeSetting" não é definido na instância, mas referenciado durante a renderização. Certifique-se de declarar propriedades de dados reativos na opção de dados. (encontrado em <MainTable>)

Lorenzo D'Isidoro
fonte
Seu componente não tem acesso aos métodos definidos em seu Vue. Você precisa adicionar o método changeSettingao MainTablecomponente.
Bert de

Respostas:

103

Problema

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

O erro está ocorrendo porque o changeSettingmétodo está sendo referenciado no MainTablecomponente aqui:

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

No entanto, o changeSettingmétodo não está definido no MainTablecomponente. Ele está sendo definido no componente raiz aqui:

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

O que precisa ser lembrado é que propriedades e métodos só podem ser referenciados no escopo em que são definidos.

Tudo no modelo pai é compilado no escopo pai; tudo no modelo filho é compilado no escopo filho.

Você pode ler mais sobre o escopo de compilação do componente na documentação do Vue .

O que posso fazer a respeito?

Até agora, tem se falado muito sobre como definir as coisas no escopo correto, então a correção é apenas mover a changeSettingdefinição para o MainTablecomponente?

Parece tão simples, mas aqui está o que eu recomendo.

Você provavelmente quer que seu MainTablecomponente seja um componente burro / de apresentação. ( Aqui está algo para ler se você não sabe o que é, mas um tl; dr é que o componente é apenas responsável por renderizar algo - sem lógica). O elemento smart / container é responsável pela lógica - no exemplo dado em sua pergunta, o componente raiz seria o componente smart / container. Com esta arquitetura, você pode usar os métodos de comunicação pai-filho do Vue para que os componentes interajam. Você passa os dados para MainTablevia props e emite ações do usuário MainTablepara seu pai por meio de eventos . Pode ser algo assim:

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
    },
  },
}),

O que foi dito acima deve ser suficiente para lhe dar uma boa ideia do que fazer e começar a resolver o seu problema.

Asa
fonte
3
Esta é a abordagem preferida atualmente? As coisas continuam evoluindo muito no Vue, então pensei que perguntaria
Aseem
Não sou especialista em Vue, mas stackoverflow.com/questions/43292810/… sugere que você pode chamar a função do aplicativo do seu componente via $root. Por exemplo, this.$root.changeSetting(value)diretamente do componente, changeSetting(..)neste caso. Parece mais conveniente para mim ...
FlasH de Ru de
@Aseem: separar questões de código para tornar as coisas mais fáceis de entender e mudar é atemporal. O método descrito na resposta separa a preocupação dos dados e a preocupação de apresentar esses dados e é apenas um exemplo de como as coisas podem ser feitas. Eu não avaliaria a abordagem para saber se ela é "atual", mas se torna o código mais fácil de mudar e entender.
Ala
1
@FlasHfromRu: Você pode fazer referência a coisas, $rootmas em geral não é uma boa ideia. Veja esta nota sobre como acessar instâncias raiz da documentação do Vue : "Isso pode ser conveniente para demos ou aplicativos muito pequenos com um punhado de componentes. No entanto, o padrão não se ajusta bem a aplicativos de médio ou grande porte, por isso recomendamos o uso do Vuex para gerenciar o estado na maioria dos casos. "
Ala
20

Se alguém tiver o mesmo problema bobo que eu tive, certifique-se de que seu componente tenha a propriedade ' data ' escrita corretamente. (por exemplo , dados , e não data )

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

<script>
export default {
  name: "MyComponent",
  data() {
    return {
      name: ""
    };
  }
</script>
tno2007
fonte
2
irmão, sério, quero dizer sério, obrigado
Noni,
3
Eu aqui em 2020, escrevi DATE
Paaksing
lmfao este comentário acabou de me salvar
Cris Ravazzano
Ele gera o mesmo erro quando você digita incorretamente os nomes das propriedades. Para mim aconteceu porque usei plural datasno template.
totymedli
Should anybody land with the same silly problem I had, make sure your component has the 'data' property spelled correctly.Lol realmente um problema muito siilly :) obrigado cara
TarangP
10

No meu caso, o motivo foi, só esqueci o fechamento

</script>

tag.

Mas isso causou a mesma mensagem de erro.

Frankfurt-Laravel
fonte
Cara ... era isso! Eu nunca teria encontrado isso.
KyleFarris 01 de
4

Provavelmente é causado por um erro ortográfico

Eu cometi um erro de digitação na tag de fechamento do script

</sscript>
babadores
fonte
3

Adicionando minha parte também, se alguém tiver dificuldades como eu, observe que métodos diferenciam maiúsculas de minúsculas:

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

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

'Métodos' devem ser 'métodos'

Daniel Katz
fonte
1
no meu caso, eu tinha o método LOL
Kick Buttowski
3

Se você usar duas vezes a instância vue. Em seguida, ele apresentará este erro. Por exemplo, em app.js e sua própria tag de script no arquivo de visualização. Só use uma vez

 const app = new Vue({
    el: '#app',
});
Hamza Khan
fonte
2

É mais provável que seja um erro ortográfico de variáveis ​​vuejs reservadas. Cheguei aqui porque computed:digitei errado e vuejs não reconheceria minhas variáveis ​​de propriedade computadas. Portanto, se você tiver um erro como este, verifique a ortografia primeiro!

Mahatmanich
fonte
2

Recebi este erro quando tentei atribuir uma propriedade de componente a uma propriedade de estado durante a instanciação

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

Tive dois methods:no <script>, vai mostrar, que você pode passar horas procurando por algo que foi um erro tão simples.

learncodes123
fonte
2

Meu problema era que eu estava colocando os métodos dentro do meu objeto de dados. apenas formate-o assim e ele funcionará bem.

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

Se você estiver enfrentando esse problema, certifique-se de não ter

methods: {
...
}

ou

computed: {
...
}

declarado duas vezes

Chuks Jr.
fonte
1

No meu caso foi uma propriedade que me deu o erro, a escrita correta e ainda me deu o erro no console. Procurei muito e nada funcionou para mim, até que dei a ele Ctrl + F5 e Voilá! o erro foi removido. : 'v

Jennifer Miranda Beuses
fonte