0 Project Overview

TinyBlog is a blogging system, as Tiny as its name is, it is an extremely Tiny Tiny Tiny 👌 blogging system, designed as a Demo application for learning various technologies 😀.

This article mainly uses Vue + Vuetify to realize the front end page. Refer to the previous article for the background interface section

TinyBlog backend development SpringBoot+JdbcTemplate version

Let’s take a look at the final result.

View a list of all blogs. (Blog data is randomly copied in digging gold, interested please search to see the original, here only as a test data demo)

A new Blog.

To edit a Blog.

1 Project Construction

1.1 Vue CLI Creation Project

Open Terminal and run the command vue create tinyblog-vuetify to create a project.

1.2 installation Vuetify

Then we switch to the project directory CD tinyblog-vuetify/and add vuetify with the vue add vuetify command.

1.3 Installing the Vue Router

Run the NPM install vue-router command to add a vue router.

1.4 installation Axios

Add axios using the NPM install axios command.

Finally, open the project with VS Code by executing code. We can start the application by running the NPM run serve command.

If the browser accesses the url of the application, it should see the following page.

1.5 technology stack

  • Vue, Vuetify

1.6 Development Tools

  • Vue CLI, VS Code

2 Writing code

2.1 Encapsulating background Interface services

2.1.1 encapsulation axios

Create a new file SRC /http.js, encapsulate axios, and define the background interface address.

2.1.2 Encapsulating background Interfaces

Encapsulate the interface provided by the background into the corresponding method, which is convenient for subsequent use. (Background interface refer to the previous article: TinyBlog backend development SpringBoot+JdbcTemplate version)

request URL Interface specification
POST /api/blog Create a blog
GET /api/blog Get all blogs
GET /api/blog/:id Get id for:idThe blog
PUT /api/blog/:id Update the id for:idThe blog
DELETE /api/blog/:id Delete the id for:idThe blog

Create the SRC/services/BlogService js file, encapsulation backend interface.

2.2 Planning Pages and Routes

2.2.1 Planning Page

The most basic functions of a blog system include at least: view blog list, create blog, edit blog. So we define at least three routing addresses:

  • /blogs: View all blogs.
  • /edit/${id}: Edit the blog with id ${id}.
  • /add: Start a new blog.

2.2.2 Defining a Route

Create a new SRC /router.js file and define our routing information.

import Vue from "vue";
import Router from "vue-router";

Vue.use(Router);


export default new Router({
  mode: "history",
  routes: [
    {
      path: "/",
      alias: "/blogs",
      name: "blogs",
      component: () => import("./components/BlogList")
    },
    {
      path: "/edit/:id",
      name: "edit",
      component: () => import("./components/EditBlog")
    },
    {
      path: "/add",
      name: "add",
      component: () => import("./components/AddBlog")
    }
  ]
});
Copy the code

2.2.3 Importing routes

After creating router.js, you need to import the route to main.js for it to take effect. (If you are running the Vue component, comment out the route in router.js temporarily, otherwise you will get an error.)

It can be seen that 3 routes correspond to 3 Vue components. The 3 components have not been written yet, but it doesn’t matter. Let’s define them first and implement them slowly later.

2.3 Writing Vue Components

Based on the previous plan, we need three Vue components. But don’t hurry up, because we need to create the navigation bar for the web page first.

2.3.1 Writing the navigation bar

We create a navigation bar component SRC/components/Navbar vue.

<template> <v-app-bar app color="white" class="d-flex justify-center"> <div class="d-flex" style="width: 960px"> <! -- LOGO --> <v-toolbar-title class="mr-2 headline grey--text text--darken-1"> <span class="font-weight-light">Tiny</span> <span>Blog</span> </v-toolbar-title> <v-spacer></v-spacer> <! <v-text-field v-model="searchParam" class=" MR-4 "style="max-width: 100%; clear: both; min-height: 1em; 450px" Dense Flat Hide-no-data hide-details "label=" dense Flat Hide-no-data Hide-details" solo-inverted ></v-text-field> <! < v-bTN to="/blogs" text> <span class="subtitle-1 grey--text text--darken-2"> </span> </ v-bTN > < V-bTN To ="/add" text> <span class="subtitle-1 grey--text text--darken-2"> </span> <v-btn > <v-icon class="grey--text text--darken-2"> mdi-github </v-icon> </v-btn> </div> </v-app-bar> </template> <script> export  default { name: "Navbar", data() { return { searchParam: "", }; }, methods: { searchByParam() { }, goToGitHub() { window.location.href ="https://gitee.com/noissues/tinyblog-vue-vuetify.git"; ,}}}; </script> <style> .navitem { width: 960px; } </style>Copy the code

Next, we’ll add our wrapped navigation bar to app.vue. (It should still contain the content of HelloWorld for now)

After the changes, NPM Run Serve starts and you can see our changes take effect.

2.3.2 Writing BlogList components

New SRC/components/BlogList. Vue components.

<template> <v-card class="mx-auto MT-3 "style="max-width: 960px" tile> <v-card-title> --> <v-col v-for="(item, i) in blogs" :key="i" cols="12" class="py-1"> <v-card outlined @click="editBlog(item.id)"> <div class="d-flex flex-no-wrap justify-space-between"> <div> <! <v-card-title class="subtitle-1 font weight-black" v-text="item.title" ></v-card-title> <! <v-card-subtitle class="grey "--text" v-text="item.description" ></v-card-subtitle> </div> </v-card> </v-col> </v-card> </template> <script> import BlogService from ".. /services/BlogService"; export default { props: ["searchParam"], name: "BlogList", data() { return { blogs: [], }; }, methods: { getAllBlogs() { BlogService.getAllBlogs() .then((response) => { this.blogs = response.data.map(this.getDisplayBlog); console.log(response.data); }) .catch((e) => { console.log(e); }); }, editBlog(id) { this.$router.push({ path: `/edit/${id}` }); }, getDisplayBlog(blog) {return {id: blog.id, title: blog.title. Length > 30? blog.title.substr(0, 30) + "..." : blog.title, description: blog.description.length > 30 ? blog.description.substr(0, 30) + "..." : blog.description, }; }, }, mounted() { this.getAllBlogs(); }}; </script> <style> .list { max-width: 960px; } </style>Copy the code

2.3.3 Writing the BlogEditor component

Noting that the page for adding and editing blogs can be reused, we split it out as a component.

New SRC/components/BlogList. Vue components.

<template> <v-form ref="form" lazy-validation> <v-card class="mx-auto" tile> <v-card-title V-if ="currentBlog"> edit blog </ V-card-title > < V-card-title V-else > newly created blog </ V-card-title > < V-card-text > < V-text-field bank statements v-model="blog.title" :rules="[(v) => !! V | | 'please fill in the title'] "label =" title "required > < / v - text - field > < v - text - field outlined v - model =" blog. Description: rules = "[(v) = >!!!!! V | | 'please fill out the brief introduction] "label =" introduction "required > < / v - text - field > < v - textarea outlined label =" content "v - model =" blog. The content ": rules =" [(v) = >!!!!! V | | 'please fill out the content] "required > - < / v textarea > < / v - card - text > < v - divider class =" mt - 2 "> < / v - divider > < v - card - actions > < div V-if ="currentBlog"> <v-btn @click="updateBlog" color="primary" small class=" MR-2 "> update </ V-bTN > < V-bTN @click="deleteBlog" color="error" small class=" MR-2 "> Delete </ V-bTN > < V-btn small @click="back"> cancel </v-btn> </div> <div V-else > <v-btn @click="addBlog" color="primary" small class=" MR-3 "> Submit </ v-bTN > </div> </v-card-actions> </ V-card > </v-form> </template> <script> import BlogService from ".. /services/BlogService"; export default { name: "BlogEditor", props: ["currentBlog"], data() { return { blog: { id: null, title: "", description: "", content: "", }, message: "", }; }, methods: { back() { this.$router.back(); }, updateBlog() { BlogService.updateBlog(this.blog.id, this.blog) .then((response) => { console.log(response.data); This.$emit("updated", "🎉 blog updated successfully!" ); }) .catch((e) => { console.log(e); }); }, addBlog() { var data = { title: this.blog.title, description: this.blog.description, content: this.blog.content, }; BlogService.addBlog(data) .then((response) => { console.log(response.data); let data = {}; data.id = response.data.id; Data. message = "🎉 blog created successfully!" ; this.$emit("added", data); }) .catch((e) => { console.log(e); }); }, deleteBlog() { BlogService.deleteBlog(this.blog.id) .then((response) => { console.log(response.data); this.$router.push({ name: "blogs" }); }) .catch((e) => { console.log(e); }); }, }, mounted() { if (this.currentBlog) { this.blog.id = this.currentBlog.id; this.blog.title = this.currentBlog.title; this.blog.description = this.currentBlog.description; this.blog.content = this.currentBlog.content; }}}; </script>Copy the code

2.3.4 Writing AddBlog component

New SRC/components/AddBlog vue components. Use the BlogEditor component we just created.

<template> <div class="submit-form mt-3 mx-auto"> <div v-if="! Submitted "> <BlogEditor @added="addBlogHandler" /> </div> <div V-else > < V-card class="mx-auto"> < V-card-title > 🎉  </v-card-subtitle> <v-card-subtitle> <v-btn color="primary" @click="editBlog"> </ v-bTN > < v-bTN color="success" @click="addBlog"> </div> </div> </template> <script> import BlogEditor from "./BlogEditor"; export default { name: "AddBlog", components: { BlogEditor, }, data() { return { submitted: false, }; }, methods: { addBlogHandler(data) { this.submitted = true; this.id = data.id; // New blog id}, addBlog() {this.submitted = false; }, editBlog() { this.$router.push({ path: `/edit/${this.id}` }); ,}}}; </script> <style> .submit-form { max-width: 960px; margin: auto; } </style>Copy the code

2.3.5 Writing the EditBlog component

New SRC/components/EditBlog vue components.

<template> <div v-if="currentBlog" class="edit-form mt-3 mx-auto"> <BlogEditor v-bind:currentBlog="currentBlog" @updated="updateBlogHandler" /> <v-snackbar v-model="snackbar" :timeout="timeout" top> {{ message }} <template V-slot :action="{attrs}"> <v-btn color="white" text v-bind="attrs" @click="snackbar = false"> Close </ v-bTN > </template> </v-snackbar> </div> </template> <script> import BlogService from ".. /services/BlogService"; import BlogEditor from "./BlogEditor"; export default { name: "EditBlog", components: { BlogEditor, }, data() { return { snackbar: false, timeout: 2000, currentBlog: null, message: "", }; }, methods: { updateBlogHandler(message) { this.snackbar = true; this.message = message; }, getBlog(id) { BlogService.getBlogById(id) .then((response) => { this.currentBlog = response.data; console.log(response.data); }) .catch((e) => { console.log(e); }); }, }, mounted() { this.getBlog(this.$route.params.id); }}; </script> <style> .edit-form { max-width: 960px; margin: auto; } </style>Copy the code

3 Running Tests

Start the back-end service first.

Note that several bugs in the back-end interface were found when testing the front-end code, which have been fixed. Please update the latest code test.

Then NPM Run Serve starts the foreground application.

A new Blog.

To edit a Blog.

4 Project Summary

This paper mainly introduces the TinyBlog front-end development process, mainly using Vue + Vuetify to achieve. The code has been uploaded to my Gitee repository.

Since most of the work is still background development, TinyBlog’s front-end is also for sale, so if you have any ideas or suggestions, please leave them in the comments section.