vue template props dinamicos data componentes javascript vue.js vuejs2 vue-component

javascript - template - [Advertencia de Vue]: la propiedad o método no está definido en la instancia, sino que se hace referencia durante el render



vue router (1)

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 error a continuación ocurre cuando se hace clic en el botón.

[Vue warn]: la propiedad o método "changeSetting" no está definido en la instancia, sino que se hace referencia durante el renderizado. Asegúrese de declarar propiedades de datos reactivos en la opción de datos. (encontrado en <MainTable> )


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

El error ocurre porque el método changeSetting está siendo referenciado 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 donde se definen.

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 documentation de Vue.

¿Qué puedo hacer al respecto?

Hasta ahora se ha hablado mucho sobre la definición de las cosas en el ámbito correcto, por lo que la solución es solo mover la definición MainTable componente MainTable .

Parece así de simple, pero esto es lo que recomiendo.

Probablemente desee que su componente MainTable sea ​​un componente tonto / presentacional. ( Here hay algo para leer si no sabe qué es sino 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. MainTable los datos de MainTable través de props y emite acciones de usuario de MainTable a su padre a través de events . Podría verse más o menos así:

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.