Vue实现Markdown
本文介绍了如何使用Vue和SpringBoot实现一个Markdown编辑器,涉及了前后端开发中的状态管理、路由设计、API封装、Markdown解析和数据库映射等方面内容。通过本项目,读者可以掌握Vue和SpringBoot在前后端开发中的应用及其基本原理。
前言:本文将介绍如何使用Vue和SpringBoot实现一个Markdown编辑器,其中Vue用于前端,SpringBoot用于后端,实现数据存储和接口调用。
项目背景
Markdown是一种轻量级的标记语言,用于简化文本编辑,最初由John Gruber于2004年创建,随着GitHub等开源平台的兴起,被广泛应用于编写技术博客、文档等场景之中。
Vue是一种流行的JavaScript框架,用于构建交互式的用户界面,在前端开发中被广泛应用。
SpringBoot是一种基于Java语言的开源框架,用于创建微服务、RESTful API等后端应用程序。
本项目将结合Vue和SpringBoot,实现一个Markdown编辑器,旨在探索Vue与SpringBoot在前后端开发中的应用。
技术栈
前端:
- Vue
- Vue Router
- Vuex
- axios
- marked
- highlight.js
后端:
- SpringBoot 2.5.1
- MyBatis
- MySQL
功能列表
- 用户注册/登录
- Markdown编辑器
- 支持文档上传、下载
- 支持文档的增删改查
数据库设计
用户表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(16) NOT NULL DEFAULT '',
`password` varchar(32) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
文档表
CREATE TABLE `document` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`title` varchar(255) NOT NULL DEFAULT '',
`content` text,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
CONSTRAINT `document_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
前端实现
前端代码结构如下:
.
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── api
│ ├── assets
│ ├── components
│ ├── router
│ ├── store
│ ├── utils
│ └── views
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── babel.config.js
├── package-lock.json
└── package.json
路由设计
const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue')
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue')
},
{
path: '/register',
name: 'Register',
component: () => import('@/views/Register.vue')
},
{
path: '/editor',
name: 'Editor',
component: () => import('@/views/Editor.vue'),
meta: {
requireAuth: true
}
},
{
path: '/document/:id',
name: 'Document',
component: () => import('@/views/Document.vue'),
meta: {
requireAuth: true
}
},
{
path: '*',
name: 'NotFound',
component: () => import('@/views/NotFound.vue')
}
]
状态管理
采用Vuex进行状态管理,主要存储用户登录信息和文档列表。
组件设计
Login(登录)
包括用户名和密码的输入框以及登录按钮。
Register(注册)
包括用户名、密码、确认密码的输入框和注册按钮。
Nav(导航栏)
包括LOGO、文档列表和个人信息按钮,可跳转到编辑器和个人中心页面。
Editor(编辑器)
包括文档标题和Markdown编辑器,可保存为草稿或发布为文章。
Document(文档详情)
展示文档的标题和内容,可进行编辑和删除。
NotFound(404页面)
展示页面不存在的提示信息。
封装API
使用axios封装了后台API,包括用户注册/登录、文档相关操作等。
import axios from 'axios'
const API_BASE_URL = 'http://localhost:8080/api'
export const register = (username, password) =>
axios.post(`${API_BASE_URL}/register`, { username, password })
export const login = (username, password) =>
axios.post(`${API_BASE_URL}/login`, { username, password })
export const logout = () => axios.post(`${API_BASE_URL}/logout`)
export const createDocument = (title, content) =>
axios.post(`${API_BASE_URL}/documents`, { title, content })
export const updateDocument = (id, title, content) =>
axios.put(`${API_BASE_URL}/documents/${id}`, { title, content })
export const deleteDocument = (id) => axios.delete(`${API_BASE_URL}/documents/${id}`)
export const getDocument = (id) => axios.get(`${API_BASE_URL}/documents/${id}`)
export const getDocuments = () => axios.get(`${API_BASE_URL}/documents`)
Markdown解析
使用marked.js和highlight.js解析Markdown文本和代码块,提高用户的阅读体验。
import marked from 'marked'
import hljs from 'highlight.js/lib/core'
marked.setOptions({
highlight: (code, lang) => {
if (lang && hljs.getLanguage(lang)) {
return hljs.highlight(lang, code).value
}
return hljs.highlightAuto(code).value
}
})
后端实现
后端代码结构如下:
.
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── controller
│ │ │ ├── dto
│ │ │ ├── interceptor
│ │ │ ├── mapper
│ │ │ ├── model
│ │ │ ├── security
│ │ │ ├── service
│ │ │ ├── util
│ │ │ └── DemoApplication.java
│ │ └── resources
│ │ ├── application-dev.yml
│ │ ├── application-prod.yml
│ │ ├── application.yml
│ │ ├── mapper
│ │ ├── static
│ │ ├── templates
│ │ └── logback-spring.xml
│ ├── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── demo
│ │ └── DemoApplicationTests.java
│ ├── .gitignore
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── README.md
数据库连接配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.example.demo.model
安全配置
通过Spring Security进行登录验证。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/register", "/api/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/api/login").permitAll()
.and()
.logout().permitAll().logoutUrl("/api/logout").logoutSuccessUrl("/api/login");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
数据库映射
使用MyBatis进行数据库映射。
@Mapper
public interface UserMapper {
@Insert("INSERT INTO user(username, password, create_time, update_time) " +
"VALUES(#{username}, #{password}, #{createTime}, #{updateTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Select("SELECT * FROM user WHERE username = #{username}")
User findByUsername(String username);
}
@Mapper
public interface DocumentMapper {
@Insert("INSERT INTO document(user_id, title, content, create_time, update_time) " +
"VALUES(#{userId}, #{title}, #{content}, #{createTime}, #{updateTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(Document document);
@Update("UPDATE document SET title = #{title}, content = #{content}, update_time = #{updateTime} WHERE id = #{id}")
int update(Document document);
@Delete("DELETE FROM document WHERE id = #{id}")
int delete(int id);
@Select("SELECT * FROM document WHERE id = #{id}")
Document findById(int id);
@Select("SELECT * FROM document WHERE user_id = #{userId}")
List<Document> findByUserId(int userId);
}
RESTful API
后端提供了以下API接口:
- /register(POST):注册新用户
- /login(POST):用户登录
- /logout(POST):用户退出登录
- /documents(POST):创建新文档
- /documents/:id(PUT):更新文档
- /documents/:id(DELETE):删除文档
- /documents/:id(GET):获取指定ID文档
- /documents(GET):获取所有文档
总结
本文介绍了如何使用Vue和SpringBoot实现一个Markdown编辑器,涉及了前后端开发中的状态管理、路由设计、API封装、Markdown解析和数据库映射等方面内容。通过本项目,读者可以掌握Vue和SpringBoot在前后端开发中的应用及其基本原理。
更多推荐
所有评论(0)