• Assurez la sécurité des applications de la bonne manière! Détectez, protégez, surveillez, accélérez et plus encore…
  • Apprenez à créer une application Nuxt.

    CRUD - Créer, lire, mettre à jour, supprimer

    Je suppose que vous connaissez déjà les principes de base de Vue JS et / ou que vous êtes un peu familier avec le cadre. Nuxt JS est un framework robuste, construit sur Vue JS. C'est essentiellement le même que Vue JS. Alors pourquoi, Nuxt?

    Pour la plupart des gens, la décision d'utiliser Nuxt JS est généralement pour ses capacités SSR.

    Qu'est-ce que le SSR?

    SSR est une abréviation de Server Side Rendering.

    Habituellement, pour la plupart des applications à page unique (SPA), les fichiers rendus sont automatiquement injectés dans le DOM après le chargement de la page. Par conséquent, les robots et les robots d'exploration trouveront une page vide lors du chargement de la page. Cependant, pour SSR, en raison de sa capacité à pré-rendre les applications sur le serveur avant la page, cette page peut être facilement indexée par les robots d'exploration SEO. En outre, cela rend l'application encore plus performante qu'un SPA classique.

    Nuxt JS donne aux développeurs la possibilité de créer facilement des applications SSR. Les applications Vue JS SPA standard peuvent également être configurées pour utiliser SSR, mais le processus est quelque peu fastidieux, et Nuxt JS fournit un wrapper pour gérer toute cette configuration. Outre le SSR, Nuxt fournit également un moyen simple de configurer votre projet VueJS avec plus d'efficacité.

    Bien que Nuxt JS soit toujours Vue JS, il présente des différences fondamentales dans la structure de son architecture de dossiers.

    L'objectif de cet article est que vous puissiez créer une application avec Nuxt; Par conséquent, nous n'allons pas plonger profondément dans l'architecture de dossiers de Nuxt, cependant, je vais rapidement expliquer certains des éléments importants dont nous pourrions avoir besoin ici.

    Nos Pages

    Le dossier pages est l'une des différences fondamentales avec Vue SPA classique. Il représente le dossier Views dans l'architecture Vue standard, de plus, dans Nuxt, les fichiers créés dans le dossier Pages sont automatiquement provisionnés en tant que route. Cela signifie que lorsque vous créez un fichier index.vue dans le dossier pages, cela devient automatiquement votre route racine, c'est-à-dire localhost: 3000 /.

    De plus, lorsque vous créez un autre nom de fichier.vue, il devient une route - la création de about.vue vous permet d'accéder à localhost: 3000 / about.

    Vous pouvez également créer un dossier dans le dossier Pages. Si vous créez un dossier nommé «contact» et que dans ce dossier, vous avez email.vue, vous pouvez accéder à localhost: 3000 / contact / email. C'est aussi simple que cela. De cette façon, vous n'avez pas besoin de créer manuellement un fichier router.js comme vous le feriez généralement avec Vue JS pour créer vos routes.

    Composants

    C'est toujours à peu près la même chose qu'avec Vue JS, les composants créés ne sont pas automatiquement provisionnés en tant que routes.

    Statique

    Le dossier statique remplace le dossier public dans les applications Vue JS normales, fonctionne à peu près de la même manière. Les fichiers ici ne sont pas compilés; ils sont servis de la même manière qu'ils sont stockés.

    Vous pouvez tout lire sur l'architecture et la structure au Page de documentation Nuxt JS.

    Maintenant, construisons quelque chose d'intéressant…

    Créer une application de librairie

    Nous allons créer une application de librairie, dans laquelle un utilisateur peut ajouter des livres qu'il a lus à une catégorie particulière qu'il aime. Il ressemblera à ceci.

    Ainsi, nous aurons une mise en page simple comme ci-dessus, juste 3 colonnes contenant les différentes sections de livres. Récemment lu des livres, des livres préférés, et oui, le meilleur des meilleurs livres (j'avoue, je ne savais pas comment appeler cette section, 🙂)

    Donc, le but ici, est de pouvoir ajouter le titre, l'auteur et la description d'un livre à une carte sur n'importe laquelle des sections, éditer des livres déjà ajoutés et supprimer un livre existant. Nous n'utiliserons aucune base de données, donc tout se passe dans l'état.

    Tout d'abord, nous installons Nuxt:

    npm install create-nuxt-app

    Deuxièmement, après avoir installé Nuxt, vous pouvez maintenant créer le projet avec la commande,

    create-nuxt-app bookStore

    Je choisis de nommer mon application «bookStore»; vous pouvez nommer votre quelque chose de plus cool ^ _ ^

    Ensuite, parcourons les invites restantes, entrez une description,

    Nom de l'auteur, saisissez un nom ou appuyez sur Entrée pour conserver les valeurs par défaut

    Sélectionnez un gestionnaire de packages, selon lequel vous êtes à l'aise, les deux vont bien

    Sélectionnez un cadre d'interface utilisateur. Pour ce projet, j'utiliserai Vuetify, puis encore une fois, tout framework d'interface utilisateur avec lequel vous êtes à l'aise fera très bien l'affaire.

    Sélectionnez un cadre de serveur personnalisé; nous n'en avons pas besoin, je n'en sélectionnerai aucun

    Modules supplémentaires, sélectionnez ce que vous voulez ou sélectionnez les deux, nous ne les utiliserions pas pour cette application.

    Le peluchage est important. Allons-y avec ESLint.

    Bien que les tests soient importants, nous ne nous pencherons pas sur cela aujourd'hui, donc aucun

    Mode de rendu, ouais SSR c'est ça.

    Remarque: le choix de SSR ne signifie pas que nous n'obtenons pas l'avantage d'avoir un SPA, l'application reste toujours un SPA mais avec SSR. L'autre option signifie simplement SPA et pas de SSR.

    Appuyez sur Entrée et continuez,

    Et notre projet crée,

    Après la création, nous pouvons maintenant aller dans le répertoire et exécuter

    yarn dev

    si vous utilisez npm en tant que gestionnaire de paquets, utilisez,

    npm run dev

    Par défaut, l'application s'exécute sur localhost: 3000. Visitez le lien dans votre navigateur et vous devriez voir une page Nuxt par défaut.

    Commençons maintenant par créer les composants dont nous avons besoin. Nous aurons des cartes affichant les informations de chaque livre, et nous aurons un modal contenant un formulaire pour saisir de nouvelles informations sur le livre ou modifier celles existantes.

    Pour créer un composant, créez simplement un nouveau fichier dans le dossier des composants. Voici le code du composant de ma carte.

    // BookCard.vue
    
    <template>
      <v-card class="mx-auto" max-width="400">
        <v-img src="https://cdn.vuetifyjs.com/images/cards/sunshine.jpg" height="200px"></v-img>
        <v-card-title>{{bookTitle}}</v-card-title>
        <v-card-subtitle>{{bookAuthor}}</v-card-subtitle>
        <v-card-text>{{bookDescription}}</v-card-text>
        <v-card-actions>
          <v-spacer></v-spacer>
          <slot name="button"></slot>
        </v-card-actions>
      </v-card>
    </template>
    
    <script>
    export default {
      props: ["bookTitle", "bookAuthor", "bookDescription"]
    };
    </script>

    Une explication rapide de ce qui est fait ci-dessus. L'image est codée en dur; nous ne nous soucierons pas de cela pour le moment. Le titre du livre, l'auteur du livre et la description du livre sont transmis à ce composant depuis la page parent en tant qu'accessoires. Si vous n'êtes pas familier avec les accessoires, imaginez-les comme des points d'entrée grâce auxquels ce composant peut être rempli de données.

    Passons maintenant au composant suivant, le modal.

    //BookModal.vue
    
    <template>
      <v-dialog max-width="500px" v-model="open">
        <v-card class="p-5">
          <v-card-title>Add Books</v-card-title>
          <v-form>
            <v-select v-model="category" :items="categories" label="Select A Category"></v-select>
            <v-text-field v-model="title" label="Enter Book Title"></v-text-field>
            <v-text-field v-model="author" label="Enter Book Author"></v-text-field>
            <v-textarea v-model="description" label="Enter Book Description"></v-textarea>
          </v-form>
          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn @click.stop="saveBook" color="green">Add</v-btn>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </template>

    Maintenant, c'est le balisage pour le modal; nous devons créer les v-models en tant que propriétés de données; par conséquent, nous ajouterons une balise de script sous le marque.

    <script>
    export default {
      data() {
        return {
          category: "",
          title: "",
          author: "",
          description: "",
        };
      },
    }
    </script>

    En outre, il existe une liste déroulante «Sélectionner une catégorie» qui attend des données de «catégories». Nous ajouterons cela aux données.

    <script>
    export default {
      data() {
        return {
          open: false,
          category: "",
          title: "",
          author: "",
          description: "",
          categories: ["Recently read books", "Favourite books", "Best of the best"]
        };
      },
    }
    </script>

    Maintenant, nous avons besoin d'un moyen de basculer notre ouverture et fermeture modales, pour l'instant, nous aurons juste une propriété de données `` ouverte '' comme ci-dessus. Nous examinerons cela de près ensuite.

    Créons rapidement notre page d'affichage où nous aurons trois grilles / colonnes, une pour chaque section du livre. Appelons la page index.vue, voir le code ci-dessous.

    //index.vue
    <template>
      <div>
        <v-row>
          <v-col md="4">
            <h2 class="text-center mb-5">Recently Read Books</h2>
          </v-col>
          <v-col md="4">
            <h2 class="text-center mb-5">Favourite Books</h2>
          </v-col>
          <v-col md="4">
            <h2 class="text-center mb-5">Best of the Best</h2>
          </v-col>
        </v-row>
        <BookModal />
      </div>
    </template>

    Maintenant que nous avons nos grilles, nous devons ajouter notre composant carte à chaque grille, pour chaque livre ajouté. Par conséquent, nous importerons notre composant BookCard.vue.

    <template>
      <div>
        <v-row>
          <v-col md="4">
            <h2 class="text-center mb-5">Recently Read Books</h2>
            <v-row v-for="(item,index) in recentBooks" :key="index">
              <BookCard
                class="mb-5"
                :bookTitle="item.title"
                :bookAuthor="item.author"
                :bookDescription="item.description"
              >
                <template v-slot:button>
                  <v-btn @click.stop="edit(item,index)">Edit</v-btn>
                  <v-btn @click.stop="remove(item.category, index)">Remove</v-btn>
                </template>
              </BookCard>
            </v-row>
          </v-col>
          <v-col md="4">
            <h2 class="text-center mb-5">Favourite Books</h2>
            <v-row v-for="(item,index) in favouriteBooks" :key="index">
              <BookCard
                class="mb-5"
                :bookTitle="item.title"
                :bookAuthor="item.author"
                :bookDescription="item.description"
              >
                <template v-slot:button>
                  <v-btn @click.stop="edit(item,index)">Edit</v-btn>
                  <v-btn @click.stop="remove(item.category, index)">Remove</v-btn>
                </template>
              </BookCard>
            </v-row>
          </v-col>
          <v-col md="4">
            <h2 class="text-center mb-5">Best of the Best</h2>
            <v-row v-for="(item,index) in bestOfTheBest" :key="index">
              <BookCard
                class="mb-5"
                :bookTitle="item.title"
                :bookAuthor="item.author"
                :bookDescription="item.description"
              >
                <template v-slot:button>
                  <v-btn @click.stop="edit(item,index)">Edit</v-btn>
                  <v-btn @click.stop="remove(item.category, index)">Remove</v-btn>
                </template>
              </BookCard>
            </v-row>
          </v-col>
        </v-row>
      </div>
    </template>

    Maintenant, nous avons importé le composant BookCard et avons lié ses accessoires aux résultats de la boucle; cela garantit que pour chaque entrée ajoutée à l'une des sections, une carte est créée pour elle. De plus, sur chaque carte, nous inclurons des boutons pour modifier ou supprimer une carte.

    Maintenant, nous devons importer la carte depuis le script et définir les tableaux qui contiendront des enregistrements pour chacune des catégories.

    <script>
    import BookCard from "@/components/BookCard";
    
    export default {
      components: {
        BookCard,
      },
      data() {
        return {
          recentBooks: [],
          favouriteBooks: [],
          bestOfTheBest: []
        };
      },
    };
    </script>

    Ensuite, nous devons avoir un bouton dans l'en-tête qui ouvrira le modal chaque fois que nous aurons besoin d'ajouter des livres. Nous le ferons dans le fichier 'default.vue'. Nous ajouterons le bouton à l'en-tête de la barre d'application par défaut.

    <v-btn color="green" @click.stop="openModal">Add Books</v-btn>

    Ensuite, nous devons créer la méthode openModal dans la section script. Dans les applications Vue JS classiques, il existe un bus d'événements qui vous permet de communiquer avec un autre composant et même de transmettre des données, dans Nuxt JS, il existe toujours un bus d'événements et vous pouvez toujours le créer de la même manière. Nous allons donc utiliser un bus d'événements pour passer des données en ouvrant un modal dans la page index.vue (que nous devons encore importer) à partir du fichier layout / default.vue.

    Voyons comment cela se fait.

    Pour créer un bus d'événements global, ouvrez un fichier dans le répertoire racine du projet, nommez-le eventBus.js et collez-y le code ci-dessous.

    import Vue from 'vue'
    
    export const eventBus = new Vue()

    Ouais, c'est tout. Maintenant, nous pouvons l'utiliser.

    <script>
    import { eventBus } from "@/eventBus";
    methods: {
        openModal() {
          eventBus.$emit("open-add-book-modal");
        }
      }
    </script>

    Ensuite, nous retournerons à notre composant BookModal, et écouterons quand le eventBus émettra 'open-add-book-modal'. Nous ajouterons ceci à la section script.

    import { eventBus } from "@/eventBus";
    
    created() {
        eventBus.$on("open-add-book-modal", this.open = true);
      },

    Maintenant, nous pouvons ouvrir et fermer notre modal, mais il n'ajoute pas encore de livres. Ajoutons une méthode à notre Modal pour lui faire enregistrer ce qui est ajouté à l'état (rappelez-vous que nous n'utilisons aucune base de données ou stockage local). Nous ajoutons ceci à côté de 'created ()'

    methods: {
        saveBook() {
          let cardData = {
            title: this.title,
            author: this.author,
            description: this.description,
            category: this.category
          };
          eventBus.$emit("save-book", cardData);
          this.open = false;
        }
      }

    Ensuite, nous avons besoin d'un moyen de remplir à nouveau le modal lorsque nous éditons des données à partir de l'une des cartes. Faisons donc quelques ajustements au 'created ()'

    created() {
        eventBus.$on("open-add-book-modal", data => {
          if (data) {
            this.category = data.category;
            this.title = data.title;
            this.author = data.author;
            this.description = data.description;
          }
          this.open = true;
        });
      },

    Maintenant, le BookModal ressemble à ceci dans son ensemble,

    //BookModal.vue
    
    
    <template>
      <v-dialog max-width="500px" v-model="open">
        <v-card class="p-5">
          <v-card-title>Add Books</v-card-title>
          <v-form>
            <v-select v-model="category" :items="categories" label="Select A Category"></v-select>
            <v-text-field v-model="title" label="Enter Book Title"></v-text-field>
            <v-text-field v-model="author" label="Enter Book Author"></v-text-field>
            <v-textarea v-model="description" label="Enter Book Description"></v-textarea>
          </v-form>
          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn @click.stop="saveBook" color="green">Add</v-btn>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </template>
    
    <script>
    import { eventBus } from "@/eventBus";
    export default {
      data() {
        return {
          open: false,
          category: "",
          title: "",
          author: "",
          description: "",
          categories: ["Recently read books", "Favourite books", "Best of the best"]
        };
      },
      created() {
        eventBus.$on("open-add-book-modal", data => {
          if (data) {
            this.category = data.category;
            this.title = data.title;
            this.author = data.author;
            this.description = data.description;
          }
          this.open = true;
        });
      },
      methods: {
        saveBook() {
          let cardData = {
            title: this.title,
            author: this.author,
            description: this.description,
            category: this.category
          };
          eventBus.$emit("save-book", cardData);
          this.open = false;
        }
      }
    };
    </script>

    Ensuite, nous pouvons maintenant revenir à la page index.vue pour importer le composant BookModal. Nous ajouterons ceci à la section script.

    <script>
    import BookCard from "@/components/BookCard";
    import BookModal from "@/components/BookModal";
    import { eventBus } from "@/eventBus";
    
    export default {
      components: {
        BookCard,
        BookModal
      },
      data() {
        return {
          recentBooks: [],
          favouriteBooks: [],
          bestOfTheBest: []
        };
      },
    </script>

    Aussi, dans le corps, nous ajouterons,

    <BookModal/>

    Nous avons besoin de méthodes pour modifier et supprimer une carte. Dans le modèle précédent, j'ai déjà transmis les méthodes d'édition et de suppression aux boutons comme indiqué ci-dessous, de même, j'ai transmis les arguments requis pour chaque méthode.

    <template v-slot:button> <v-btn @click.stop="edit(item,index)">Edit</v-btn> <v-btn @click.stop="remove(item.category, index)">Remove</v-btn> </template>

    Créons les méthodes.

    methods: {
        remove(category, index) {
          if (category === "Recently read books") {
            this.recentBooks.splice(index, 1);
          }
          if (category === "Favourite books") {
            this.favouriteBooks.splice(index, 1);
          }
          if (category === "Best of the best") {
            this.bestOfTheBest.splice(index, 1);
          }
        },
        edit(item, index) {
          if (item.category === "Recently read books") {
            eventBus.$emit("open-add-book-modal", item);
            this.recentBooks.splice(index, 1);
          }
          if (item.category === "Favourite books") {
            eventBus.$emit("open-add-book-modal", item);
            this.favouriteBooks.splice(index, 1);
          }
          if (item.category === "Best of the best") {
            eventBus.$emit("open-add-book-modal", item);
            this.bestOfTheBest.splice(index, 1);
          }
        }
      }

    Rappelez-vous, le BookModal émet, et un événement appelé save-book, nous avons besoin d'un auditeur pour cet événement ici.

    created() {
        eventBus.$on("save-book", cardData => {
          if (cardData.category === "Recently read books") {
            this.recentBooks.push(cardData);
          }
          if (cardData.category === "Favourite books") {
            this.favouriteBooks.push(cardData);
          }
          if (cardData.category === "Best of the best") {
            this.bestOfTheBest.push(cardData);
          }
        });
      },

    Maintenant, en un seul coup d'œil, notre page index.vue ressemble à ceci

    <template>
      <div>
        <v-row>
          <v-col md="4">
            <h2 class="text-center mb-5">Recently Read Books</h2>
            <v-row v-for="(item,index) in recentBooks" :key="index">
              <BookCard
                class="mb-5"
                :bookTitle="item.title"
                :bookAuthor="item.author"
                :bookDescription="item.description"
              >
                <template v-slot:button>
                  <nuxt-link :to="`/books/${item.title}`">
                    <v-btn>View</v-btn>
                  </nuxt-link>
                  <v-btn @click.stop="edit(item,index)">Edit</v-btn>
                  <v-btn @click.stop="remove(item.category, index)">Remove</v-btn>
                </template>
              </BookCard>
            </v-row>
          </v-col>
          <v-col md="4">
            <h2 class="text-center mb-5">Favourite Books</h2>
            <v-row v-for="(item,index) in favouriteBooks" :key="index">
              <BookCard
                class="mb-5"
                :bookTitle="item.title"
                :bookAuthor="item.author"
                :bookDescription="item.description"
              >
                <template v-slot:button>
                  <v-btn @click.stop="edit(item,index)">Edit</v-btn>
                  <v-btn @click.stop="remove(item.category, index)">Remove</v-btn>
                </template>
              </BookCard>
            </v-row>
          </v-col>
          <v-col md="4">
            <h2 class="text-center mb-5">Best of the Best</h2>
            <v-row v-for="(item,index) in bestOfTheBest" :key="index">
              <BookCard
                class="mb-5"
                :bookTitle="item.title"
                :bookAuthor="item.author"
                :bookDescription="item.description"
              >
                <template v-slot:button>
                  <v-btn @click.stop="edit(item,index)">Edit</v-btn>
                  <v-btn @click.stop="remove(item.category, index)">Remove</v-btn>
                </template>
              </BookCard>
            </v-row>
          </v-col>
        </v-row>
        <BookModal />
      </div>
    </template>
    
    <script>
    import BookCard from "@/components/BookCard";
    import BookModal from "@/components/BookModal";
    import { eventBus } from "@/eventBus";
    
    export default {
      components: {
        BookCard,
        BookModal
      },
      data() {
        return {
          recentBooks: [],
          favouriteBooks: [],
          bestOfTheBest: []
        };
      },
      created() {
        eventBus.$on("save-book", cardData => {
          if (cardData.category === "Recently read books") {
            this.recentBooks.push(cardData);
            this.recentBooks.sort((a, b) => b - a);
          }
          if (cardData.category === "Favourite books") {
            this.favouriteBooks.push(cardData);
            this.favouriteBooks.sort((a, b) => b - a);
          }
          if (cardData.category === "Best of the best") {
            this.bestOfTheBest.push(cardData);
            this.bestOfTheBest.sort((a, b) => b - a);
          }
        });
      },
      methods: {
        remove(category, index) {
          if (category === "Recently read books") {
            this.recentBooks.splice(index, 1);
          }
          if (category === "Favourite books") {
            this.favouriteBooks.splice(index, 1);
          }
          if (category === "Best of the best") {
            this.bestOfTheBest.splice(index, 1);
          }
        },
        edit(item, index) {
          if (item.category === "Recently read books") {
            eventBus.$emit("open-add-book-modal", item);
            this.recentBooks.splice(index, 1);
          }
          if (item.category === "Favourite books") {
            eventBus.$emit("open-add-book-modal", item);
            this.favouriteBooks.splice(index, 1);
          }
          if (item.category === "Best of the best") {
            eventBus.$emit("open-add-book-modal", item);
            this.bestOfTheBest.splice(index, 1);
          }
        }
      }
    };
    </script>

    Si vous êtes arrivé jusqu'ici, super boulot !!! Tu es incroyable!

    Comme mentionné précédemment, chaque fichier .vue créé dans le dossier pages est automatiquement provisionné comme une route, de même, pour chaque dossier créé dans le dossier pages. Cela ne vaut pas seulement pour les pages statiques, et les pages dynamiques peuvent également être créées de cette façon!

    Voyons comment.

    En utilisant notre projet actuel, disons que nous voulons ajouter une page dynamique pour toutes les cartes de livre avec un bouton d'affichage pour afficher plus de détails sur un livre.

    Ajoutons rapidement un bouton d'affichage et utilisons un <nuxt-link> pour visiter la page. Ouais, <nuxt-link> remplace <router-link> et ça marche.

    <nuxt-link :to="`/${item.title}`">
                    <v-btn>View</v-btn>
                  </nuxt-link>

    Ensuite, nous créons un dossier dynamique en préfixant le nom avec un trait de soulignement. c'est-à-dire, _title et à l'intérieur de ce dossier, nous aurons un fichier index.vue qui sera rendu lorsque nous visiterons cette route.

    Juste pour la démonstration, nous n'accéderons qu'à la propriété params dans le fichier.

    // _title/index.vue
    
    <template>
      <h1>{{$route.params.title}}</h1>
    </template>

    Maintenant, lorsque nous cliquons sur afficher, cela ouvre une autre page où nous pouvons voir le titre que nous avons passé par l'itinéraire. Cela peut être développé pour faire tout ce que nous voulons en ce qui concerne les pages dynamiques.

    Voilà pour cette leçon!

    Le code complet pour cela se trouve dans ce dépôt. Vous êtes invités à contribuer au code. Si vous souhaitez maîtriser le cadre, je vous suggère ceci Cours Udemy.