前言
感谢作者的开源,让我们有机会学习
项目地址: 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><inputclass="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变得支持响应式,省去程序员自己写相关代码。
vueuse官方文档
页面跳转,顶部进度条
依赖包:NProgress
官方文档
菜单标签
项目效果
这块的功能涉及路由和菜单比较复杂,就简单写了个类似的demo,代码如下:
组件代码
<template><div @mouseover="handleOver(tagRef)" @mouseout="handleOut(tagRef)"><divclass="tag"ref="tagRef":class="tagOptions.isActive ? 'active' : 'common'"><!-- 文字 --><div>{
{ tagOptions.message }}</div><!-- 关闭按钮 --><iv-show="tagOptions.showIcon"class="el-icon-close close-btn"@click="closeTag"></i></div><!-- 底部线条 --><divref="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-tagv-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
后,线条的效果就很不错了。
中英文切换
传送门
流程图
滴滴开源流程图
编辑器
wangEditor
组件
视频组件
传送门
拖拽组件
传送门
图片裁剪
这个目前用不到,不踩坑了,有需要使用的,可以去看官方文档
传送门
系统管理
table表格
这个表格挺有用的,是一个专门的表格组件,有丰富的功能
官方地址:vxe-table