前言:一路走来,迈出了转型的好多个第一步,从第一个 Java swing 点餐程序的磕磕绊绊,再到现在自己纯手写的这个博客网站的搭建,中间收获了很多,也经历过最枯燥的日子,感谢教导我的老师们和陪我一路走来的好朋友。
1、巩固自己半年内的前端技术学习成果。从去年八月份(2021年8月份)开始,发现自己的知识体系太过片面,对于前端一窍不通,只是停留在 HTML 阶段,这样对于以后的学习肯定会出现知识断层。于是网上找课程进行系统的学习,方便以后和前端的同学好沟通。
2、分享自己平时学习过程中的一些心得总结和感悟。我个人认为检验一个人掌握知识的最好方法就是---通过自己的分享把复杂的知识点简易化的讲解出来,即输入输出。所以分享总结在学习编程的过程中是很重要的。
1、前端技术:vue2、element-ui、vuex
2、服务端:Node.js、express、mongoodb、mongoose
3、对于服务端的技术选型,当时很纠结,本来计划是使用 mysql 和 ssm 框架,于是打算提前看spring和springMvc,但是后边听从了一个大佬的建议,便选用了 Node.js 作为服务端,虽然使用的还是 mvc 模式,但是总感觉写起来没有 Java 的三层架构舒服吧,只是搭建服务的方式比较简单吧,使用 express 框架,直接几行代码就可以跑起来一个服务。
1、这个博客系统主要由用户端和后台管理组成,这儿只展示部分页面。



2、功能需求分析


3、数据库表设计。


这是我使用 vue-cli 创建的项目结构,由于第一次使用,我对项目的结构把握的不是很好,在组件里边我的结构不是很清晰,而且我对所有的请求没有进行一个统一的封装,这样后期项目部署后,运行时请求太多,可能会造成504 错误,所以在今后的项目中,可以在src 目录下创建一个 api 目录用来封装所有的请求,同时全局创建一个request.js文件来处理请求和响应的公共逻辑。
views 文件夹下放置你所有的路由页面,这个项目中我也使用了 vuex,但是官方的说法是小型应用不需要 vuex,我为了熟悉 vuex用法,便在开始项目创建的时候勾选了vuex。这个项目中我把需要用到的vuex 单独抽离出来一个js文件进行使用。
assets 是我的存储静态资源的目录,但是我不建议直接使用img 元素的 src 属性直接引入,最好的做法就是通过vue语法中的reqruie 把他引入,作为一个变量绑定在src上,这样后期加载 图片的时候效率比较高;例如:
<template>;
<!--使用v-bind动态绑定-->
<img :src="image"/>
</template>
<script>
export default{
data(){
return{
image:require("@/assets/image.jpg");
}
}
}
</script>;
或者使用import引入
<template>
<!--使用v-bind动态绑定-->
<img :src="image"/>
</template>;
<script>
import img from "@/assets/image.jpg"
export default{
data(){
return{
image:img;
}
}
}
</script>
vue 语法使用的总结vue 的语法,尽量不要出现原生的 JavaScript,这些规则能够在绝大多数工程中改善可读性和开发体验。即使你违反了,代码还是能照常运行,但例外应该尽可能少且有合理的理由。HTML元素产生冲突,可以由一个单词或者多个单词构成。多个单词构成的时候可以使用连接符或者驼峰命名法。如:app-about
驼峰命名的时候主要要和vue-cli搭配,不然无法识别组件
AppAbout
data 必须是一个函数。**尽量不要使用对象(除了 new Vue 外的任何地方)。data的值必须是返回一个对象的函数。data(){
return{
value:"info",
}
}
vue的生命周期,很重要!很重要!很重要!我在这儿就只介绍项目中经常用到的生命周期函数。mountd 函数一般用于数据的请求,发送 axios请求,启动定时器,因为这时候data和methods中的数据已经被初始化了,而且已经挂载到页面上了,所以我们才可以调用methods中的方法给data中的数据赋值。beforeDestory函数,离开该组件前触发,这时候组件中的 data、methods、computed中的数据都是可用状态,一般用于清除一些数据,销毁一些资源。详见下图:
对于从服务端请求到的图片,我推荐使用图片懒加载。具体用法如下:
npm install vue-lazyload --save
2.main.js中引入全局使用
import VueLazyload from "vue-lazyload"
//自己映入加载时的图片和加载失败的图片
const loadingImg = require("./assets/img/loadingImg.gif")
const errorImage = require("./assets/img/errorImage.jpg")
Vue.use(VueLazyload, {
//加载时图片的展示高度
preLoad: 1,
error: errorImage,
loading: loadingImg,
attempt: 1
})
3.在img元素中使用v-lazy指令代替src绑定图片,建议加一个key,这个key可以是图片的地址,不然会出现页面刷新了,但是图片不刷新的情况,因为key可能会相同,但是页面不刷新。
npm包,可以在main.js中进行全局绑定。这样在各个组件中使用的时候便不需要单独引入了。例:使用了一个时间处理工具库import dayjs from "dayjs";
//在main.js文件中绑定dayjs
Vue.prototype.$dayjs = dayjs;
//在其他组件中使用
const time = new Date();
this.$dayjs(time).format("YYYY-MM-DD");
axios 请求,尽量使用 async 和 await来进行处理,代码结构比较清晰,当然你也可以使用.then和.catch来处理结果。此外,得到结果的时候进行解构赋值,这样你在使用数据的时候可以不用在对象.属性了。例: async findAllComments() {
let { data } = await this.$axios.post("/node/blog/findComment", {
id: this.blogData._id,
});
this.commentDatas = data.comments.reverse();
},
{
path: "/personal",
name: "Personal",
component: () => import("../components/resourcePage/ResourcePage.vue")
}
export default {
namespaced: true,
state: {
userInfo: {
userDate: "",
userIcon: "/vue_img/hot5.png",
userName: "",
userPass: "",
id: "",
}
},
actions: {
changeuserinfo(content, value) {
content.commit("CHANGEUSERINFO", value)
}
},
mutations: {
CHANGEUSERINFO(state, value) {
state.userInfo = value
}
}
}
import Vue from 'vue'
import Vuex from 'vuex'
import userInfo from "./moudleStore/userInfo"
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
userInfo
}
})
query或者params,params是动态路由。两者的区别是query传递的值在页面刷新后还存在,但是params中传递的数据会消失。示例://在router文件下的index.js中的写法,这样写直接可以使用props接收值,不在使用$router.query.indexof获取
{
path: "/detail",
name: "Detail",
component: () => import("../components/article/Detail.vue"),
props(route) {
return {
indexof: route.query.indexof
}
}
}
//组件中使用
<router-link
:to="{
name: 'Detail',
query: {
indexof: item._id,
},
}"
>{{ item.title }}</router-link>
//接收值
props: ["indexof"],

bug还是维护的时候,都比较方便。处理数据库中得到的数据的js 文件你可以放在 module 里边,处理业务逻辑的一些js文件也可以放在module里边,连接MongooDB数据库的文件放在单独在module底下新建一个目录进行统一管理,管理路由的文件放置在router目录下,app.js文件是你的启动文件,我们可以使用express框架建立一个服务。代码如下:const express = require("express");
const app = express();
const history = require("connect-history-api-fallback")
// 配置静态
app.use(express.static("./public"))
// 解析post请求数据
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
// 链接数据库
require("./module/mongoose/mongoose")
//引入session
app.use(require("./module/plugin_vue/session"))
// 设置博客界面的子路由 ---------前台展示界面路由的引入
app.use("/blog", require("./router/blogVue.js"))
//设置管理端界面的路由-------后台管理
app.use("/adminUser", require("./router/amdinUser"))
app.use(history)
app.listen("9001", () => {
console.log("9001端口启动成功");
})
/blog的子路由举例,这时候前端发送请求的时候,他的请求路径就是:https://localhost:9001/blog/getLinkconst express = require("express");
const router = express.Router();
//引入处理相应数据的函数
const { getTypeLink } = require("../module/admin-link/link");
router.post("/getLink", async (req, res) => {
let { value } = req.body;
let data = await getTypeLink(value);
res.send(data)
})
数据返回格式。例如使用上边的函数 getTypeLink函数返回数据后得到的结果://引入你需使用的MongoDB数据库里的集合
const dbLink = require("../mongoose/mongoLink");
const getTypeLink = async (val) => {
let data = await dbLink.find({ type: val });
let result = data;
if (data) return { code: 1, value: "查找成功", result }
return { code: 0, value: "查找失败" }
}
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/blog")
.then(() => {
console.log("数据库连接成功");
})
.catch(() => {
console.log("链接失败");
})
mongooDB数据库中创建集合的方法const mongoose = require("mongoose");
module.exports = mongoose.model(
"blog",
new mongoose.Schema(
{
title: {
type: String,
required: true
},
summary: String,
type: String,
content: String,
date: {
type: Date,
required: true
},
views: {
type: Number,
default: 6
},
pictureUrl: String,
property: String,
state: {
type: String,
default: "草稿"
}
},
{
versionKey: false
}
)
);
在以往的很长一段时间里,后端开发才是开发团队里的核心,前端开发往往仅由一小撮人甚至交给后端人员兼任。比如JSP开发,它是一个典型的前后端高耦合的技术案例,前后端代码放在一起写,各种繁琐的套模板。这种开发方式在以前互联网服务不那么繁荣,web化趋势还不那么明显的年代发挥着巨大作用。随着各种社会服务的信息化程度加深,前端需要展示的内容越来越复杂(比如淘宝页面),JSP这种套模板的技术(仅仅依靠html、css、js、jq等技术的堆积来完成一个复杂的页面展示也变得非常繁杂)再也无法高效的开发。**究其本质原因:前端开发没有像后端开发那样实现工程化、模块化、可复用化的思想。所以就会出现前后端开发不协调、效率低、扯皮的问题,这很不利于项目开发。因此项目管理者就想办法来解决这种问题,如何解决?→解耦。**在软件领域,任何复杂的问题面前,高内聚、低耦合这种原则几乎总是能见效。所以前后端分离开发出现了,把前端开发的责任从后端开发人员身上拿掉,给前端开发工程师一个单独的岗位和责任领域,将前端也工程化、模块化、项目化。这才是前后端分离开发最开始的来源。这些与vue、react框架没有什么关系,它们充其量只是一种具体实现方式而已。从本质上来看,前后端分离并不是一个技术问题,而是一个工程化考量和项目管理的问题。
前后端分离核心思想是前端HTML页面通过AJAX调用后端的API接口并使用JSON数据进行交互。
我这里以vue和node.js作为前端和服务端示例,其实不必太在意前后端使用的是什么技术,原理其实一样,不同点在于其配置,我们需要学习的是这样的开发模式和思维。
vue 项目中在配置文件 vue.config.js 中进行如下配置:就是进行一个代理
module.exports = {
devServer: {
proxy: {
"/node": {
target: 'https://127.0.0.1:9001',
ws: true,
changeOrigin: true,
pathRewrite: {
'^/node': ''
}
}
}
}
}
此后,使用前缀 /node 进行 axios 请求:
import axios from "axios";
export const addBlog = async (ruleform) => {
let { data } = await axios.post("/node/adminUser/addBlog", { data: ruleform });
return data;
}
服务端通过相应的接口接收数据:
const { addBlog } = require("../module/adminBlog/blog")
router.post("/addBlog", async (req, res) => {
let { data } = req.body;
let result = await addBlog(data)
res.send(result)
})
这便是最简单的前后端分离,然而在正式开发中,并不是如此简洁。这便要从软件开发的四大步说起:设计、开发、测试、部署,真正的前后端分离需要渗透到以上的每一步中。
mock(mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。)中模拟出来的,并不是从后端拿的;而后端开发仅提供一套接口,按照先前提供的评审好的接口约定来提供数据,这一套接口可以提供给很多的前端使用,比如web网``页、h5页面、app、微信小程序等。JSP时代前端html页面、css样式、js效果等都是由后台驱动,即前端都是塞到后端中,然后项目部署。当前端人员需要修改、发版本的时候就需要去求着后端人员帮忙)。前后端分离之后,就不再这样了,前后端发布上线可以完全独立,互相透明。这次项目部署的时候,我使用了前后端分离部署,感觉特别方便,尤其是在修改网页文件的时候,不需要考虑服务端。博客迁移声明:
后来随着个人写博客的一个需求,发现自己原有开发的博客网站满足不了我当下的需求,于是开始重构博客,后边感觉没必要浪费这个时间,应该把精力专注于博客写作和内容输出上,所以便果断放弃了以前开发的博客,通过一些流行博客框架进行搭建,因此,现在看到的博客站点可能和文章描述的博客站点是不一样的。