NuxtJs

https://nuxtjs.org

¿Por qué user NuxtJs?

  • Trae varias configuraciones últiles hechas por defecto.
  • Server-rendering pre configurado.
  • En esencia es VueJs, con más modules necesarios ya integrados.
  • Nos permite concentrarnos de entrada en las reglas de negocio y olvidarnos de las configuraciones.

Instalación

  • Escoger el framework par el servidor.
  • Framework UI
  • Framework de testing
  • Si queremos instalar axinos module.
  • Finalmente ESLint y Prettier
yarn create nuxt-app <my-project>
yarn dev

assets

Contiene ficheros que deben ser procesados antes de ser servidos: sass, imágenes, etc.

components

Componentes Vue que pueden ser reutilizados en varias partes de la aplicación, incluso potecialmente en otros proyectos.

No tiene los métodos asyncData y fetch.

pages

Todos los ficheros que terminen .vue serán convertido en una ruta y estarán visible en la aplicación.

Son componentes Vue con algunos métodos más adicionados por Nuxt.

  • asyncData: Retorna una objecto que será mezclado con los datos del componente.

    Puede devolver también una promesa.

  • fetch: Se utiliza para llenar el store.

  • head: Devuelve un objeto con información que se podrá en los headers de la aplicación.

¿Cómo se forman las rutas?

pages/
--| about.vue            -> /about
--| _slug/               
-----| comments.vue      -> /:slug/comments
-----| index.vue         -> /:slug
--| users/
-----| _id.vue           -> /users/:id?
--| index.vue            -> /

layouts

Tiene los layouts de la aplicación. El layout por defecto debe tener el nombre default.vue

<template>
  <nuxt/>
</template>

Dentro podemos crear tantos Layouts como queramos.

export default {
  layout: 'blog',
  // OR
  layout (context) {
    return 'blog'
  }
}

Middleware

Contiene funciones que se ejecuta antes de una página o grupo de páginas (Layouts).

En aplicaciones universal son llamados en el servidor en la primera carga y despueś en el navegador cuando se navegue.

// middleware/stats.js

export default function (context) {
  context.userAgent = process.server ? 
    context.req.headers['user-agent'] :
    navigator.userAgent
}

Middleware

Para que se ejecute antes de entrar a cualquier página, lo ponesmos en nuxt.config.js.

export default {
  router: {
    middleware: 'stats'
  }
}

Si queremos que se ejecute solo en una página o grupo hacemos lo siguiente, se hace lo mismo pero directo en la página o Layout

plugins

Es el lugar para poner código que se debe ejecutar antes de que se cree el componente raíz, antes de que se ejecute new Vue({});

// /plugins/index.vue

import Vue from 'vue'
import Vuelidate from 'vuelidate'

Vue.use(Vuelidate);

// this.$myInjectedFunction('a value')
Vue.prototype.$myInjectedFunction = (string) => console.log(string) 

Lueto en el fichero nuxt.config.js poner

export default {
  plugins: ['~/plugins/index']
}

static

Ficheros que no necesitan ser procesados y se sirven directamente.

store

  • Todos los ficheros en esta carpeta se convierte en un módulo del store.
  • Tiene un método llamado nuxtServerInit que se ejecuta solo en el servidor y permite llenar el store con datos iniciales desde el servidor.
  • El store está disponible en el servidor y en el cliente.

modules

Son funciones que permiten extender Nuxt. Está pensado para reutilizar en diferentes códigos, usarlo en un solo proyecto no tiene mucho sentido.

// /modules/simple
export default function SimpleModule (moduleOptions) {
  // Write your code here
}

moduleOptions: Es un objeto que tiene configuración pasada por el usuario.

export default {
  modules: [
    // Passing options directly
    ['~/modules/simple', { token: '123' }]
  ]
}

context

Es un objeto que es pasado a muchas funciones y tiene lo siguiente.

  • app: Root Vue Instance, está disponible en el servidor y cliente.
  • client: Boolean
  • server: Boolean
  • static: Boolean
  • isDev: Boolean
  • store: Store instance
  • req/res: Solo disponible en el servidor.

Ejemplo práctico.

Se creará una aplicación que permite listar, adicionar, eliminar y editar registros de una base de datos.

Para lograr mayor agilidad se utilizó  server json. https://github.com/typicode/json-server

Store, store/post

export const state = () => ({
  list: []
})

export const mutations = {
  setList(state, data) {
    state.list = data
  }
}

export const actions = {
  async loadList({ commit }) {
    const data = await this.$axios.$get('/posts')
    commit('setList', data)
  },
  async remove({ dispatch }, { id }) {
    await this.$axios.$delete(`/posts/${id}`)
    dispatch('loadList')
  },
  async add({ dispatch }, params) {
    await this.$axios.$post(`/posts`, params)
    dispatch('loadList')
  },
  async update({ dispatch }, params) {
    await this.$axios.$put(`/posts/${params.id}`, params)
    dispatch('loadList')
  },
  get(_, { id }) {
    return this.$axios.$get(`/posts/${id}`)
  }
}

nuxt.config.js

//.....
axios: {
  baseURL: 'http://localhost:4001'
},
//.....

Home, pages/index.vue

import { mapState } from 'vuex'

export default {
  data() {
    return {
      headers: [
        {
          text: 'Title',
          align: 'left',
          value: 'title'
        },
        { text: 'Author', value: 'author' },
        { text: 'Actions', value: 'id' }
      ]
    }
  },
  computed: {
    ...mapState({
      list: state => state.post.list
    })
  },
  async fetch({ store, params }) {
    await store.dispatch('post/loadList')
  },
  methods: {
    remove(id) {
      return this.$store.dispatch('post/remove', { id })
    }
  }
}

Home, pages/index.vue

<template>
  <v-layout column justify-center align-center>
    <v-flex xs12 sm8 md6>
      <nuxt-link to="/post/form">Create</nuxt-link>
      <v-data-table :headers="headers" :items="list" class="elevation-1">
        <template v-slot:items="props">
          <td>
            {{ props.item.title }}
          </td>
          <td class="text-xs-right">
            {{ props.item.author }}
          </td>
          <td class="text-xs-right">
            <button @click="remove(props.item.id)">
              Remove
            </button>
            <nuxt-link :to="`/post/form?id=${props.item.id}`">
              Edit
            </nuxt-link>
          </td>
        </template>
      </v-data-table>
    </v-flex>
  </v-layout>
</template>

Form, pages/form.vue

export default {
  data() {
    return {
      form: {
        title: '',
        author: '',
        description: ''
      }
    }
  },
  async created() {
    const { id } = this.$route.query
    if (id) {
      this.form = await this.$store.dispatch('post/get', { id })
    }
  },
  methods: {
    submit() {
      const form = JSON.parse(JSON.stringify(this.form))
      const action = form.id ? 'post/update' : 'post/add'
      this.$store.dispatch(action, form)
      this.$router.replace('/')
    }
  }
}

Form, pages/form.vue

<template>
  <div>
    <form @submit.prevent="submit">
      <label for="">Title</label>
      <input v-model="form.title" type="text">
      <br>
      <label for="">Author</label>
      <input v-model="form.author" type="text">
      <br>
      <label for="">Description</label>
      <textarea v-model="form.description" cols="30" rows="10" />
      <v-btn color="success" type="submit">
        OK
      </v-btn>
    </form>
  </div>
</template>
Made with Slides.com