VUE3
一、项目初始化
- vite创建vue3项目
npm init vite@latest 项目名 -- --template vue-ts
- 启动项目
cd 项目名
npm install
npm run dev
vue3生命周期函数:
-
setup():开始创建组件之前,在
beforeCreate
和created
之前执行,创建的是data
和method
-
onBeforeMount() : 组件挂载到节点上之前执行的函数
-
onMounted() : 组件挂载完成后执行的函数
-
onBeforeUpdate(): 组件更新之前执行的函数
-
onUpdated(): 组件更新完成之后执行的函数
-
onBeforeUnmount(): 组件卸载之前执行的函数
-
onUnmounted(): 组件卸载完成后执行的函数
-
onActivated(): 被包含在 中的组件,会多出两个生命周期钩子函数,被激活时执行
-
onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行
-
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数
二、安装相关依赖并配置
vite
- 安装
@types/node
npm install @types/node -D
// vite.config.ts
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import * as path from "path"
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.join(__dirname, 'src'),
"@assets": path.join(__dirname, "src/assets"),
"@components": path.join(__dirname, "src/components"),
"@views": path.join(__dirname, "src/views"),
"@utils": path.join(__dirname, "src/utils")
}
},
server: {
host: '127.0.0.1',
port: 3000,
open: true,
proxy: {
'/api': {
target: '你的服务器地址',
changeOrigin: true,
rewrite: (path:string) => path.replace(/^\/api/, '')
}
}
}
});
{
"script": {
"build": "vue-tsc --noEmit --skipLibCheck && vite build"
}
}
typescript
//在tsconfig.json中添加以下配置
{
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
// 解决打包报错
"skipLibCheck": true,
"suppressImplicitAnyIndexErrors": true,
"baseUrl": ".",
"paths": {
"@": [
"./src"
],
"@/*": [
"./src/*"
]
},
"exclude": [
"node_modules"
]
}
eslint
- 安装
npm install eslint eslint-plugin-vue -D
- 新建配置文件
.eslintrc.js
// .eslintrc.js
module.exports = {
root: true,
parserOptions: {
sourceType: "module"
},
parser: "vue-eslint-parser",
extends: [
'plugin:vue/vue3-essential',
'plugin:vue/vue3-strongly-recommended',
'plugin:vue/vue3-recommended'
],
env: {
browser: true,
node: true,
es6: true
},
rules: {
'no-console': 'off',
'comma-dangle': [2, 'never'] // 禁止使用拖尾符号
}
}
global.scss
- 新建
src\assets\css\global.scss
样式文件
/*全局公共样式表*/
html, body, #app {
margin: 0;
padding: 0;
height: 100%;
a {
text-decoration: none;
color: #333;
}
ul, li {
list-style: none;
}
}
/*设置滚动条样式*/
::-webkit-scrollbar {
width: 5px;
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track {
border-radius: 10px;
background-color: rgba(0, 0, 0, 0.1);
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(26, 25, 25, 0.3);
background-color: rgba(0, 0, 0, 0.1);
}
/*设置进度条颜色 不配置时为默认颜色*/
#nprogress .bar {
/*background: rgba(41, 236, 127, 0.5) !important;*/
}
- 使用样式
// App.vue
<style>
@import "assets/style/global";
</style>
animate.css
- 安装
npm install animate.css --save
- 使用
@import 'animate.css';
<h1 class="animate__animated animate__bounce">An animated element</h1>
reset.css
- 安装
npm install reset.css --save
- 使用
// App.vue
<style>
@import "reset.css";
</style>
less/sass
- 安装
less
npm install less less-loader -D
sass
npm install sass sass-loader -D
- 使用
<style scoped lang="less">
</style>
或者
<style scoped lang="sass">
</style>
element plus
官网:Element Plus
组件:组件使用
- 安装
npm install element-plus --save
完整引用
- 配置文件
// src/plugins/element-plus.ts
import {App} from 'vue'
import ElementPlus from "element-plus"
import 'element-plus/dist/index.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
import * as Icons from '@element-plus/icons-vue'
export default {
install(app: App) {
app.use(ElementPlus, {
locale,
size: 'small' || 'middle'
})
// 循环遍历所有图标(全局注册)
Object.keys(Icons).forEach((key: string) => {
app.component(key, Icons[key as keyof typeof Icons]);
})
}
}
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
import ElementPlus from "./plugins/element-plus";
const app = createApp(App)
app.use(ElementPlus)
.mount('#app')
按需引用
自动导入(推荐)
- 安装
npm install unplugin-vue-components unplugin-auto-import -D
- 配置
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
手动引入
- 安装
npm install unplugin-element-plus --save
- 配置
// vite.config.ts
import ElementPlus from 'unplugin-element-plus/vite'
export default {
plugins: [ElementPlus()],
}
- 使用
<template>
<el-button type="primary">测试</el-button>
</template>
<script setup lang="ts">
import { ElButton } from 'element-plus'
</script>
图标使用
- 安装
npm install @element-plus/icons-vue
- 单独引用
<template>
<div>
<el-icon :size="size" :color="color">
<edit />
</el-icon>
<!-- Or use it independently without derive attributes from parent -->
<edit />
</div>
</template>
<script setup lang="ts">
import {Edit} from '@element-plus/icons-vue'
</script>
- 动态引用(推荐)
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as Icons from '@element-plus/icons-vue'
const app = createApp(App);
app.use(ElementPlus)
.mount('#app')
// 循环遍历所有图标(全局注册)
Object.keys(Icons).forEach((key) => {
app.component(key, Icons[key as keyof typeof Icons]);
})
axios
- 安装
npm install axios vue-axios --save
- 配置
// utils/request.ts
import axios, {AxiosRequestConfig, AxiosResponse} from "axios";
import VueAxios from "vue-axios"
//初始化axios
axios.create({
baseURL: '服务器地址', //设置服务器地址
timeout: 6 * 1000, // 超时设置
withCredentials: true, // 检查跨站点访问控制
})
//设置post请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
//配置请求拦截器
axios.interceptors.request.use(
(request: AxiosRequestConfig) => {
console.log("请求成功");
return request;
}, ((error: any) => {
console.log(error);
return Promise.reject(error);
}))
//配置响应拦截器
axios.interceptors.response.use(
(response: AxiosResponse) => {
console.log("响应成功");
return response;
}, ((error: any) => {
console.log(error);
return Promise.reject(error);
}))
export {axios, VueAxios}
- 使用
// main.ts
import {createApp} from 'vue'
import App from './App.vue';
import {axios, VueAxios} from './utils/axios'
const app = createApp(App)
app.use(VueAxios, axios)
.mount('#app')
- 使用例子
<script setup lang="ts">
import {ref} from "vue";
import axios from "../utils/axios";
const text = ref('')
function test() {
axios.get('/api/test').then(res => {
if (res.data !== null) {
text.value = "连接成功";
}
}).catch(err => {
text.value = "连接失败";
})
}
</script>
<template>
<button @click="test">测试Axios</button>
<p>{{ text }}</p>
</template>
<style scoped lang="less">
p {
color: red;
}
</style>
js-cookie
npm文档:js-cookie
- 安装
npm install @types/js-cookie --save
- 再次封装cookie
// utils/cookie.ts
import cookie from 'js-cookie'
export const getCookie = (name: string): string => cookie.get(name)
export const getCookieAll = (): string => cookie.get()
export const setCookie = (name: string, value: any) => cookie.set(name, value)
export const setCookieDate = (name: string, value: any, day: number) => cookie.set(name, value, {expires: day})
export const removeCookie = (name: string) => cookie.remove(name)
// env.s.ts
declare module 'js-cookie'
- 常用方法
import cookie from 'js-cookie'
// 设置cookie
cookie.set('name', 'value')
// 设置7天过期的cookie
cookie.set('name', 'value', { expires: 7 })
// 设置当前路径下7天过期的cookie
cookies.set('name', 'value', { expires: 7, path: '' })
//获取所有cookie
cookies.get()
// 获取指定cookie
cookies.get('name')
// 删除指定cookie
cookies.remove('name')
// 删除指定路径下cookie
cookies.remove('name', { path: '' })
js-base64
- 安装
npm install @types/js-base64 --save
- 引用
import { Base64 } from 'js-base64'
vue-router
- 安装
npm install vue-router@4
- 配置
// src/router/index.ts
import {createRouter, createWebHistory, RouteRecordRaw} from 'vue-router'
const routes: Array<RouteRecordRaw> = []
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
- 使用
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
// 默认引入其中的index.ts
import router from './router'
createApp(App)
.use(router)
.mount('#app')
nProgress
- 安装
npm install nprogress --save
- 配置
// utils/index.ts
import {createRouter, createWebHistory} from 'vue-router'
import nProgress from 'nprogress'
import 'nprogress/nprogress.css'
router.beforeEach((to, from, next) => {
nProgress.start()
next()
})
router.afterEach(() => {
nProgress.done()
})
// NProgress配置
nProgress.configure({
ease: 'linear',
speed: 500,
showSpinner: true // 是否使用进度环
})
export default router;
- 设置进度条颜色
// App.vue
<style>
/*设置进度条颜色 不配置时为默认颜色*/
#nprogress .bar {
background: red !important;
}
</style>
// src/env.d.ts
declare module 'nprogress'
pinia
- 安装
npm install pinia
- 配置
// store/index.ts
import {defineStore} from "pinia";
interface storeTypes {
}
export const useMainStore = defineStore('main', {
// 存储全局状态
state: (): storeTypes => {
return {}
},
// 封装计算属性 具有缓存功能
getters: {},
// 封装业务逻辑 修改state
actions: {}
});
- 使用
// main.ts
import {createApp} from 'vue'
import App from './App.vue';
import {createPinia} from "pinia"
createApp(App)
.use(createPinia())
.mount('#app');
markdown
v-md-editor(推荐)
官方文档:v-md-editor
- 安装
npm install @kangc/v-md-editor@next --save
# 高亮代码插件
npm install prismjs --save
npm install vite-plugin-prismjs -D
- 解决在 vue3 + typescript 中使用报错?
// src/env.d.ts
declare module 'nprogress';
declare module '@kangc/v-md-editor';
declare module '@kangc/v-md-editor/*';
declare module 'prismjs';
- 代码高亮配置
// src/vite.config.js
import { defineConfig } from 'vite';
import prismjs from 'vite-plugin-prismjs';
export default defineConfig({
plugins: [
prismjs({
// languages: ['javascript', 'css', 'shell', 'json', 'java', 'typescript', 'sass', 'less','yaml','xml','sql','powershell','php','html'],
languages: 'all',
plugins: ["line-numbers"],
theme: "twilight",
css: true
}
],
});
- 创建配置文件
v-md-editor.ts
// src/utils/v-md-editor.ts
import VueMarkdownEditor from '@kangc/v-md-editor';
import '@kangc/v-md-editor/lib/style/base-editor.css';
import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js';
import '@kangc/v-md-editor/lib/theme/style/vuepress.css';
// 流程图插件
import createMermaidPlugin from '@kangc/v-md-editor/lib/plugins/mermaid/cdn';
import '@kangc/v-md-editor/lib/plugins/mermaid/mermaid.css';
// 显示行号
import createLineNumbertPlugin from '@kangc/v-md-editor/lib/plugins/line-number/index';
// 数学公式插件
import createKatexPlugin from '@kangc/v-md-editor/lib/plugins/katex/cdn';
// emoji插件
import createEmojiPlugin from '@kangc/v-md-editor/lib/plugins/emoji/index';
import '@kangc/v-md-editor/lib/plugins/emoji/emoji.css';
// 提示信息插件
import createTipPlugin from '@kangc/v-md-editor/lib/plugins/tip/index';
import '@kangc/v-md-editor/lib/plugins/tip/tip.css';
// 任务列表插件
import createTodoListPlugin from '@kangc/v-md-editor/lib/plugins/todo-list/index';
import '@kangc/v-md-editor/lib/plugins/todo-list/todo-list.css';
// 代码快捷复制插件
import createCopyCodePlugin from '@kangc/v-md-editor/lib/plugins/copy-code/index';
import '@kangc/v-md-editor/lib/plugins/copy-code/copy-code.css';
// 高亮代码行
import createHighlightLinesPlugin from '@kangc/v-md-editor/lib/plugins/highlight-lines/index';
import '@kangc/v-md-editor/lib/plugins/highlight-lines/highlight-lines.css';
// 代码高亮插件
import Prism from 'prismjs';
import 'prismjs/components/prism-json';
VueMarkdownEditor
.use(createHighlightLinesPlugin())
.use(createCopyCodePlugin())
.use(createLineNumbertPlugin())
.use(createTipPlugin())
.use(createTodoListPlugin())
.use(createKatexPlugin())
.use(createEmojiPlugin())
.use(vuepressTheme, {
Prism
})
export default VueMarkdownEditor
- 组件注册
// src/main.ts
import {createApp} from 'vue'
import App from './App.vue'
import VueMarkdownEditor from './utils/v-md-editor'
createApp(App)
.use(VueMarkdownEditor)
.mount('#app')
- 编辑与预览模式
<script setup lang="ts">
import {reactive} from "vue";
const Options = reactive({
// 双向绑定数据
content: '# 你好世界',
// 编辑器模式 默认editable
mode: [
{name: '仅编辑模式', value: 'edit'},
{name: '仅预览模式', value: 'preview'},
{name: '编辑与预览模式', value: 'editable'}
],
// 正常模式下编辑器的高度
height: '400px',
// 编辑和预览时制表符的长度 默认2
tabSize: 2,
// 目录导航是否在右侧 默认false
tocNavPositionRight: false,
// 是否默认显示目录导航 默认false
defaultShowToc: false,
// 提示文本
placeholder: '记录下你的想法吧!',
// 编辑器加载完是否自动聚焦 默认false
autofocus: true,
// 是否默认开启全屏
defaultFullscreen: false,
// 目录导航生成时包含的标题。默认[2,3]
includeLevel: [1, 2, 3, 4, 5],
// 左侧工具栏 默认 undo redo clear | h bold italic strikethrough quote | ul ol table hr | link image code | save
leftToolbar: 'h bold italic strikethrough quote | ul ol table hr | link image code |undo redo clear | save',
// 哟测工具栏 默认 preview toc sync-scroll fullscreen
rightToolbar: 'preview toc sync-scroll fullscreen',
// 自定义工具栏
toolbar: {},
// toolbar内置配置
toolbarConfig: {
'image-link': {
// 是否在插入图片链接的时候默认带上width height 属性,默认值:false
insertWithSize: false
}
}
})
</script>
<template>
<v-md-editor
v-model="Options.content"
:mode="Options.mode[2].value"
:height="Options.height"
:tab-size="Options.tabSize"
:toc-nav-position-right="Options.tocNavPositionRight"
:default-show-toc="Options.defaultShowToc"
:placeholder="Options.placeholder"
:autofocus="Options.autofocus"
:default-fullscreen="Options.defaultFullscreen"
:include-level="Options.includeLevel"
:left-toolbar="Options.leftToolbar"
:right-toolbar="Options.rightToolbar"
:toolbar="Options.toolbar"
:toolbar-config="Options.toolbarConfig"
/>
</template>
<style scoped lang="less">
</style>
- 预览模式
<script setup lang="ts">
import {reactive} from "vue";
const Documentation = reactive({
// 文档标题
title: '',
// 双向绑定数据
content: ''
})
const Options = reactive({
// 编辑器模式 默认editable
mode: [
{name: '仅编辑模式', value: 'edit'},
{name: '仅预览模式', value: 'preview'},
{name: '编辑与预览模式', value: 'editable'}
]
})
// 点击图片时触发的事件
const clickImage = (images: string, currentIndex: number) => {
console.log("点击图片...")
console.log(images)
console.log(currentIndex)
}
</script>
<template>
<v-md-editor
v-model="Documentation.content"
:mode="Options.mode[1].value"
/>
</template>
<style scoped lang="less">
</style>
Editor.md
官方网站:Editor.md
- 安装
npm install editor.md
mavon-edito(Vue3.x暂不支持)
github源码:github
使用文档:mavon-editor
- 安装
npm install mavon-editor --save
- 注册使用
全局注册
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
md-editor-vue3
官方文档:MdEditorV3 文档
- 安装
npm install md-editor-v3
- 使用
<script lang="ts" setup>
// 文档:https://imzbf.github.io/md-editor-v3/docs/index
import MdEditor from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import {ref} from "vue";
const blogContent = ref('')
</script>
<template>
<MdEditor v-model="blogContent" />
</template>
<style lang="less" scoped>
/*编辑器样式设置*/
#md-editor-v3 {
height: 750px;
}
</style