有Vue2、Vue3组合api基础知识,TypeScript基础知识
CSS3
TypeScript
Vue3.2
Vuex4.x
Vue Router4.x
Vite2.x
Element-Plus
新建vue存放目录,cmd进入存放目录,执行命令创建项目
npm init vite@latest
or
yarn crerate vite
√ Project name: ... vue3-ts
√ Select a framework: » vue
√ Select a variant: » vue-ts
Scaffolding project in D:\bigdata-ws\vue\vue3-ts...
Done. Now run:
cd vue3-ts
npm install
npm run dev
http://localhost:3000/
解决:Network: use --host
to expose
vite.config.ts配置文件,添加如下配置:
export default defineConfig({
plugins: [vue()],
server: {
host: '0.0.0.0', //Network: use `--host` to expose
port: 8080,
open: true
}
})
参考官网:https://vitejs.cn/config/#resolve-alias
npm install @types/node --save-dev
npm run build
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
host: '0.0.0.0', //Network: use `--host` to expose
port: 8080,
open: true
},
resolve:{
alias: [
{
find: '@',
replacement:resolve(__dirname,'src') }
]
}
})
npm install vue-router@4
npm run build
//vue2-router
const router = new VueRouter({
mode: history,
...
})
//vue-router
import { createRouter,createWebHistory} from 'vue-router'
const router = createRouter({
history: createWebHistory(),
...
})
import { createRouter,createWebHistory,RouteRecordRaw } from "vue-router";
import Layout from '@/components/HelloWorld.vue'
const routes:Array = [
{
path:'/',
name:'home',
component:Layout
}
]
//创建
const router = createRouter({
history:createWebHistory(),
routes
})
//暴露 router
export default router
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
createApp(App)
.use(router)
.mount('#app')
https://vuex.vuejs.org/zh/
npm install vuex@next --save
or
yarn add vuex@next --save
// store.ts
import { InjectionKey } from 'vue'
import { createStore, Store } from 'vuex'
// 为 store state 声明类型
export interface State {
count: number
}
// 定义 injection key
export const key: InjectionKey> = Symbol()
export const store = createStore({
state: {
count: 0
}
})
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { store,key } from './store/index'
createApp(App)
.use(router)
.use(store,key)
.mount('#app')
// store.ts
import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
export interface State {
count: number
}
export const key: InjectionKey> = Symbol()
export const store = createStore({
state: {
count: 0
},
mutations: {
setCount(state:State,count:number){
state.count = count;
}
},
getters: {
getCount(state:State){
return state.count;
}
}
})
// 定义自己的 `useStore` 组合式函数
export function useStore () {
return baseUseStore(key)
}
{{ showcount }}
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
//解决打包报`vue-tsc --noEmit && vite build`的错误,忽略所有的声明文件(*.d.ts)的类型检查
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
//ts排除的文件
"exclude": ["node_modules"],
"references": [{ "path": "./tsconfig.node.json" }]
}
import { useStore } from '../store';
修改为
import { useStore } from '@/store';
npm run build
npm run dev
npm install --save-dev eslint-plugin-vue
注:src目录平级位置
module.exports = {
root: true,
parserOptions: {
sourceType: 'module'
},
parser: 'vue-eslint-parser',
extends: ['plugin:vue/vue3-essential','plugin:vue/vue3-strongly-recomended','plugin:vue/vue3-recomended'],
env: {
browser: true,
node: true,
es6: true
},
rules: {
'no-console': 'off',
//禁止使用拖尾逗号
'comma-dangle': [2,'never']
}
}
npm install -D sass sass-loader
https://element-plus.gitee.io/zh-CN/guide/installation.html
npm install element-plus --save
https://element-plus.gitee.io/zh-CN/guide/quickstart.html
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { store,key } from '@/store/index'
//引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App)
.use(router)
.use(store,key)
.use(ElementPlus)
.mount('#app')
在HelloWorld.vue页面加入按钮
{{ showcount }}
Primary
Success
Info
Warning
Danger
禁用Vetur
安装Vue Language Features(Volar)
安装Element UI Snippets
1、setup语法糖中,组件的使用方式
setup语法糖中,引入的组件开源直接使用,无需再通过components进行注册,并且无法制定当前组件的名字,它会自动以文件名为主,不用再写name属性了。
setup语法糖中,定义的数据和方法,直接可以在模板中使用,无需return。
2、ref使用
定义:const xxx = ref(sss)
作用:定义一个响应式的数据
js中操作,需要使用xxx.value
模板中使用不需要 .value
Vite App
https://element-plus.gitee.io/zh-CN/component/container.html
在src下创建layout目录,再创建Index.vue页面
Aside
Header
Main
在src下router目录,修改index.ts中的路由
import { createRouter,createWebHistory,RouteRecordRaw } from "vue-router";
// import Layout from '@/components/HelloWorld.vue'
import Layout from '@/layout/index.vue'
const routes:Array = [
{
path:'/',
name:'home',
component:Layout
}
]
//创建
const router = createRouter({
history:createWebHistory(),
routes
})
//暴露 router
export default router
Aside
Header
Main
https://github.com/vuejs/rfcs/tree/master/active-rfcs
https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md
在layout目录下新建header目录,然后新建Header.vue组件
头部
在layout目录下的Index.vue中引入Header.vue组件
Aside
Main
https://element-plus.gitee.io/zh-CN/component/menu.html#可折叠的菜单
在layout目录先创建menu目录,新建MenuBar.vue
Navigator One
item four
item one
Navigator Two
在layout目录下的Index.vue页面引入左侧导航栏
Main
Navigator One
item four
item one
Navigator Two
注
setup语法糖父子组件传值的方法
父组件传值给子组件,通过属性绑定方式
子组件通过defineProps接收,无需显示的引入
插槽的使用
reactive:响应式数据定义,适用于对象类型
[@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep() instead.
新建src/layout/menu/MenuLogo.vue
Vue实战
在src/layout/menu/MenuBar.vue中引入MenuLogo.vue
https://v3.cn.vuejs.org/api/sfc-script-setup.html
https://github.com/vuejs/rfcs/tree/master/active-rfcs
element plus图标使用
https://element-plus.gitee.io/zh-CN/component/icon.html
在
npm install @element-plus/icons
import { Fold } from '@element-plus/icons'
//局部引用图标
https://v3.cn.vuejs.org/api/sfc-script-setup.html#使用组件
在main.ts把图标注册为全局组件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { store,key } from '@/store/index'
//引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//统一导入element-icon图标
import * as Icons from '@element-plus/icons'
const app = createApp(App);
app.use(router)
.use(store,key)
.use(ElementPlus)
.mount('#app')
//全局注册组件
//方式一
//typeof获取一个对象的类型
//keyof获取某种类型的所有键
Object.keys(Icons).forEach(
(key)=>{
console.log(key)
// app.component(key,Icons[key])
app.component(key,Icons[key as keyof typeof Icons])
}
);
{
path: '/dashboard',
component: "Layout",
meta: {
title: "首页",
icon: "HomeFilled",
roles: ["sys:manage"]
},
children: []
},
{{menu.meta.title}}
{{menu.meta.title}}
import { createApp,createVNode } from 'vue'
import App from './App.vue'
import router from './router/index'
import { store,key } from '@/store/index'
//引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//统一导入element-icon图标
import * as Icons from '@element-plus/icons'
const app = createApp(App);
app.use(router)
.use(store,key)
.use(ElementPlus)
.mount('#app')
//全局注册组件
//方式二
const Icon = (props: {icon: string})=>{
const { icon } = props
return createVNode(Icons[icon as keyof typeof Icons]);
};
app.component('Icon',Icon);
{{menu.meta.title}}
{{menu.meta.title}}
解决type ‘string’ can’t be used to index type ‘typeof’ 字符串不能做下标的错,在tsconfig.json的compilerOptions中添加如下配置
方式一
"suppressExcessPropertyErrors": true, //解决用字符串做下标报错
方式二
key as keyof typeof Icons
https://v3.cn.vuejs.org/api/sfc-script-setup.html
https://github.com/vuejs/rfcs/tree/master/active-rfcs
https://router.vuejs.org/zh/installation.html
首先在vscode编辑器中打开,[文件]->[首选项]->[用户片段]->[新代码片段]->取名vue.json->回车
把下面代码粘进去,其中prefix里面的内容就是快捷键
{
"Print to console": {
"prefix": "vue",
"body": [
"",
" ",
"",
"",
"",
""
],
"description": "Log output to console"
}
}
新建.vue结尾文件,代码区域输入 vue 回车,即可生成定义的模板代码
点击左侧菜单,能够在内容展示区展示对应页面
在setup里面没有访问this,所以不能再直接访问this.$router或this.$route;使用useRouter和useRoute替代;
const router = useRouter() ---> this.$router
const route = useRoute() ---> this.$route
在router/index.ts添加路由
import { createRouter,createWebHistory,RouteRecordRaw } from "vue-router";
// import Layout from '@/components/HelloWorld.vue'
import Layout from '@/layout/index.vue'
const routes:Array = [
{
path:'/',
name:'home',
component:Layout,
redirect: '/dashboard',
children: [
{
path: '/dashboard',
component: ()=>import('@/layout/dashboard/Index.vue'),
name: 'dashboard',
meta: {
title: '首页',
icon: 'HomeFilled'
},
},
],
},
{
path:'/system',
name:'system',
component:Layout,
meta: {
title: "系统管理",
icon: "Menu",
roles: ["sys:manage"],
parentId: 0,
},
children: [
{
path: "/department",
component: ()=>import('@/views/system/department/department.vue'),
name: 'department',
meta: {
title: "机构管理",
icon: "Document",
roles: ["sys:dept"]
}
},
{
path: "/userList",
component: ()=>import('@/views/system/user/UserList.vue'),
name: "userList",
meta: {
title: "用户管理",
icon: "Avatar",
roles: ["sys:user"]
},
},
{
path: "/roleList",
component:()=>import('@/views/system/role/RoleList.vue'),
name: "roleList",
meta: {
title: "角色管理",
icon: "Tools",
roles: ["sys:role"]
},
},
{
path: "/menuList",
component: ()=>import('@/views/system/menu/MenuList.vue'),
name: "menuList",
meta: {
title: "权限管理",
icon: "Document",
roles: ["sys:menu"]
},
},
]
},
{
path: "/goods",
component: Layout,
name: "goods",
meta: {
title: "商品管理",
icon: "Shop",
roles: ["sys:goods"]
},
children: [
{
path: "/goodsCategory",
component: ()=>import('@/views/goods/goodscategory/goodsCategoryList.vue'),
name: "goodsCategory",
meta: {
title: "商品分类",
icon: "Sell",
roles: ["sys:goodsCategory"]
}
}
]
},
{
path: "/systemConfig",
component: Layout,
name: "systemConfig",
meta: {
title: "系统工具",
icon: "Setting",
roles: ["sys:systemConfig"]
},
children: [
{
path: "/document",
component: ()=>import('@/views/system/config/systemDocument.vue'),
name: "https://42.193.158.170:8089/swagger-ui/index.html",
meta: {
title: "接口文档",
icon: "Document",
roles: ["sys:document"]
},
},
],
},
]
//创建
const router = createRouter({
history:createWebHistory(),
routes
})
//暴露 router
export default router
src/layout/dashboard/Index.vue
首页
src/views/goods/goodscategory/goodsCategoryList.vue
商品分类
src/views/system/config/systemDoument.vue
接口文档
src/views/system/department/department.vue
机构管理
src/views/system/menu/MenuList.vue
权限管理
src/views/system/role/RoleList.vue
角色管理
src/views/system/user/UserList.vue
用户管理
src/layout/Index.vue
https://element-plus.gitee.io/zh-CN/component/menu.html#menu-属性
src/layout/menu/MenBar.vue
router 是否启用 vue-router 模式。 启用该模式会在激活导航时以 index 作为 path 进行路由跳转
......
src/layout/menu/MenBar.vue
default-active 默认激活菜单的 index
https://element-plus.gitee.io/zh-CN/component/menu.html#menu-属性
在src/store/index.ts
// store.ts
import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
export interface State {
count: number,
//collapse 是否水平折叠收起菜单(仅在 mode 为 vertical 时可用) boolean
collapse:boolean
}
export const key: InjectionKey> = Symbol()
export const store = createStore({
state: {
count: 0,
collapse: false
},
mutations: {
setCount(state:State,count:number){
state.count = count;
},
//设置collapse
setCollapse:(state: State,collapse: boolean)=>{
state.collapse = collapse;
}
},
getters: {
getCount(state:State){
return state.count;
},
//获取collapse
getCollapse:(state:State)=>{
return state.collapse;
}
}
})
// 定义自己的 `useStore` 组合式函数
export function useStore () {
return baseUseStore(key)
}
在src/layout/header/Header.vue中引入Collapse组件
在src/layout/menu/MenuBar.vue中,控制菜单展开和关闭
在src/layout/menu/MenuBar.vue中添加动画样式
在src/layout/menu/MenuBar.vue中的MenuLogo添加class
在src/layout/header/下新建BredCum.vue组件
https://element-plus.gitee.io/zh-CN/component/breadcrumb.html
homepage
promotion management
promotion list
promotion detail
在src/layout/header/Header.vue中使用面包屑
在src/layout/header/BredCum.vue中
{{item.meta.title}}
vuex在组合API中的使用
const store = useStore();
vue-router在组合API中的使用
const route = useRoute();
const router = useRouter();
响应式数据的定义;ref、reactive
watch、computed的使用
element plus组件Tabs标签的使用
TypeScript中接口interface的使用,接口是一种规范
在src/layout/tabs目录下,新建Tabs.vue组件
https://element-plus.gitee.io/zh-CN/component/tag.html
点击菜单,显示对应的选项卡
watch监听路由path的变化,把当前路由的title和path放到Tabls选项卡对用的数据里面
选项卡的激活设置
把当前激活的选项卡v-mode绑定项为当前路由的path
点击选项卡,左侧对应菜单激活
点击选项卡,跳转到对应的路由;只需要把选项卡的v-mode绑定项设为当前路由的path,左侧菜单便可自动激活
关闭选项卡
首页不能关闭,关闭时,删除当前选项卡,重新设置vuex里面的选项卡数据;并跳转到新的路由;
刷新浏览器时,选项卡数据丢失
window.addEventListener('beforeunload')
interface和type的基本使用
typeof和keyof的使用
反型、泛型约束的使用
TppeScript模板字符串的基本使用
TypeScript中文交叉类型、联合类型的基本使用
Omit、Pick、Parameters、ReturnType的基本使用