前言
感谢作者的开源,让我们有机会学习
项目地址: vue-pure-admin
只是记录自己的学习,有问题地方感谢指正
只会记录一些自己目前感觉有用的知识点
代码demo都是基于vue3、ts、element plus
目录结构
-src
--api 存放与请求有关的文件
--assets 存放静态文件(图标、文字)
--components 存放全局公共组件
--config 项目配置
--directives 全局指令
--layout 全局布局
--plugins 插件
--router 路由
--store vuex
--style 全局样式
--utils 全局工具方法
--views 页面
登录页
登录页小功能
项目效果如下,感觉挺不错的
demo
<template>
<div class="login">
<div class="user">
<div ref="nameRef" class="user_name">用户名</div>
<input
class="input"
type="text"
v-model="userName"
@focus="onUserFocus(nameRef)"
@blur="onUserBlur(nameRef, userName)"
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
setup() {
let nameRef = ref(null);
let userName = ref("");
return {
userName,
nameRef,
onUserFocus,
onUserBlur,
};
},
});
//获取焦点事件
const onUserFocus = (dom) => {
dom.classList.remove("blur_name");
dom.classList.add("focus_name");
};
//失去焦点事件
const onUserBlur = (dom, value) => {
if (!value) {
dom.classList.add("blur_name");
}
};
</script>
<style scoped lang="scss">
.login {
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 150px;
margin-left: 100px;
}
.user {
width: 100%;
position: relative;
display: grid;
}
.user_name {
color: gray;
position: relative;
left: 20px;
top: 10px;
font-size: 18px;
}
.focus_name {
transform: translateY(-20px);
transition: 0.3s;
font-size: 14px;
color: blueviolet;
}
.blur_name {
transform: translateY(0px);
transition: 0.3s;
font-size: 18px;
}
.input {
position: absolute;
top: 0;
left: 0;
border: none;
border-bottom: 1px solid gray;
outline: none;
background: none;
padding: 0.5rem 0.7rem;
font-size: 1.2rem;
color: #555;
}
</style>
效果
备注(踩坑)
- 原理差不多,与源代码有些区别
- 不要使用封装好的input框,要使用原始的input框。我使用position和z-index属性可以使文字和输入框在一块,但是会无法触发获取焦点事件
- 使用原生输入框的话,需要解决的问题是前台如何进行登陆校验。
- 试了一下el-input,打算修改placeholder的样式来实现,但是placeholder从输入框里跑出去看不见了
首页
全屏
使用了vueuse
包里的useFullscreen
功能
vueuse:VueUse不是Vue.use,它是为Vue 2和3服务的一套Vue Composition API的常用工具集,是目前世界上Star最高的同类型库之一。它的初衷就是将一切原本并不支持响应式的JS API变得支持响应式,省去程序员自己写相关代码。
页面跳转,顶部进度条
依赖包:NProgress
官方文档
菜单标签
项目效果
这块的功能涉及路由和菜单比较复杂,就简单写了个类似的demo,代码如下:
组件代码
<template>
<div @mouseover="handleOver(tagRef)" @mouseout="handleOut(tagRef)">
<div
class="tag"
ref="tagRef"
:class="tagOptions.isActive ? 'active' : 'common'"
>
<!-- 文字 -->
<div>{{ tagOptions.message }}</div>
<!-- 关闭按钮 -->
<i
v-show="tagOptions.showIcon"
class="el-icon-close close-btn"
@click="closeTag"
></i>
</div>
<!-- 底部线条 -->
<div
ref="tagBottomRef"
class="tag-bottom"
:style="{
width: tagOptions.isActive || tagOptions.isMove ? '94%' : '0%',
}"
></div>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive, ref, watch } from "vue";
export default defineComponent({
props: {
//是否激活,默认不激活
active: {
type: Boolean,
default: false,
},
//是否显示按钮,默认不显示
icon: {
type: Boolean,
default: false,
},
//信息
message: {
type: String,
default: "",
},
//路由地址
url: {
type: String,
default: "",
},
},
setup(props, context) {
let tagOptions = reactive({
//是否激活
isActive: false,
//是否显示按钮
showIcon: false,
//消息
message: "",
//路由地址
url: "",
isMove: false,
});
let tagRef = ref(null);
let tagBottomRef = ref(null);
//监听激活状态
watch(
() => props.active,
(nval) => {
tagOptions.isActive = nval;
tagOptions.isMove = false;
tagOptions.showIcon = false;
}
);
//页面渲染完成进行赋值
onMounted(() => {
tagOptions.isActive = props.active;
tagOptions.showIcon = props.icon;
tagOptions.message = props.message;
tagOptions.url = props.url;
});
//鼠标移入事件
const handleOver = (dom) => {
//鼠标移入时,如果不是激活状态,显示底部边框、关闭按钮
if (!props.active) {
tagOptions.showIcon = true;
tagOptions.isMove = true;
}
};
//鼠标移出事件
const handleOut = (dom) => {
//鼠标移出时,如果不是激活状态,隐藏底部边框、关闭按钮
if (!props.active) {
tagOptions.showIcon = false;
tagOptions.isMove = false;
}
};
//关闭事件
const closeTag = () => {
context.emit("close");
};
return {
tagOptions,
tagRef,
tagBottomRef,
handleOver,
handleOut,
closeTag,
};
},
});
</script>
<style scoped lang="scss">
.tag {
display: flex;
height: 20px;
line-height: 20px;
margin: 0 2px;
cursor: pointer;
}
// 激活样式
.active {
background: #eaf4fe;
color: #8590ff;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
padding: 6px 10px;
}
//平常样式
.common {
padding: 6px 10px;
color: #9c9e9c;
}
//底部线条样式
.tag-bottom {
height: 2px;
width: 0%;
margin: 0 3%;
background: #1890ff;
transition: width 1s;
}
// 按钮样式
.close-btn {
margin-left: 5px;
font-size: 12px;
line-height: 20px;
color: #8590ff;
font-weight: 600;
}
</style>
实例
<template>
<div class="tag_list">
<my-tag
v-for="item in menuList"
:key="item.url"
:message="item.message"
:active="isActive == item.url"
@click="change(item)"
@close="closeItem(index, item)"
></my-tag>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import MyTag from "./my-tag.vue";
export default defineComponent({
components: { MyTag },
setup() {
let isActive = ref("news");
let menuList = ref([
{
message: "首页",
url: "home",
},
{
message: "新闻",
url: "news",
},
{
message: "我的",
url: "my",
},
]);
//切换菜单
const change = (item) => {
isActive.value = item.url;
console.log(isActive.value)
};
//关闭菜单
const closeItem = (index, item) => {
console.log(`你关闭了${item.message}`);
};
return {
isActive,
menuList,
change,
closeItem,
};
},
});
</script>
<style scoped lang="scss">
.tag_list {
display: flex;
}
</style>
效果
备注(踩坑)
- 右侧按钮最开始用的是
v-if
但是鼠标移入移出都会创建、销毁影响性能。另一个是会造成页面的闪烁,导致图标点不了,换成v-show
就很好的解决了这个问题 - 文字下面的线条,最开始是用的
border-bottom
也能实现这个效果,但是线条没有动画效果。后来发现这个线条实际上是一个单独的小div
,换成div
后,线条的效果就很不错了。
中英文切换
流程图
编辑器
组件
视频组件
拖拽组件
图片裁剪
这个目前用不到,不踩坑了,有需要使用的,可以去看官方文档
系统管理
table表格
这个表格挺有用的,是一个专门的表格组件,有丰富的功能