1, Vue introduction
Author: You Yuxi
Official website: https://cn.vuejs.org/
Vue The author is from China. His name is you Yuxi. His major is not computer science. During his college years, he majored in interior art and art history He had a master's degree in art design and technology. It was during his master's degree that he came into contact with him by chance JavaScript ,Since then, I have been deeply attracted by this programming language, Started his front-end career. In February 2014, a front-end development library was developed Vue.js. ((quoted from Baidu Encyclopedia)
-
Question 1: what is Vue:
Vue is a progressive framework for building user interfaces (free combination and flexible reuse). Vue's core library only focuses on view layers, which is not only easy to start, but also easy to integrate with third-party libraries (Vue Router: jump, axios: communication, vuex: state management).
-
Question 2: what are the advantages over other frameworks:
https://cn.vuejs.org/v2/guide/comparison.html
Angular: the front-end framework acquired by Google is characterized by moving the background MVC mode to the front-end and adding the concept of modular development
React: produced by Facebook, a high-performance JS front-end framework; The feature is that a new concept [virtual DOM] is proposed for
Reduce real DOM operations, simulate DOM operations in memory, and effectively improve the front-end rendering efficiencyVue: it combines the advantages of Angular (Modular) and React (virtual DOM), and is easy to use, flexible and efficient
-
Question 3: Vue's core features:
-
Responsive data binding
-
Composable view components
-
Virtual DOM
-
MVVM mode
MVVM is a design idea
DOM Listeners and Data Bindings are regarded as two tools, which are the key to realizing two-way binding.
From the View side, the DOM Listeners tool in the ViewModel will help us monitor the changes of DOM elements on the page. If there are changes, change the data in the Model; From the Model side, when we update the data in the Model, the Data Bindings tool will help us update the DOM elements in the page.
-
2, Element introduction
vue2.0-https://element.eleme.io/#/zh-CN
vue3.0-https://element-plus.gitee.io/zh-CN/
Website rapid prototyping tool, a set of desktop component library based on Vue 2.0 for developers, designers and product managers
3, Development environment
brew,node.js, npm and Vue cli;
- brew: it is a software package management tool, similar to yum under centos or apt get under ubuntu. It is very convenient and avoids the inconvenience of manual compilation and installation
- node.js: JavaScript running on the server side
- npm: Yes, along with node JS is a package management tool in the JavaScript world. Through npm, you can install, share and distribute code, and manage project dependencies (npm has been integrated into the new version of nodejs)
- vue cli: a scaffold officially provided to quickly generate a vue project template; The pre-defined directory structure and basic code are just like when we create Maven project, we can choose to create a skeleton project, which is the scaffold, and our development is faster;
1. Install node js
Installation tutorial: https://www.runoob.com/nodejs/nodejs-install-setup.html
Download from the official website: http://nodejs.cn/download/
Brew Download: brew install -g node
Set Taobao image accelerator
npm install cnpm -g npm install --registry=https://registry.npm.taobao.org When the back npm When the installation fails, you can use cnpm Try replacing it
2. Installing VUE-CLI
vue-cli:
At the command console, enter, - g for global installation
💡 npm install vue-cli -g
Check whether the installation is successful
💡 vue list
3. Create a vue project
To create a project from Vue cli scaffolding:
vue init webpack vue_test
Run project:
4. Engineering structure
5. Editor environment preparation
Recommendation: vsCode, webStorm, idea (the degree of recommendation decreases in order)
idea: install Vue JS plug-in (the genuine version needs to be cracked, but the community version can't find the plug-in) https://blog.csdn.net/m0_47333020/article/details/108182429
webStorm: no need to install plug-ins (genuine version needs to be cracked)
vsCode: install corresponding plug-ins (relatively convenient) https://blog.csdn.net/yujing1314/article/details/90340647
4, Adding, deleting, modifying and querying based on Vue
design sketch
1. Install routing, element UI and axios communication tools
npm install vue-router
npm i element-ui -S
npm install axios
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-fvrrzpxg-164078161641)( https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f0f72c1b-7bf7-48fc-ba14-15481a80631e/Untitled.png )]
2. In main JS: root directory - > main js
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import Vue from 'vue' import App from './App' import router from './router' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.config.productionTip = false Vue.use(ElementUI); /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
Configure agent (solve cross domain problems): root directory - > config - > index js
proxyTable: { '/': { // The request address of the back-end interface is used for local access target: 'http://114.116.255.239:8081', // secure: false, / / this parameter needs to be configured if it is an https interface changeOrigin: true, // If the interface is cross domain, you need to configure this parameter pathRewrite: { '^/': '' } } }
Universal request tool encapsulation: src -- utils -- API js
import axios from 'axios'; //Request encapsulation let base = ""; //post request encapsulation, in the form of Key and Value export const postKeyValueRequest=(url,params)=>{ return axios({ method: 'post', url: `${base}${url}`, data: params, transformRequest: [function (data) { let ret = ''; for(let i in data) { ret += encodeURIComponent(i)+'='+encodeURIComponent(data[i])+'&'; } console.log(ret); return ret; }], headers: { 'Content-Type':'application/x-www-form-urlencoded' } }) }; //post request encapsulation, json form export const postRequest = (url, params) => { return axios({ method: 'post', url: `${base}${url}`, data: params }) } //put request encapsulation export const putRequest = (url, params) => { return axios({ method: 'put', url: `${base}${url}`, data: params }) } //get request encapsulation export const getRequest = (url, params) => { return axios({ method: 'get', url: `${base}${url}`, params: params }) } //delete request encapsulation export const deleteRequest = (url, params) => { return axios({ method: 'delete', url: `${base}${url}`, params: params }) }
Routing configuration (page access and jump): src - router - index js
import Vue from 'vue' import Router from 'vue-router' import {postRequest} from "../utils/api"; import {getRequest} from "../utils/api"; import {postKeyValueRequest} from "../utils/api"; import {putRequest} from "../utils/api"; import {deleteRequest} from "../utils/api"; import Emp from "../views/Emp" //The global variable set as vue is convenient to be referenced in the component Vue.prototype.postRequest = postRequest; Vue.prototype.getRequest = getRequest; Vue.prototype.postKeyValueRequest = postKeyValueRequest; Vue.prototype.putRequest = putRequest; Vue.prototype.deleteRequest = deleteRequest; Vue.use(Router) Vue.config.productionTip = false; //Define routing rules export default new Router({ routes: [ { path: '/', name: 'Employee list', component: Emp, hidden : true } ] })
Emp.vue content:
<template> <div style="margin: 50px"> <!--increase--> <el-button size="small" type="success" style="margin-bottom:10px" @click="dialogVisible = true">add to</el-button> <el-input size="small" v-model="employee.name" placeholder="Please enter your name" style="width:200px; margin-left:30px"> </el-input> <el-select v-model="employee.gender" placeholder="Gender" size="small"> <el-option label="All" value=""></el-option> <el-option label="male" value="1"></el-option> <el-option label="female" value="0"></el-option> </el-select> <!--search--> <el-button size="small" type="primary" style="margin-bottom:10px" @click="initData()">search</el-button> <!-- List data --> <el-table :data="empList" stripe style="width: 100%"> <el-table-column type="selection" width="50"> </el-table-column> <el-table-column prop="id" label="id" width="180"> </el-table-column> <el-table-column prop="name" label="full name" width="180"> </el-table-column> <el-table-column label="Sex " width="180"> <template #default="scope"> <el-tag v-if="scope.row.gender === '1'">male</el-tag> <el-tag v-else type="warning">female</el-tag> </template> </el-table-column> <el-table-column prop="address" label="address" width="180"> </el-table-column> <el-table-column prop="email" label="mailbox" width="180"> </el-table-column> <el-table-column prop="phone" label="Telephone" width="180"> </el-table-column> <el-table-column prop="department" label="department" width="180"> </el-table-column> <el-table-column label="operation"> <template #default="scope"> <el-link type="warning" @click="update(scope.row)">modify</el-link> <el-link type="danger" @click="del(scope.row.id)">delete</el-link> </template> </el-table-column> </el-table> <!-- Add bullet frame --> <el-dialog title="add to" :visible.sync="dialogVisible" width="30%"> <el-form label-position="left" label-width="50px" :model="employee"> <el-form-item label="id"> <el-input v-model="employee.id"></el-input> </el-form-item> <el-form-item label="full name"> <el-input v-model="employee.name"></el-input> </el-form-item> <el-form-item label="address"> <el-input v-model="employee.address"></el-input> </el-form-item> <el-form-item label="Gender"> <el-radio v-model="employee.gender" label="1">male</el-radio> <el-radio v-model="employee.gender" label="0">female</el-radio> </el-form-item> <el-form-item label="department"> <el-select v-model="employee.department" placeholder="Please select"> <el-option label="ABC" value="ABC"></el-option> <el-option label="AIDC" value="AIDC"></el-option> </el-select> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">Cancel</el-button> <el-button type="primary" @click="add()">determine</el-button> </span> </el-dialog> <!-- Modify bullet frame --> <el-dialog title="modify" :visible.sync="updateDialogVisible" width="30%"> <el-form label-position="left" label-width="50px" :model="employee"> <el-form-item label="id"> <el-input v-model="employee.id"></el-input> </el-form-item> <el-form-item label="full name"> <el-input v-model="employee.name"></el-input> </el-form-item> <el-form-item label="address"> <el-input v-model="employee.address"></el-input> </el-form-item> <el-form-item label="Gender"> <el-radio v-model="employee.gender" label="1">male</el-radio> <el-radio v-model="employee.gender" label="0">female</el-radio> </el-form-item> <el-form-item label="department"> <el-select v-model="employee.department" placeholder="Please select"> <el-option label="ABC" value="ABC"></el-option> <el-option label="AIDC" value="AIDC"></el-option> </el-select> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="updateDialogVisible = false">Cancel</el-button> <el-button type="primary" @click="updateData()">determine</el-button> </span> </el-dialog> </div> </template> <script type="text/javascript"> export default { name: "Task", data() { return { employee: { id: "", name: "", gender: "", address: "", email: "", phone: "", department: "" }, empList:[], dialogVisible: false, updateDialogVisible: false } }, mounted() { this.initData(); }, methods: { clearDara() { this.employee = { id: "", name: "", gender: "", address: "", email: "", phone: "", department: "" } }, // initialization initData() { this.getRequest("employee/query", this.employee).then(res=>{ if(res.data.code == 0) { this.empList = res.data.info; } }) }, // increase add() { this.postRequest("employee/add", this.employee).then(res=>{ if(res.data.code == 0) { this.$message.success("Successfully added!"); this.initData(); } else { this.$message.error("Failed to add!" + res.data.msg); } }) this.dialogVisible = false; this.clearDara(); }, // to update update(emp) { this.employee = emp; this.updateDialogVisible = true; }, updateData() { this.putRequest("employee/update", this.employee).then(res=>{ if(res.data.code == 0) { this.$message.success("Update succeeded!"); this.initData(); }else { this.$message.error("Update failed!" + res.data.msg); } }) this.updateDialogVisible = false; this.clearDara(); }, //delete del(id) { this.$alert('Delete this record', 'Tips', { confirmButtonText: 'determine', callback: action => { this.deleteRequest("employee/delete/" + id).then(res=>{ if(res.data.code == 0) { this.$message.success("Delete succeeded!"); this.initData(); }else { this.$message.error("Deletion failed!" + res.data.msg); } }) } }); } } } </script> <style scoped> </style>
Back end main logic:
package com.controller; import com.pojo.BaseResponse; import com.pojo.Employee; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author 10018318 * Provide interface */ @RestController @RequestMapping("/employee") public class EmployeeController { private static final Map<Integer, Employee> employeeData = new LinkedHashMap<>(); static { for (int num = 1001; num <= 1010; num++) { employeeData.put(num, new Employee(num, "Li Jiegui", "1", "lijiegui1@shein.com", "15874423919", "Nanjing", "ABC")); } } /** * Query employee information */ @GetMapping("/query") public BaseResponse getEmployeeList(Employee employee) { List<Employee> employeeList = employeeData.entrySet().stream() .filter(employeeEntry -> (StringUtils.isEmpty(employee.getName()) ? true : employeeEntry.getValue().getName().contains(employee.getName())) && (StringUtils.isEmpty(employee.getGender()) ? true : employeeEntry.getValue().getGender().equals(employee.getGender()))) .map(Map.Entry::getValue).collect(Collectors.toList()); return BaseResponse.ok(employeeList); } /** * Add employee * @param employee * @return */ @PostMapping("/add") public BaseResponse addEmployee(@RequestBody Employee employee) { if (!employeeData.containsKey(employee.getId())) { employeeData.put(employee.getId(), employee); return BaseResponse.ok("Successfully added!"); } return BaseResponse.fail("Failed to add, id Repeated!"); } /** * Delete employee * @param id * @return */ @DeleteMapping("/delete/{id}") public BaseResponse delEmployeeById(@PathVariable Integer id) { employeeData.remove(id); if(!employeeData.containsKey(id)) { return BaseResponse.ok("Delete succeeded!"); } return BaseResponse.fail("Deletion failed!"); } /** * Update employees * @param employee * @return */ @PutMapping("/update") public BaseResponse updateEmployee(@RequestBody Employee employee) { employeeData.put(employee.getId(), employee); return BaseResponse.ok("Update succeeded!"); } }
Entity:
@Data @AllArgsConstructor public class Employee { private Integer id; private String name; private String gender; private String email; private String phone; private String address; private String department; }
5, How to deploy
npm run build
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-pc7olzsj-164078161641)( https://s3-us-west-2.amazonaws.com/secure.notion-static.com/eefefaa1-bbbf-4d20-908a-da9ad27980c1/Untitled.png )]
-
Deployment method:
1. Copy the contents under the dist file to the static file under the resource under the springboot project
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-kc4m2pj0-164078161642)( https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9dff1a66-fb61-464c-9b41-f4004aa14528/Untitled.png )]
2. Through nginx proxy,
#user nobody; worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name duxing.online; root /home/duxing/front/dist/; index index.html; try_files $uri $uri/ /index.html last; # gzip config gzip on; gzip_min_length 1k; gzip_comp_level 9; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary on; gzip_disable "MSIE [1-6]\."; location ^~ /prod-api/ { add_header 'Access-Control-Allow-Origin' *; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; proxy_pass http://127.0.0.1:8888/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server { listen 8085; server_name www.duxing.online; root /home/duxing/back/dist/; index index.html; try_files $uri $uri/ /index.html last; # gzip config gzip on; gzip_min_length 1k; gzip_comp_level 9; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary on; gzip_disable "MSIE [1-6]\."; location ^~ /prod-api/ { add_header 'Access-Control-Allow-Origin' *; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; proxy_pass http://127.0.0.1:8888/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
reference resources: