vue-pure-admin项目的学习

42 篇文章 1 订阅

前言

感谢作者的开源,让我们有机会学习
项目地址: 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变得支持响应式,省去程序员自己写相关代码。

vueuse官方文档

页面跳转,顶部进度条

在这里插入图片描述
依赖包: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后,线条的效果就很不错了。

中英文切换

传送门

流程图

滴滴开源流程图

编辑器

wangEditor

组件

视频组件

传送门

拖拽组件

传送门

图片裁剪

这个目前用不到,不踩坑了,有需要使用的,可以去看官方文档

传送门

系统管理

table表格

这个表格挺有用的,是一个专门的表格组件,有丰富的功能

官方地址:vxe-table

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值