前端实习踩过的坑之组件库系列

1 阅读5分钟

【前言】

很多人在使用流行的UI组件库时都被坑过,我也是深受其害。因此想分享我在使用ElementPlusVant过程中遇到的坑。

1️⃣vant-Image的src属性

空合并运算符 ??

当左侧的数是undefined或null 的时候才会使用右侧的值

逻辑或运算符 ||

当左侧的数可以被转换成false时 才会返回右侧操作数 否则返回左侧操作数

    :src=" '' ?? 本地图片地址" 结果是:图片处于加载状态
    :src=" '' || 本地图片地址" 结果是:采用本地图片地址   
    :src = '' 此时返回的是 false , 所以用 || 图片显示不出来的时候显示本地图片

2️⃣el-select 下拉框双向绑定的值无法显示对应的label

原因: options 赋值的时机在 绑定的value 之后

解决: 必须先给options赋值,再给绑定的value赋值才行

el-select中一些常用属性的解释 :

clearable:允许用户清空已选内容。
filterable:支持通过输入关键字过滤选项。
multiple:支持多选模式。
collapse-tags:在多选模式下,折叠标签以节省空间。
collapse-tags-tooltip:当标签折叠时,鼠标悬停显示完整标签内容。

3️⃣el-table中一些属性的用法

show-overflow-tooltip当单元格内容溢出时,自动显示为省略号,并提供悬浮提示框展示完整内容

:default-sort="{prop: 'id', order: 'descending'}":设置默认排序字段为id,降序排列

height="550"max-height="550":设置表格高度为固定550px。

tooltip-effect="dark":设置表格单元格提示框效果为深色

<el-col class="line" :span="0.5">-</el-col> : 连续两个时间控件间的分割线

4️⃣绑定事件需要传参时,直接调用函数的写法是错误的

拿按钮的点击事件来举例

    <el-button type="primary" @click="handleSubmit">提交</el-button>✅
    <el-button type="primary" @click="handleDelete([scope.row])">删除</el-button>❌
    <el-button type="primary" @click="()=>{handleDelete([scope.row])}">删除</el-button>✅

问题: 直接调用函数handleDelete([scope.row]),函数会在渲染时立即执行,而不是点击按钮才执行;直接传递参数,会导致参数的值在渲染时确定,而不是点击时动态获取;未知的副作用:例如在渲染时触发网络请求或状态更新;这种写法会误以为是点击时执行而实际上是渲染时执行,影响代码的可读性

解决方法: 采用回调函数来延迟执行和传递动态参数,确保点击时执行。

5️⃣组件库无法自动导入和样式异常

检查是否正确导入文件

错误示范

PixPin_2024-12-31_17-13-58.gif 现在回看当时真的很菜,问了前辈一语点醒梦中人。其实是elementPlus的全局样式没有导入,在main.ts文件中导入就解决了

   import 'element-plus/dist/index.css' 

vant和elementPlus组件库的自动导入

官网示例 - Vant 4

这里我介绍下基于Vite的项目,如何在vite.config.js或.ts后缀文件中配置插件

    npm i unplugin-vue-components unplugin-auto-import -D
    import Components from 'unplugin-vue-components/vite'
    import vue from '@vitejs/plugin-vue'; 
    import AutoImport from 'unplugin-auto-import/vite'
    import Components from 'unplugin-vue-components/vite'
    import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'//elementPlus组件的按需引入支持
    import { VantResolver } from 'unplugin-vue-components/resolvers'//vant组件的按需引入支持
    export default {
        plugins: [ 
            vue(), //VantResolver() 可改为ElementPlusResolver()
            AutoImport({ resolvers: [VantResolver()], }), 
            Components({ resolvers: [VantResolver()], }),
            ], 
        };

6️⃣深度选择器修改组件库样式

当你在<style>标签上添加scoped属性时,当前生成的vue文件的类选择器.container 中,会多一个[data-v-678245a5e]属性选择器,它是每个vue文件的文件指纹,每个vue文件template标签中的每个标签都会生成一个文件指纹,这使得css只作用于当前组件中的元素,父组件的样式将不会渗透到子组件,形成了样式隔离。

在写vue的时候,我们很多时候会用到第三方的组件库,如elementPlus、Vant等,需要改动里面的样式。把样式放在全局中是一个解决方法,但显而易见容易污染其他元素,深度选择器就派上用场了。它能够穿透scoped的作用域,使得父组件的样式可以应用于子组件的元素。

深度选择器的区别

  • /deep/ vue2中的用法,支持Sass、Less等预处理器和CSS原生样式,在Vue3中不再被支持
  • css原生语法 >>> ,用于穿透样式封装,存在浏览器兼容问题,不再被推荐使用
  • :deep 伪类选择器 替代>>> 拥有更好的预处理器兼容性 vue2不支持 只支持vue3
  • ::v-deep 工作方式与deep相同 vue3能用的同时还兼容vue2
  • v-deep() (Vue3 Composition API) vue3特有的模板编译特性,可结合v-bind:class或v-bind:style 在模板中动态绑定样式使用

使用示例:

//第三方组件库样式穿透 
:deep(.el-form-item__label) {
  color: #121212;
  font-size: 14px;
  font-weight: 400;
}
:deep(.van-cell) {
    padding: 0;
}
//自定义父子组件样式穿透
<template>
      <div :class="{'custom-class': true}">
      <ChildComponent />
  </div>
</template>

<script setup>
// Composition API 逻辑
</script>

<style scoped>
    .custom-class::v-deep(.child-class) {
      /* 样式规则 */
    }
    /* 或者使用v-deep()函数(虽然不直接在<style>中,但说明其概念) */
    /* 注意:实际中v-deep()不直接用于<style>标签内,而是可能通过其他方式结合Composition API使用 */
</style>

7️⃣弹框组件默认挂载问题

观察elementPlus、vant组件库的类似组件时,你会发现他们都被挂载到body下面了,用css样式选择器时会无法选择到此类组件。

image.png

我们固定定位的弹窗组件也会有同样的现象,原因是:如果固定定位的元素在dom树里面嵌套的层次比较深,当祖先元素出现变形元素时(style="transform:scale(1.1)")会导致固定定位的元素不再相对于视口,所以只能发送到body元素下面。

image.png 可以使用Vue3中提供的把组件内部的dom结构发送到另一个元素里面。 对于组件库 可以用:teleport属性,发送到的元素最好是唯一id选择器的

结语

暂时想到这几个,后面再补充啦~