Building a Student Management System with Vue.js: Components, Lifecycle Hooks, and Async Operations

Advanced Vue.js Concepts

Creating Custom Components

Components in Vue.js serve as reusable, self-contained units that encapsulate template, logic, and styling. Similar to Element UI components, custom components act as custom HTML elements that can be instantiated multiple times throughout an application.

The basic syntax for defining a global component uses Vue.component():

Vue.component('component-name', {
    props: ['propertyList'],
    data: function() {
        return { /* component state */ }
    },
    template: ''
});

A practical implementation demonstrates a custom button component:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Custom Component Demo</title>
    <script src="vue/vue.js"></script>
</head>
<body>
    <div id="root">
        <custom-btn></custom-btn>
    </div>
</body>
<script>
    Vue.component('custom-btn', {
        props: ['btnStyle'],
        data: function() {
            return {
                label: 'Click Me'
            }
        },
        template: '<button style="background-color:#3498db;color:white">{{label}}</button>'
    });

    new Vue({
        el: '#root'
    });
</script>
</html>

Understanding the Vue Instance Lifecycle

Every Vue instance undergoes a series of initialization steps throughout its existence. These phases provide hooks that allow developers to execute code at specific moments.

The eight lifecycle hooks are:

  • beforeCreate: Instance initialized, data observation not yet set up
  • created: Data observation complete, template not yet mounted
  • beforeMount: Template compiled, not yet inserted into DOM
  • mounted: Component mounted to DOM, accessible via this.$el
  • beforeUpdate: Data changed, DOM not yet re-rendered
  • updated: DOM updated to reflect data changes
  • beforeDestroy: Instance still functional before teardown
  • destroyed: All bindings and event listeners removed
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lifecycle Demo</title>
    <script src="vue/vue.js"></script>
</head>
<body>
    <div id="app">
        {{content}}
    </div>
</body>
<script>
    let vueInstance = new Vue({
        el: '#app',
        data: {
            content: 'Lifecycle Example'
        },
        beforeCreate: function() {
            console.log('beforeCreate: el=' + this.$el + ', data=' + this.$data);
        },
        created: function() {
            console.log('created: data initialized=' + this.content);
        },
        beforeMount: function() {
            console.log('beforeMount: el=' + this.$el);
        },
        mounted: function() {
            console.log('mounted: DOM ready');
        },
        beforeUpdate: function() {
            console.log('beforeUpdate: data=' + this.content);
        },
        updated: function() {
            console.log('updated: DOM synced');
        },
        beforeDestroy: function() {
            console.log('beforeDestroy: cleaning up');
        },
        destroyed: function() {
            console.log('destroyed: instance removed');
        }
    });
    vueInstance.content = 'Updated Value';
</script>
</html>

Asynchronous HTTP Requests with Axios

Vue.js applications commonly require server communication. Axios provides a promise-based HTTP client that simplifies AJAX operations.

Implementation steps:

  1. Include the Axios library script
  2. Invoke axios methods (get, post, etc.)
  3. Process responses via .then() and handle errors with .catch()

Frontend implementation:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Axios Demo</title>
    <script src="js/vue.js"></script>
    <script src="js/axios.min.js"></script>
</head>
<body>
    <div id="container">
        {{userName}}
        <button @click="fetchData()">Send Request</button>
    </div>
</body>
<script>
    new Vue({
        el: '#container',
        data: {
            userName: 'JohnDoe'
        },
        methods: {
            fetchData() {
                // POST request example
                axios.post('apiServlet', 'userName=' + this.userName)
                    .then(response => {
                        alert('Response: ' + response.data);
                    })
                    .catch(err => {
                        alert('Error: ' + err);
                    });
            }
        }
    });
</script>
</html>

Backend servlet handler:

package com.example.controller;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/apiServlet")
public class ApiServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        
        String userName = req.getParameter("userName");
        System.out.println("Received: " + userName);
        
        resp.getWriter().write("Request processed successfully");
    }
}

Student Management System Implementation

User Authentication

The login feature validates credentials against the database and establishes a user session.

Frontend login handler:

handleLogin(formRef) {
    this.$refs[formRef].validate((isValid) => {
        if (isValid) {
            axios.post('userServlet', 
                'username=' + this.credentials.username + 
                '&password=' + this.credentials.password)
                .then(response => {
                    if (response.data === true) {
                        location.href = 'dashboard.html';
                    } else {
                        alert('Invalid credentials');
                        location.href = 'login.html';
                    }
                });
        }
    });
}

UserServlet backend:

package com.example.controller;

import com.example.model.User;
import com.example.service.UserService;
import com.example.service.UserServiceImpl;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {
    private UserService userService = new UserServiceImpl();
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        
        User user = new User(username, password);
        boolean authenticated = userService.authenticate(user);
        
        if (authenticated) {
            req.getSession().setAttribute("username", username);
            resp.getWriter().write("true");
        } else {
            resp.getWriter().write("false");
        }
    }
}

UserMapper interface:

package com.example.mapper;

import com.example.model.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface UserMapper {
    @Select("SELECT * FROM user WHERE username=#{username} AND password=#{password}")
    List<User> findByCredentials(User user);
}

Paginated Student List

Vue instance for managing pagination and data display:

new Vue({
    el: '#app',
    data: {
        addDialogVisible: false,
        editDialogVisible: false,
        studentForm: {},
        editForm: {},
        studentList: [],
        pager: {
            page: 1,
            size: 5,
            totalRecords: 0
        }
    },
    methods: {
        loadStudents() {
            axios.post('studentServlet', 
                'action=pageQuery&page=' + this.pager.page + 
                '&size=' + this.pager.size)
                .then(response => {
                    this.studentList = response.data.list;
                    this.pager.page = response.data.pageNum;
                    this.pager.totalRecords = response.data.total;
                });
        },
        onPageSizeChange(newSize) {
            this.pager.size = newSize;
            this.loadStudents();
        },
        onPageChange(newPage) {
            this.pager.page = newPage;
            this.loadStudents();
        },
        openAddDialog() {
            this.addDialogVisible = true;
        },
        openEditDialog(row) {
            this.editDialogVisible = true;
            this.editForm = {
                studentId: row.studentId,
                studentName: row.studentName,
                birthDate: row.birthDate,
                location: row.location
            };
        }
    },
    mounted() {
        this.loadStudents();
    }
});

StudentServlet with pagination:

package com.example.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.example.model.Student;
import com.example.service.StudentService;
import com.example.service.StudentServiceImpl;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/studentServlet")
public class StudentServlet extends HttpServlet {
    private StudentService studentService = new StudentServiceImpl();
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json;charset=UTF-8");
        
        String action = req.getParameter("action");
        
        if ("pageQuery".equals(action)) {
            handlePageQuery(req, resp);
        }
    }
    
    private void handlePageQuery(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        int page = Integer.parseInt(req.getParameter("page"));
        int size = Integer.parseInt(req.getParameter("size"));
        
        Page<Student> result = studentService.findPaginated(page, size);
        PageInfo<Student> pageInfo = new PageInfo<>(result);
        
        String json = new ObjectMapper().writeValueAsString(pageInfo);
        resp.getWriter().write(json);
    }
}

Adding New Students

Vue method for student creation:

createStudent() {
    let payload = 'action=create' +
        '&studentId=' + this.studentForm.studentId +
        '&studentName=' + this.studentForm.studentName +
        '&birthDate=' + this.studentForm.birthDate +
        '&location=' + this.studentForm.location +
        '&page=' + this.pager.page +
        '&size=' + this.pager.size;
    
    axios.post('studentServlet', payload)
        .then(response => {
            this.studentList = response.data.list;
            this.pager.page = response.data.pageNum;
            this.pager.totalRecords = response.data.total;
        });
    this.addDialogVisible = false;
}

Servlet handler for creation:

private void handleCreate(HttpServletRequest req, HttpServletResponse resp) 
        throws IOException {
    Map<String, String[]> params = req.getParameterMap();
    Student student = new Student();
    
    registerDateConverter();
    try {
        BeanUtils.populate(student, params);
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    studentService.addStudent(student);
    resp.sendRedirect(req.getContextPath() + 
        "/studentServlet?action=pageQuery&page=" + 
        req.getParameter("page") + "&size=" + req.getParameter("size"));
}

private void registerDateConverter() {
    ConvertUtils.register(new Converter() {
        public Object convert(Class type, Object value) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            try {
                return sdf.parse(value.toString());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
    }, Date.class);
}

Mapper for insert operation:

@Insert("INSERT INTO student VALUES (#{studentId}, #{studentName}, #{birthDate}, #{location})")
void addStudent(Student student);

Updating Student Records

Vue update method:

updateStudent() {
    let payload = 'action=update' +
        '&studentId=' + this.editForm.studentId +
        '&studentName=' + this.editForm.studentName +
        '&birthDate=' + this.editForm.birthDate +
        '&location=' + this.editForm.location +
        '&page=' + this.pager.page +
        '&size=' + this.pager.size;
    
    axios.post('studentServlet', payload)
        .then(response => {
            this.studentList = response.data.list;
            this.pager.page = response.data.pageNum;
            this.pager.totalRecords = response.data.total;
        });
    this.editDialogVisible = false;
}

Mapper for update operation:

@Update("UPDATE student SET studentName=#{studentName}, birthDate=#{birthDate}, " +
        "location=#{location} WHERE studentId=#{studentId}")
void updateStudent(Student student);

Deleting Student Records

Vue delete method:

removeStudent(row) {
    if (confirm('Delete student ' + row.studentId + '?')) {
        let payload = 'action=delete' +
            '&studentId=' + row.studentId +
            '&page=' + this.pager.page +
            '&size=' + this.pager.size;
        
        axios.post('studentServlet', payload)
            .then(response => {
                this.studentList = response.data.list;
                this.pager.page = response.data.pageNum;
                this.pager.totalRecords = response.data.total;
            });
    }
}

Mapper for delete operation:

@Delete("DELETE FROM student WHERE studentId=#{studentId}")
void deleteStudent(String studentId);

Tags: Vue.js javascript frontend Component Development axios

Posted on Wed, 29 Jul 2026 17:02:54 +0000 by Goose