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]; } } });Con el código anterior, el siguiente error ocurre cuando se hace clic en el botón.
[Advertencia de Vue]: la propiedad o el método "changeSetting" no está definido en la instancia, pero se hace referencia durante el procesamiento. Asegúrese de declarar propiedades de datos reactivos en la opción de datos. (encontrado en
<MainTable>)
[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>)
El error se produce porque se hace referencia al método changeSetting en el componente MainTable aquí:
"<button @click='changeSetting(index)'> Info </button>" + Sin embargo, el método changeSetting no está definido en el componente MainTable . Se está definiendo en el componente raíz aquí:
var app = new Vue({ el: "#settings", data: data, methods: { changeSetting: function(index) { data.settingsSelected = data.settings[index]; } } });Lo que debe recordarse es que las propiedades y los métodos solo pueden referenciarse en el ámbito en el que están definidos.
Todo en la plantilla principal se compila en el ámbito principal; todo en la plantilla secundaria se compila en el ámbito secundario.
Puede leer más sobre el alcance de la compilación de componentes en la documentación de Vue.
Hasta ahora se ha hablado mucho sobre la definición de las cosas en el ámbito correcto, por lo que la solución es simplemente mover la definición de changeSetting al componente MainTable .
Parece tan simple, pero esto es lo que recomiendo.
Probablemente querrá que su componente MainTable sea un componente tonto/de presentación. ( Aquí hay algo para leer si no sabe qué es, pero un tl; dr es que el componente solo es responsable de representar algo, sin lógica). El elemento inteligente/contenedor es responsable de la lógica; en el ejemplo dado en su pregunta, el componente raíz sería el componente inteligente/contenedor. Con esta arquitectura, puede utilizar los métodos de comunicación padre-hijo de Vue para que los componentes interactúen. Transmite los datos para MainTable a través de accesorios y emite acciones de usuario desde MainTable a su padre a través de eventos . Podría verse algo como esto:
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 }, }, }),Lo anterior debería ser suficiente para darle una buena idea de qué hacer y comenzar a resolver su problema.
Si alguien aterriza con el mismo problema tonto que yo tuve, asegúrese de que su componente tenga la propiedad ' datos ' escrita correctamente. (por ejemplo, datos , y no fecha )
<template> <span>{{name}}</span> </template> <script> export default { name: "MyComponent", data() { return { name: "" }; } </script>En mi caso el motivo fue, solo se me olvido el cierre
</script>etiqueta.
Pero eso causó el mismo mensaje de error.