个人博客后台管理系统


博客后台管理系统背景介绍

  在学校的课程开设的影响下,对前端WEB开发有着浓厚的兴趣,于是在经过了对大学前两年专业知识的学习,并下定决心能运用所学知识进行自主网页开发。为此我在学习学校基础课程的同时,利用课外的空闲时间去探索前端开发领域,对前端开发技术一点点积累学习,最后将知识点进行整合运用,产生了开发个人博客项目的想法。该博客后台项目是本人在大二暑假实现。
    用到的技术栈:
      前端:Element-UI + Vue2.0 + Axois + Vue-Router + 第三方中间件 + ECharts
      后端:Node.js + Express框架
      数据库:MySQL
      项目版本控制工具: Git分布式版本控制系统


项目GitHub链接:个人博客后台管理系统,starred支持小白一下,以示鼓励。

一、项目介绍

1.1 登录

       用户登录使用了基于JWT中间件的token认证机制,进行用户信息的加密和解密。

// 导入配置文件
const secretKey = require('./config.js')

const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')

// 使用jsonwebtoken进行用户名的token字符串生成
const token = jwt.sign({ username: bodys.username }, secretKey, { expiresIn: '30s' });
// 导入express-jwt,用于后续的token解析
const expressJWT = require('express-jwt');
// 导入解析密钥
const secretKey = require('./config.js')
// 出了以/api开头的接口不用token认证,其余都需要
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))

// 使用错误中间件进行token过期的验证
app.use((err, req, res, next) => {
    // 捕获身份认证失败的错误
    if (err.name === 'UnauthorizedError') return res.send({
        status: 401,
        message: 'toke过期,身份验证失败'
    })
	// 其他未知错误
    res.send({
        status: 500,
        message: '服务错误'
    })
})

同时新增了在token认证机制下的用户持久化登录,每次用户请求数据时,请求头headers中的Authorization属性就自动携带用户的token值,服务器获取到token后进行有效时间的判断并解析,token在该有效时间能即可成功请求对应的接口数据。

// axios请求拦截器的使用
request.interceptors.request.use(config => {
    // 请求头携带token值
    config.headers.Authorization = window.localStorage.getItem('token');
    // 将配置完成的config对象返回出去 如果不返回 请求则不会进行
    return config;
}, err => {
    // 返回使用Promise封装的错误信息
    return Promise.reject(err);
});


// axios响应拦截器的使用
request.interceptors.response.use(response => {

    // 用户登录持久化
    const status = response.data.status;
    // 接口数据状态码返回的是401时代表用户需要进行权限认证
    if (status === 401) {
        // 用户重新登陆信息提示
        MessageBox.alert(
            '登录状态已过期, 您可以继续留在该页面, 或者重新登陆',
            '系统提示', {
            confirmButtonText: '重新登录',
            type: 'warning',
            callback: action => {
                // 将页面重定向为登录页面
                location.href = '/';
            }
        }
        )
        // 清除用户过期的token
        window.localStorage.removeItem('token');
    }

    // 将响应信息返回
    return response;
}, err => {
    // 返回使用Promise封装的错误信息
    return new Promise(err);
})

管理员登录页面
当我们的token过期时,页面显示用户信息如下(我们手动修改一下有效的token)。可以看到,jwt认证机制已成功实现。
在这里插入图片描述

1.2 文章管理页

在这里插入图片描述
在这里插入图片描述

1.3 撰写文章页

在这里插入图片描述
在这里插入图片描述

1.4 文章分类页

在这里插入图片描述

1.5 用户管理页

在这里插入图片描述
在这里插入图片描述

1.6 管理员添加页

在这里插入图片描述

1.7 博主个人信息页

在这里插入图片描述
在这里插入图片描述

二、部分代码

2.1 登录

代码如下:

<template>
    <div id="login-container">
        <!-- 使用原生的Div+Css进行登录页面的样式设计 -->
        <div class="login">
            <form action="" style="height: 100%" method="post">
                <!-- 整个的登录框内容 -->
                <div class="login-box">
                    <!-- 登录框标题内容 -->
                    <div class="login-text">
                        <h3>个人博客后台管理</h3>
                    </div>
                    <!-- 登录框用户名内容 -->
                    <div class="login-username">
                        <input type="text" v-model="username" name="username" @blur="login" placeholder="请输入用户名">
                        <span class="info1" v-if="context === 'usn'"><strong>{{ info1 }}</strong></span>
                        <span class="info1" v-if="context === 'isnull'"><strong>{{ info3 }}</strong></span>
                    </div>
                    <!-- 登录框密码内容 -->
                    <div class="login-password">
                        <input type="password" v-model="password" name="passowrd" placeholder="请输入用户密码">
                        <span class="info2" v-if="context === 'psw'"><strong>{{ info2 }}</strong></span>
                    </div>
                    <!-- 登录框提交内容 -->
                    <div class="login-submit">
                        <router-link :to="url">
                            <button type="submit" id="submit" @click="login">登录</button>
                        </router-link>
                    </div>
                </div>
            </form>
        </div>
    </div>
</template>

2.2 文章管理

代码如下:

<template>
    <div id="classify-container">
        <div id="search">
            <input type="text" placeholder="输入副分类进行搜索" v-model="searchMsg" @keyup.enter="search" />
            <el-button type="primary" size="mini" @click="search">搜索文章</el-button>
        </div>
        <el-table :data="currentList" style="width: 100%">
            <!-- 文章ID数据列 -->
            <el-table-column label="ID" width="180">
                <template slot-scope="scope">
                    <span style="margin-left: 10px">{{ scope.row.id }}</span>
                </template>
            </el-table-column>
            <!-- 文章所属分类数据列 -->
            <el-table-column label="分类" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-collection-tag"></i>
                    <span style="margin-left: 10px">{{ scope.row.title }}</span>
                </template>
            </el-table-column>
            <!-- 文章所属副分类数据列 -->
            <el-table-column label="副分类" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-time"></i>
                    <span style="margin-left: 10px">{{ scope.row.subtitle }}</span>
                </template>
            </el-table-column>
            <!-- 文章标题内容数据列 -->
            <el-table-column label="标题内容" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-document-copy"></i>
                    <span style="margin-left: 10px">{{ scope.row.md_content }}</span>
                </template>
            </el-table-column>
            <!-- 文章创建日期数据列 -->
            <el-table-column label="日期" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-date"></i>
                    <span style="margin-left: 10px">{{ scope.row.creatdate }}</span>
                </template>
            </el-table-column>
            <!-- 文章操作列 -->
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <!-- 文章信息编辑模态框 -->
        <el-dialog title="文章信息修改" :visible.sync="dialogFormVisible">
            <el-form :model="form">
                <!-- 文章的所属分类 -->
                <el-form-item label="分类" :label-width="formLabelWidth">
                    <el-input v-model="form.title" autocomplete="off"></el-input>
                </el-form-item>
                <!-- 文章的所属副分类 -->
                <el-form-item label="副分类" :label-width="formLabelWidth">
                    <el-input v-model="form.subtitle" autocomplete="off"></el-input>
                </el-form-item>
                <!-- 文章的标题内容 -->
                <el-form-item label="标题内容" :label-width="formLabelWidth">
                    <el-input v-model="form.md_content" autocomplete="off"></el-input>
                </el-form-item>
            </el-form>
            <!-- 模态框的取消和确定按钮 -->
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="primary" @click="close">确 定</el-button>
            </div>
        </el-dialog>

        <!-- 页面上下页操作按钮列 -->
        <div class="operations">
            <!-- 上一页操作按钮 -->
            <el-button type="primary" icon="el-icon-arrow-left" size="mini" @click="pre"></el-button>
            <el-button type="primary" size="mini" plain>
                {{ page }} / {{ pages }}
            </el-button>
            <el-button type="primary" size="mini" plain>
                总{{ allPage}}条
            </el-button>
            <!-- 下一页操作按钮 -->
            <el-button type="primary" size="mini" @click="next" icon="el-icon-arrow-right"></el-button>
        </div>
    </div>
</template>

2.3 文章撰写

代码如下:

<template>
    <div class="container">
        <el-form ref="form" :model="sizeForm" label-width="80px" size="mini" style="padding: 5%">
            <el-form-item label="主标题">
                <el-input v-model="sizeForm.title"></el-input>
            </el-form-item>
            <el-form-item label="副标题">
                <el-select v-model="sizeForm.subtitle" placeholder="请选择副标题类型">
                    <el-option label="JavaWeb笔记" value="JavaWeb笔记">JavaWeb笔记</el-option>
                    <el-option label="Java笔记" value="Java笔记"></el-option>
                    <el-option label="Vue笔记" value="Vue笔记"></el-option>
                    <el-option label="人生哲学" value="人生哲学"></el-option>
                    <el-option label="体育" value="体育"></el-option>
                    <el-option label="散文欣赏" value="散文欣赏"></el-option>
                    <el-option label="数据结构" value="数据结构"></el-option>
                    <el-option label="生活点滴" value="生活点滴"></el-option>
                    <el-option label="竞赛" value="竞赛"></el-option>
                    <el-option label="算法笔记" value="算法笔记"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="标题内容">
                <el-input v-model="sizeForm.md_content" size="small"></el-input>
            </el-form-item>
            <el-form-item label="是否置顶">
                <el-radio-group v-model="sizeForm.resource" size="medium">
                    <el-radio border label=""></el-radio>
                    <el-radio border label=""></el-radio>
                </el-radio-group>
            </el-form-item>
            <el-form-item label="文章内容">
                <el-input type="textarea" :rows="6" placeholder="请输入内容" v-model="sizeForm.content">
                </el-input>
            </el-form-item>
            <el-form-item label="创建时间">
                <el-col :span="11">
                    <el-date-picker type="date" placeholder="选择日期" v-model="sizeForm.date1" style="width: 100%;">
                    </el-date-picker>
                </el-col>
                <el-col class="line" :span="2">-</el-col>
                <el-col :span="11">
                    <el-time-picker placeholder="选择时间" v-model="sizeForm.date2" style="width: 100%;"></el-time-picker>
                </el-col>
            </el-form-item>
            <el-form-item size="large">
                <el-button type="primary" @click="onSubmit">立即撰写</el-button>
                <el-button>取消</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

2.4 文章分类

<template>
    <div id="classify-container" style="height: 100%; background: white">
        <div class="add-classify">
            <h3>添加</h3>
            <div>
                <div style="font-size: 16px; font-weight:600">类别:</div>
                <input type="text" v-model="classification1" placeholder="二级类别" />
            </div>
            <div>
                <div style="font-size: 16px; font-weight:600">所属类别:</div>
                <input type="text" v-model="classification2" placeholder="一级类别" />
            </div>
            <div style="float: right">
                <el-button type="primary" size="mini" v-on:click="add">点击添加</el-button>
            </div>
        </div>
        <div style="float: right; width: 70%">
            <h3>管理</h3>
            <el-table :data="tableData" style="width: 100%" border>
                <el-table-column label="分类名称" width="230">
                    <template slot-scope="scope">
                        <i class="el-icon-time"></i>
                        <span style="margin-left: 10px">{{ scope.row.tname }}</span>
                    </template>
                </el-table-column>
                <el-table-column label="文章数" width="180">
                    <template slot-scope="scope">
                        <el-popover trigger="hover" placement="top">
                            <p>分类名称: {{ scope.row.tname }}</p>
                            <p>数量: {{ scope.row.number }}</p>
                            <div slot="reference" class="name-wrapper">
                                <el-tag size="medium">{{ scope.row.number }}</el-tag>
                            </div>
                        </el-popover>
                    </template>
                </el-table-column>
                <el-table-column label="操作">
                    <template slot-scope="scope">
                        <el-button type="danger" size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                    </template>
                </el-table-column>
            </el-table>
            <!-- 页面上下页操作按钮列 -->
            <div class="operations">
                <el-button type="primary" size="mini" @click="pre">
                    <i class="el-icon-arrow-left"></i>
                </el-button>
                <el-button type="primary" size="mini" plain>
                    {{ current }} / {{ pages }}
                </el-button>
                <el-button type="primary" size="mini" plain>
                    总{{ allPage }}条
                </el-button>
                <el-button type="primary" size="mini" @click="next">
                    <i class="el-icon-arrow-right"></i>
                </el-button>

            </div>
        </div>
    </div>
</template>

代码如下:

2.5 管理员添加

代码如下:

<template>
    <div id="register-container">
        <div id="app">
            <!-- Element-UI表单标签 -->
            <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px"
                class="demo-ruleForm">
                <!-- 用户名输入框 -->
                <el-form-item label="用户名:" prop="username">
                    <el-input type="text" v-model="ruleForm.username" autocomplete="off" id="username" @blur="Check">
                    </el-input>
                    <span class="information">用户已经存在!!</span>
                </el-form-item>
                <!-- 密码输入框 -->
                <el-form-item label="密码:" prop="pass">
                    <el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
                </el-form-item>
                <!-- 确认密码输入框 -->
                <el-form-item label="确认密码:" prop="checkPass">
                    <el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
                </el-form-item>
                <!-- 年龄输入框 -->
                <el-form-item label="身份:" prop="position">
                    <el-input v-model="ruleForm.position"></el-input>
                </el-form-item>
                <!-- 地址输入框 -->
                <el-form-item label="住址:" prop="address">
                    <el-input v-model="ruleForm.address"></el-input>
                </el-form-item>
                <!-- 操作按钮 -->
                <el-form-item>
                    <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
                    <el-button type="danger" @click="resetForm('ruleForm')">重置</el-button>
                </el-form-item>
            </el-form>
        </div>
    </div>
</template>

2.6 管理员信息

代码如下:

<template>
    <!-- 设置对应的唯一的最外层标签,进行包裹 -->
    <div>
        <el-table :data="userList" style="width: 100%">
            <!-- ID数据列 -->
            <el-table-column label="ID" width="180">
                <template slot-scope="scope">
                    <span style="margin-left: 10px">{{ scope.row.id }}</span>
                </template>
            </el-table-column>
            <!-- 管理员数据列 -->
            <el-table-column label="用户名" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-user"></i>
                    <span style="margin-left: 10px">{{ scope.row.username }}</span>
                </template>
            </el-table-column>
            <!-- 管理员登录密码数据列 -->
            <el-table-column label="密码" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-lock"></i>
                    <span style="margin-left: 10px">{{ scope.row.password }}</span>
                </template>
            </el-table-column>
            <!-- 管理员职业数据列 -->
            <el-table-column label="职位" width="180">
                <template slot-scope="scope">
                    <i class="el-icon-school"></i>
                    <span style="margin-left: 10px">{{ scope.row.position }}</span>
                </template>
            </el-table-column>
            <!-- 管理员部分信息数据列 -->
            <el-table-column label="用户名" width="180">
                <template slot-scope="scope">
                    <el-popover trigger="hover" placement="top">
                        <p>职位: {{ scope.row.position }}</p>
                        <p>住址: {{ scope.row.address }}</p>
                        <div slot="reference" class="name-wrapper">
                            <el-tag size="medium">{{ scope.row.username }}</el-tag>
                        </div>
                    </el-popover>
                </template>
            </el-table-column>
            <!-- 管理员操作列 -->
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>

        <!-- 模态框 -->
        <el-dialog title="管理信息修改" :visible.sync="dialogFormVisible">
            <el-form :model="form">
                <el-form-item label="用户名:" :label-width="formLabelWidth">
                    <el-input v-model="form.username" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="用户密码:" :label-width="formLabelWidth">
                    <el-input v-model="form.password" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="职位:" :label-width="formLabelWidth">
                    <el-input v-model="form.position" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="地址:" :label-width="formLabelWidth">
                    <el-input v-model="form.address" autocomplete="off"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="primary" @click="close">确 定</el-button>
            </div>
        </el-dialog>
    </div>
</template>

2.7 博主个人信息

代码如下:

<template>
    <div class="manager-container">
        <!-- 个人信息展示布局,这里使用的是原生的DIV+CSS布局 -->
        <div class="manager-context">
            <div class="content">
                <h4>个人主页</h4>
                <el-button type="primary" style="height:35px; margin-top:1%; line-height:9px"
                    @click="dialogFormVisible = true">
                    修改信息
                </el-button>
            </div>
            <div class="content1">
                <span>头像:</span>
                <img src="../assets/image6.webp" alt="blank">
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px">
                <div>工号: <span>{{ blogerList.id }} </span></div>
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px; clear:both">
                <div>姓名:<span>{{ blogerList.name }}</span></div>
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px">
                <div>年龄:<span>{{ blogerList.age }}</span></div>
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px">
                <div>电话:<span>{{ blogerList.tel }}</span></div>
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px">
                <div>学校:<span>{{ blogerList.school }}</span></div>
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px">
                <div>地址:<span>{{ blogerList.address }}</span></div>
            </div>
            <div class="content2" style="min-height: 60px; line-height: 60px">
                <div>上次修改时间:<span>{{ blogerList.edit }}</span></div>
            </div>
            <!-- 修改信息模态框,使用Element-Ui实现 -->
            <el-dialog title="个人信息修改" :visible.sync="dialogFormVisible" width="65%">
                <el-form :model="form">
                    <el-form-item label="年龄:" :label-width="formLabelWidth">
                        <el-input v-model="form.age" autocomplete="on"></el-input>
                    </el-form-item>
                    <el-form-item label="电话:" :label-width="formLabelWidth">
                        <el-input v-model="form.tel" autocomplete="on"></el-input>
                    </el-form-item>
                    <el-form-item label="学校:" :label-width="formLabelWidth">
                        <el-input v-model="form.school" autocomplete="on"></el-input>
                    </el-form-item>
                    <el-form-item label="地址:" :label-width="formLabelWidth">
                        <el-input v-model="form.address" autocomplete="on"></el-input>
                    </el-form-item>
                </el-form>
                <!-- 页脚处的按钮,进行信息的取消或者确定 -->
                <div slot="footer" class="dialog-footer">
                    <el-button @click="cancel">取 消</el-button>
                    <el-button type="primary" @click="confirm">确 定</el-button>
                </div>
            </el-dialog>
        </div>
    </div>
</template>

三 项目核心介绍

3.1 Vue2.0

  Vue作为当前最主流的前端框架,给开发者提供了一套简洁方便的代码规范,在本项目中就是以Vue为核心框架进行网页与数据的双向绑定从而实现MVVM模式,大大减少了使用原生代码开发的时间,提高了开发人员的工作效率。

3.2 Axois

  Axios时目前最流行的ajax封装库之一,用于很方便地实现ajax请求的发送。在项目中ViewView-Model之间的数据交互均由使用Axois发起的ajax请求实现,具体的实现过程原理如下:在Express框架中挂载对应的路由,网页标签进行事件绑定,当用户触发了事件执行的条件进行ajax异步请求再由路由进行数据库MySQL的数据请求通过Response向网页提供得到的数据,并渲染到页面。
  同时,作者将axios进行了简单的二次封装,以此提高代码的可维护性。

/ 创建axios实例
const request = axios.create({
    // 请求地址的公共部分
    baseURL: 'http://localhost:8000',
    // 请求超时时间
    timeout: 3000,
    // 请求头中的Content-Type
    headers: {
        ContentType: 'application/json'
    }
});

// axios请求拦截器的使用
request.interceptors.request.use(config => {
    // 请求头携带token值
    config.headers.Authorization = window.localStorage.getItem('token');
    // 将配置完成的config对象返回出去 如果不返回 请求则不会进行
    return config;
}, err => {
    // 返回使用Promise封装的错误信息
    return Promise.reject(err);
});


// axios响应拦截器的使用
request.interceptors.response.use(response => {

    // 用户登录持久化
    const status = response.data.status;
    // 接口数据状态码返回的是401时代表用户需要进行权限认证
    if (status === 401) {
        // 用户重新登陆信息提示
        MessageBox.alert(
            '登录状态已过期, 您可以继续留在该页面, 或者重新登陆',
            '系统提示', {
            confirmButtonText: '重新登录',
            type: 'warning',
            callback: action => {
                // 将页面重定向为登录页面
                location.href = '/';
            }
        }
        )
        // 清除用户过期的token
        window.localStorage.removeItem('token');
    }

    // 将响应信息返回
    return response;
}, err => {
    // 返回使用Promise封装的错误信息
    return new Promise(err);
})

3.2.1 部分代码展示

// 使用axois发送ajax请求,并将行es6进行解构接收数据
            const { data: res } = await this.$http.get("/article/add", {
                params: {
                    'title': this.sizeForm.title,
                    'subtitle': this.sizeForm.subtitle,
                    'md_content': this.sizeForm.md_content,
                    'creatdate': date
                }
            })
            // 后端返回的结果字符串判断
            if (res === 'success') {
                this.$message({
                    message: '添加成功!!',
                    type: 'success'
                })
                // 路由进行编程式跳转
                this.$router.replace('/layout/article1/' + window.localStorage.getItem('username'))
            } else {
                this.$message.error('添加失败!!')
            }
// (二十二) 创建添加文章的路由,进行article表的数据更新
app.get('/article/add', (req, res) => {
    // 22.1 获取url中的查询参数
    const params = req.query
    // 22.2 设置对应的sql语句
    const sql = "insert into article values(null, ?, ?, ?, ?, 1, 1, 1)"
    // 22.3 执行对应的sql语句
    conn.query(sql, [params.title, params.subtitle, params.md_content, params.creatdate], (err, results) => {
        // 22.3.1 倘若执行过程中出现错误,将错误信息打印并直接停止后续代码的执行
        if (err) {
            console.log(err.message);
            return
        }
        // 22.3.2 执行成功使用res.send()方法向客户端响应对应的字符串
        if (results.affectedRows > 0) {
            res.send('success')
        }
    })
})

3.3 Vue-Router

  本项目使用Vue-cli单页面开发模式,App.vue作为根组件,其他vue组件之间的跳转由Vue-Router插件提供技术实现,即相当于Html中的a标签进行页面间的跳转。

3.3.1 部分代码展示

// (三) 创建对应的Router插件的实例对象
const router = new Router({
    // 3.1 路由规则
    routes: [
        // 3.1.1 当用户输入的是'/'时,页面重定向到管理员登录页面
        { path: '/administrator/login', component: Login },
        { path: '/', redirect: '/administrator/login' },
        // 3.1.2 注意下面的props属性,用来使用路由中的动态id的传输(倘若子规则开启,父规则也需要开启)
        {
            path: '/layout', component: Layout, children: [
                { path: 'article1/:username', component: Article1 },
                { path: 'userInfo', component: UserInfo },
                { path: 'addAdmin', component: AddAdmin },
                { path: 'article2', component: Article2 },
                { path: 'classify', component: Classify },
                { path: 'manager', component: Manager },
                { path: 'userInfoBack', component: UserInfoBack}
            ]
        },
    ]
})

3.4 Element-UI

  第一次使用现有的框架进行网页的开发,网页的美化展示效果让用户舒适的用时,不缺乏实用的功能。由于是第一次使用开发过程基本是以查阅文档进行开发为主,希望后续自己可以对Element-UI的使用运用更佳运用于心。

3.4.1 Element-UI在Vue中的引入方式

import router from './router'
import axios from 'axios'
import jquery from "jquery";

Vue.prototype.$ = jquery;

Vue.config.productionTip = false

axios.defaults.baseURL = "http://localhost:8000"
Vue.prototype.$http = axios


import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
 
Vue.use(ElementUI)

3.5 数据可视化-ECharts

  为了让用户对数据查看有更直观的感受,因此使用ECharts对部分数据进行饼状图的形式进行展示。

3.5.1 部分代码展示

etEchartData() {
            const chart = this.$refs.datas
            if (chart) {
                const myChart = this.$echarts.init(document.getElementById('datas'))
                const option = {
                    title: {
                        text: '统计',
                        subtext: '文章数',
                        left: 'center'
                    },
                    tooltip: {
                        trigger: 'item'
                    },
                    legend: {
                        orient: 'vertical',
                        left: 'left'
                    },
                    series: [
                        {
                            name: 'Access From',
                            type: 'pie',
                            radius: '50%',
                            data: [
                                { value: 10, name: 'JavaWeb笔记' },
                                { value: 2, name: 'Java笔记' },
                                { value: 1, name: 'Vue笔记' },
                                { value: 1, name: '人生哲学' },
                                { value: 1, name: '体育' },
                                { value: 1, name: '散文欣赏' },
                                { value: 1, name: '数据结构' },
                                { value: 13, name: '生活点滴' },
                                { value: 1, name: '竞赛' },
                                { value: 2, name: '算法笔记' }
                            ],
                            emphasis: {
                                itemStyle: {
                                    shadowBlur: 10,
                                    shadowOffsetX: 0,
                                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                                }
                            }
                        }
                    ]
                };
                myChart.setOption(option)
                window.addEventListener("resize", function () {
                    myChart.resize()
                })
            }
            this.$on('hook:destroyed', () => {
                window.removeEventListener("resize", function () {
                    myChart.resize();
                });
            })
        }

个人总结

  在学校课程开设中,慢慢对前端产生兴趣,这次的个人博客系统自己做前端和后端,由于学校课程没有需要用的技术栈,所以自学了需要的技术栈,Node.js也是自己先过了一遍再进行Vue2.0的学习,两大技术支持学习完成后就进行项目的部署,在开发中达到使用巩固。这次的项目让我提升了独立自主学习,解决困难的能力。需要的同学可以私聊我拿源码,一起交流学习,一起进步。
  自知自身技术的局限性,在后续的学习中将不断学习更多前端知识,并在本项目基础上不断改进完善。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值