Estoy siguiendo este CodePen, e intentando encajarlo en el VueJS 2.0 Boilerplate predeterminado. Así es como dividiría los archivos:

App.vue
main.js
components/Transitions.vue
components/Controls.vue
components/Page.vue

Tengo grandes problemas para que esto funcione. P.ej. mi App.vue no encuentra el state. Así es como lo definí en main.js :

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

const state = {
    animations: ['fade', 'slide', 'slideUp', 'zoom', 'flipX', 'flipY'],
    view: 'slide'
}

new Vue({
  render: h => h(App),
  data() {
    return this.state
  }
}).$mount('#app')

Este es mi App.vue :

<template>
  <div id="app">
    <component :is="state.view">
      <h1>{{ state.view }}</h1>
    </component>
    <controls></controls>
  </div>
</template>

Estos serían mis controles:

<template id="controls">
<ul class="controls">
  <li v-for="(animation, index) in state.animations" v-bind:key="index" @click.prevent="setView(animation)" v-bind:class="{ 'active': animation === state.view }">
    {{ animation }}
  </li>
</ul>
</template>

<script>
export default {
  template: '#controls',

  methods: {
    setView(animation) {
      this.state.view = animation
    }
  }
}
</script>

..Etcétera. Lamentablemente estoy obteniendo:

[Vue warn]: data functions should return an object:
https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function

(found in <Root>) vue.runtime.esm.js:619
[Vue warn]: Property or method "state" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

found in

---> <App> at src/App.vue
       <Root> vue.runtime.esm.js:619
[Vue warn]: Error in render: "TypeError: this.state is undefined"

¿Qué estoy haciendo mal aquí? ¿Cómo hacer que esto funcione?

2
stevek 20 feb. 2020 a las 21:47

2 respuestas

La mejor respuesta

Adjuntar propiedades de datos a la instancia raíz no las hace disponibles globalmente en todos los componentes descendientes (que parece ser lo que intentó). En realidad, hay algunas formas de compartir el estado entre los componentes, incluidos Vuex o bus de eventos globales (p. ej., usando $root.emit() y $root.on()). Sin embargo, otra solución simple es usar Vue.observable junto con un mixin, exportado desde un archivo compartido:

stateMixin.js:

import { observable } from "vue";

const state = observable({
  animations: ["fade", "slide", "slideUp", "zoom", "flipX", "flipY"],
  view: "slide"
});

// a mixin that declares a data propety named `state`
export default {
  data() {
    return {
      state
    };
  }
};

Luego, puede importar ese archivo a cualquier componente que necesite acceder a state:

App.vue:

import stateMixin from '@/stateMixin'

export default {
  mixins: [stateMixin],
  mounted() {
    console.log(this.state.view) // <-- stateMixin provides access to `state`
  }
}

demostración de ese Codepen en Codesandbox


También tenga en cuenta que, dado que está convirtiendo a componentes de un solo archivo (SFC), no debe exportar una propiedad template. El SFC mismo declara la plantilla ya, y el compilador sabe usarla por defecto.

2
tony19 21 feb. 2020 a las 05:11

Puede devolver ese state aplicando el operador de propagación de la siguiente manera:

const state = {
    animations: ['fade', 'slide', 'slideUp', 'zoom', 'flipX', 'flipY'],
    view: 'slide'
}

new Vue({
  render: h => h(App),
  data() {
    return {...state} 
  }
}).$mount('#app')
1
Boussadjra Brahim 20 feb. 2020 a las 18:58