Vue实现Markdown

沙漠真有鱼 2024-08-28 15:33:02 阅读 84

前言:本文将介绍如何使用Vue和SpringBoot实现一个Markdown编辑器,其中Vue用于前端,SpringBoot用于后端,实现数据存储和接口调用。

项目背景

Markdown是一种轻量级的标记语言,用于简化文本编辑,最初由John Gruber于2004年创建,随着GitHub等开源平台的兴起,被广泛应用于编写技术博客、文档等场景之中。

Vue是一种流行的JavaScript框架,用于构建交互式的用户界面,在前端开发中被广泛应用。

SpringBoot是一种基于Java语言的开源框架,用于创建微服务、RESTful API等后端应用程序。

本项目将结合Vue和SpringBoot,实现一个Markdown编辑器,旨在探索Vue与SpringBoot在前后端开发中的应用。

技术栈

前端:

VueVue RouterVuexaxiosmarkedhighlight.js

后端:

SpringBoot 2.5.1MyBatisMySQL

功能列表

用户注册/登录Markdown编辑器支持文档上传、下载支持文档的增删改查

数据库设计

用户表

<code>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在前后端开发中的应用及其基本原理。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。