闲聊

前段时间小颖在B站找了个学习vue3+TS的视频,自己尝试着搭建了一些基础代码,在实现功能的过程中遇到了一些问题,为了防止自己遗忘,写个随笔记录一下嘻嘻

项目代码

git地址:vue3.x-ts-element-plus--demo

踩坑集合:

1.根据 element-plus 官网提示 按需引入 组件后,遇到:ElLoading、ElMessage、ElNotification、ElMessageBox  样式丢失

起因是小颖在封装  axios 时,发现引入的  ElNotification 组件没有样式,表单提交时加载  ElLoading 组件有没有样式,后来通过面向百度解决了该问题,嘻嘻

解决方案一:

第一步:执行下面代码

npm i unplugin-element-plus -D

第二步:在 vue.config.js 改为

const { defineConfig } = require('@vue/cli-service')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    plugins: [
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
      require('unplugin-element-plus/webpack')({
        // options
      }),
    ],
  },
})

解决方案二:

直接全局引入 element-plus

第一步:修改 main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/es/components/button/style/css'
createApp(App).use(store).use(router).use(ElementPlus).mount('#app')

参考:记录-解决element-plus自动引入后ElLoading、ElMessage、ElNotification、ElMessageBox样式丢失的问题

2.动态使用图标组件时,图标组件不能正确渲染

起因是小颖在封装菜单组件时,要动态遍历菜单数据根据数据中的  icon 值,通过:

<component :is="menuInfo.icon" class="menu-icon" />

动态渲染各自的菜单图标,但是没有渲染出来,通过F12发现渲染出来的dom就不是图标组件的dom,而是这样的:

当前 menuInfo.icon 值为:setting

左侧菜单组件

因考虑到菜单可能不止两级可能会是多级的所以小颖将其封装成以下组件:

<template>
<div class="logo-box">XXXX管理系统</div>
<div class="menu-box">
<el-menu
active-text-color="#ffd04b"
background-color="#545c64"
class="el-menu-vertical"
:default-active="menuActive"
:unique-opened="true"
text-color="#fff"
@open="handleOpen"
@close="handleClose"
>
<template v-for="menu in menuList" :key="menu.id">
<subMenu :menuInfo="menu" />
</template>
</el-menu>
</div>
</template> <script lang="ts" setup>
import { defineProps, computed } from "vue";
import { useStore } from "vuex";
import SubMenu from "./subMenu.vue"; const store = useStore();
const props = defineProps({
menuList: {
type: Array,
default: () => [],
},
});
const menuActive = computed(() => {
return store.state.setting.menuActive;
});
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath);
};
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath);
};
</script> <style lang="scss" scoped>
.logo-box {
height: 80px;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
cursor: pointer;
background-color: #545c64;
color: #fff;
// background: v-bind(themeBackground);
}
.menu-box {
height: calc(100vh - 80px);
background-color: #545c64;
}
.el-menu-vertical {
border-right: none;
}
.el-menu-vertical:not(.menu--collapse) {
min-height: 400px;
}
</style>

leftMenu.vue

<template>
<el-sub-menu v-if="menuInfo.childs.length > 0" :index="menuInfo.id">
<template #title>
<el-icon :size="18">
<component :is="menuInfo.icon" />
</el-icon>
<span>{{ menuInfo.m_name }}</span>
</template>
<template v-for="item in menuInfo.childs" :key="item.id">
<sub-menu :menu-info="item" />
</template>
</el-sub-menu>
<el-menu-item v-else :index="menuInfo.id" @click="menuFun(menuInfo, menuInfo.id)" >
<el-icon :size="18">
<component :is="menuInfo.icon" class="menu-icon" />
</el-icon>
<span>{{ menuInfo.m_name }}</span>
</el-menu-item>
</template>
<script lang="ts" name="SubMenu" setup>
import {
Document,
Menu as IconMenu,
Location,
Setting,
Menu,
Grid,
} from "@element-plus/icons-vue";
import { defineProps } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex"; //路由
const router = useRouter();
//vuex
const store = useStore();
const props = defineProps({
menuInfo: {
type: Object,
default: () => {
return {
id: "",
parent_id: "",
m_name: "",
icon: "",
childs: [],
};
},
},
}); const menuFun = (event: any, index: string) => {
setNav(event);
store.dispatch("setMenuActive", { menuActive: index });
if (event.url && event.url.length > 0) {
router.push({
path: event.url,
query: {},
});
}
};
const setNav = (item: any) => {
store.dispatch("setNav", { nav: item });
};
</script>

subMenu.vue

解决方案一:

修改 main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/es/components/button/style/css'
import * as Icons from '@element-plus/icons-vue'
const app = createApp(App) Object.keys(Icons).forEach(key => {
app.component(key, Icons[key as keyof typeof Icons])
})
app.use(store)
app.use(router)
app.use(ElementPlus)
app.mount('#app')

解决方案二:

将 main.ts 改回原来的

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
//公共css
import './assets/css/index.scss'

将subMenu.vue组件的 js 代码改为

import { defineComponent } from "vue";
import {
Document,
Menu as IconMenu,
Location,
Setting,
Menu,
Grid,
} from "@element-plus/icons-vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
export default defineComponent({
components: {
Document,
Menu,
Location,
Setting,
Grid,
},
props: {
menuInfo: {
type: Object,
default: () => {
return {
id: "",
parent_id: "",
m_name: "",
icon: "",
childs: [],
};
},
},
},
setup() {
//路由
const router = useRouter();
//vuex
const store = useStore();
const menuFun = (event: any, index: string) => {
setNav(event);
store.dispatch("setMenuActive", { menuActive: index });
if (event.url && event.url.length > 0) {
router.push({
path: event.url,
query: {},
});
}
};
const setNav = (item: any) => {
store.dispatch("setNav", { nav: item });
};
return {
menuFun,
};
},
});
</script>

参考哪里忘记了,第一种是面向百度的,第二种是小颖自己试出来的

来来来找到了,参考这里;vue3 动态加载el-icon图标

3.vuex页面刷新数据丢失问题的四种解决方式

解决方案:

第一步:执行以下代码

npm install --save vuex-persist

第二步:在 store 下的 index.ts 中引入并使用

import VuexPersistence from "vuex-persist";//解决页面刷新vuex数据丢失

const vuexLocal = new VuexPersistence({
storage: window.localStorage
})
export default createStore({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: modules,
plugins: [vuexLocal.plugin]
})

更多方法参考:vuex页面刷新数据丢失问题的四种解决方式

4.如何自动引入  store  下指定目录下的所有文件,此方法也适用于引入组件

比如小颖要实现在 store 下的 index.ts 中自动引入 store  下的 modules 中的所有 ts

解决方案:

将 index.ts 改为:

import { createStore } from 'vuex'
import VuexPersistence from "vuex-persist";//解决页面刷新vuex数据丢失
const modulesFiles = require.context('./modules', false, /\.ts$/) // you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules: any, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const vuexLocal = new VuexPersistence({
storage: window.localStorage
})
export default createStore({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: modules,
plugins: [vuexLocal.plugin]
})

后面的坑等后面写了再继续补充,最近小颖在忙着弄接的私活所以也没继续看vue3了,等这段时间忙完继续搞,打工人···················

Vue3.x+element-plus+ts踩坑笔记的更多相关文章

  1. ts踩坑笔记

    1.react中 this.el 报错 Property 'el' does not exist on type,添加el: any; 2.使用window.xx编译总是报错,用下面方法解决 let ...

  2. EntityFramework CodeFirst SQLServer转Oracle踩坑笔记

    接着在Oracle中使用Entity Framework 6 CodeFirst这篇博文,正在将项目从SQLServer 2012转至Oracle 11g,目前为止遇到的问题在此记录下. SQL Se ...

  3. CAS5.3服务器搭建与客户端整合SpringBoot以及踩坑笔记

    CAS5.3服务器搭建与客户端整合SpringBoot以及踩坑笔记 cas服务器的搭建 导出证书(1和2步骤是找了课程,随便写了一下存记录,不过对于自己测试不投入使用应该不影响) C:\Users\D ...

  4. ES踩坑笔记

    现在开始在业务上使用ES,记录一些踩坑经历,做点笔记. 2018-11-13 source不返回问题 使用了角色校验,客户端插入成功之后获取数据没有source,和查询参数无关. 检查mapping, ...

  5. 微信小程序使用pako.js的踩坑笔记

    问题 今天组长跟我们讨论了个问题,说是文章存储占用有点大,消耗宽带流量费,让我看看能不能找个方法解决一下(文章存储的是html字符串).第一反应是没什么头绪,能想到的就是将相同的字符串替换成一个标识之 ...

  6. 开始更新webpack踩坑笔记

    今天开始学习webpack,记录下踩过的坑-zxf

  7. TypeScript|Angular踩坑笔记

    今天按照Angular官网玩了下demo程序,踩了个小坑,记录下. TypeScript可以将变量申明为自定义类型,同时也不对该类型进行检查(不像C#,如果没有这个类型会报错) 比如下面这样: 如果我 ...

  8. clickhouse源码Redhat系列机单机版安装踩坑笔记

    前情概要 由于工作需要用到clickhouse, 这里暂不介绍概念,应用场景,谷歌,百度一大把. 将安装过程踩下的坑记录下来备用 ClickHouse源码 git clone安装(直接下载源码包安装失 ...

  9. 用Java执行Python:Jython踩坑笔记

    常见的java调用python脚本方式 1.通过Jython.jar提供的类库实现 2.通过Runtime.getRuntime()开启进程来执行脚本文件 1.Jython Jpython使用时,版本 ...

随机推荐

  1. 一文搞懂│XSS攻击、SQL注入、CSRF攻击、DDOS攻击、DNS劫持

    目录 XSS 攻击 SQL 注入 CSRF 攻击 DDOS 攻击 DNS 劫持 XSS 攻击 全称跨站脚本攻击 Cross Site Scripting 为了与重叠样式表 CSS 进行区分,所以换了另 ...

  2. linux centos 系统盘文件系统损坏-已解决

    当我们使用的Linux虚拟机(云服务器/vps)磁盘出现xfs文件系统损坏时,该如何进行修复? xfs格式文件系统损坏,是运维常见的一个场景,经常发生在强制重启.异常关机.软件冲突.误删文件等事件后, ...

  3. java-方法创建与使用

    1.方法: 1)封装一段特定的业务逻辑功能 2)方法尽可能的独立,一个方法只干一件事(低耦合) 3)方法可以被反复调用多次(高复用) 4)减少代码重复,有利于代码维护,有利于团队协作开发2.方法的定义 ...

  4. 监督学习集成模型——AdaBoost

    一.集成学习与Boosting 集成学习是指将多个弱学习器组合成一个强学习器,这个强学习器能取所有弱学习器之所长,达到相对的最佳性能的一种学习范式. 集成学习主要包括Boosting和Bagging两 ...

  5. ArkUI 数据绑定、列表渲染、事件处理

    前言 有过开发微信小程序经验的小伙伴学习鸿蒙应用开发非常容易过渡过来. HML(HarmonyOS Markup Language)是一套类HTML的标记语言,通过组件,事件构建出页面的内容.页面具备 ...

  6. 面试突击78:@Autowired 和 @Resource 有什么区别?

    @Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解.它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同,并且这也是常见 ...

  7. MySQL递归查询语法

    业务上有一个递归查询数据表进行累加计算的需求,实现方式上有函数.SQL语句等多种方式,最后选择了SQL方式,如下: <select id="selectChildren" p ...

  8. 【AGC】使用云调试优惠扣费、华为设备上触发崩溃、无法下载华为应用市场问题小结

    ​ 1.使用云调试剩余优惠时长还剩300分钟,但还会扣费的情况. 问题描述:用户的云调试账户显示剩余优惠时长还有300分钟,但在使用云调试的过程中,还是产生了扣费的情况. ​ 解决方案: 当开发者成功 ...

  9. .NET使用StackTrace获取方法调用者信息

    前言 在日常工作中,偶尔需要调查一些诡异的问题,而业务代码经过长时间的演化,很可能已经变得错综复杂,流程.分支众多,如果能在关键方法的日志里添加上调用者的信息,将对定位问题非常有帮助. 介绍 Stac ...

  10. Hybrid app本地开发如何调用JSBridge

    前天同事问我公司内部的小程序怎么对接的,我回忆了一下,简单记录了一下前端同学需要注意的点. 背后还有小程序架构.网络策略等等.当时恰逢小程序架构调整,(老架构的时候我就发现了有一个问题点可以优化,但是 ...