Vue3 低代码开发平台 间距设置功能 问题记录

本文介绍了Vue项目中关于间距组件的功能改造,包括使用SVG图片、改造Element-Plus Drawer组件、全局样式修改、枚举在下拉框中的应用等。此外,还涉及动态绑定图片背景、梯形背景容器的实现以及Vue中获取DOM信息的方法。文章深入探讨了组件优化和代码维护性提升的策略。
摘要由CSDN通过智能技术生成

目录

1. 间距组件功能介绍

2. svg 图片的使用

3. 改造 element-plus Drawer

4. 修改全局 elementplus 样式有感

5. 关于枚举的使用感悟

6. 动态绑定图片背景内联样式

7. 梯形背景容器逻辑

8. vue中,获取当前点击位置 / dom信息等

9. scss 中使用变量

10. 渲染不同截取段的下拉内容

11. props 中 使用枚举 / 实现两种类型二选一

12. slider 组件 和 input 组件之间的关系


1. 间距组件功能介绍

  • 此功能用于设置组件样式中的 内外边距 / 位置信息
  • 未激活状态:
  • 通过 clip-path 绘制梯形效果,原来是通过 svg 添加背景图片的,但是代码太多,设置起来不够灵活,因此换成 div
  • 激活状态:
  • 点击数字后,出现弹框,设置详细数据;如果已经设置了新的值,会将数字更改为蓝色
  • 弹框出现之后,应该有一个黑色覆盖效果
  • 根据点击的数字位置不相同,决定弹框内左上角图标效果
  • 综上所述,我把 间距设置面板 / 间距设置弹框 分成了两个组件

2. svg 图片的使用

  1. 可以直接在 html 中使用 svg 标签
  2. 也可以将 svg 标签,拷贝到 .svg 文件里,并加上头部声明

  •  以下面的代码为例:
  • 可以更改 <path> 中的 fill,来决定 svg 图片的整体颜色
  • 可以给 svg 图片添加类名
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns="http://www.w3.org/2000/svg"
  version="1.1"
  width="16"
  height="16"
  viewBox="0 0 16 16"
>
  <path opacity=".6" fill="#fff" d="M1 3h4v4H1z"></path>
  <path fill="#fff" d="M7 3h8v4H7z"></path>
  <path
    fill-rule="evenodd"
    clip-rule="evenodd"
    d="M10 8v1a2 2 0 01-2 2H4v2h4a4 4 0 004-4V8h-2zm-6.01 5L4 15l-3-3 3-3-.01 2v2z"
    fill="#fff"
  ></path>
</svg>

3. 改造 element-plus Drawer

  • 因为点击 间距设置面板之后,会出现间距设置弹框,而间距设置弹框有一层遮罩效果,因此想到了 element-plus Drawer 组件,基本结构如下
    <el-drawer
      v-model="toChildParams.isPopShow"
      :direction="'rtl'"
      :withHeader="false"
      :lock-scroll="false"
      custom-class="setclass-drawer"
      destroy-on-close
    >
      <spacing-pop></spacing-pop>
    </el-drawer>
  • 关于抽屉组件的一些属性:
  1. v-model 绑定了抽屉是否打开,也就相当于弹框是否显示
  2. direction 绑定了打开方向
  3. withHeader 绑定了是否显示抽屉标题
  4. lock-scroll 绑定了滚动条状态,建议看官网
  5. custom-class 绑定了自定义抽屉类名

  • 弹框只有一小块,上下遮罩 都能实现 点击后关闭弹框,而 drawer 组件默认是充满屏幕高度的,且是白色背景
  • 我看了抽屉组件的 html 结构,遮罩是充满全屏的,也就是说白色背景下面就是遮罩,因此我给白色背景加了个 point-events: none + 透明背景,这样就能点击白色背景的部分能透过去,直接点到遮罩,进而实现关闭了
  • 如下代码所示:
.setclass-drawer.el-drawer {
  width: 240px !important;
  background-color: transparent;
  box-shadow: none;
  pointer-events: none;
}

4. 修改全局 elementplus 样式有感

  • /deep/ 最好用 :deep() 替换,以减少运行警告
  • 在 <style lang="scss" scoped> 中修改 elementplus 时,由于 scoped 限制了样式的作用范围,:deep() 也可能失效,因此可以考虑修改全局的公共 elementplus 样式,全局修改(也就是单独的 css/scss 等文件中)不需要使用 :deep()

  • 修改全局 elementplus 样式步骤:
  1. 在 assets/style 中 新建 element-plus.scss
  2. 在 style.scss 中引入 @import './element-plus';
  3. 给组件添加自定义类名,比如上方的抽屉组件,我加的自定义类名是 setclass-drawer,加了之后,在开发者工具中,可以查找到我自己加的类名
  4. 然后就可以在 elementplus 类名之前加上我的类名,进行修改
  5. 自己加的类名可以不止一个,用空格隔开即可

5. 关于枚举的使用感悟

  • 如上图所示,点击单位后出现单位下拉框,此下拉框使用 elementplus 中的组件,数据结构是 { value: '', label: '' }
  • 在逻辑代码里,当 选中值为 auto 时,会进行特别的操作,也就是我可能会写到 if (state.selectOptions === 'auto') {...} ,当数据变多时,前面这种 'auto' 就有可能会写错,此时就可以考虑枚举了

  • 如上图所示,我写了下拉框列表中,单位 value 的枚举值,可以在 逻辑 中使用此枚举类型
  • 那么我的代码可以替换成:if (state.selectOptions === SpacingSelectUnitEnum.AUTO) {...}

  • 同时,枚举值除了可以在逻辑里使用,还可在 模板 里使用,但必须 return 出去
  • 如下所示:
  1. import { SpacingAndPositionEnum } from '@/types/common-style';
  2. setup() { return { SpacingAndPositionEnum }}
  3. <div class="sticky-info" v-if="position.selected === PositionTypeEnum.sticky">

6. 动态绑定图片背景内联样式

  • 导入图片文件:
  • import marginTopSVG from '@/assets/images/design/settings/spacing/spacing-pop-margin-top.svg';

  • 将导入的图片赋值给一个变量:
  • state.iconImg = marginTopSVG;

  • 在模板中,动态绑定内联样式,使用模板字符串插入图片变量:
  • <div class="icon-box" :style="{ background: `url(${iconImg}) no-repeat center center / 100% 100%` }"></div>

  • 在 css 中能否使用变量绑定图片背景,这个我试了下不太行,也可能是我写错了
  • 在模板中,使用内联样式,必须记得:① style 前面的冒号:;② 双引号后面的大括号{};③ 模板字符串``;
  • 如果配置了路径替代,就是说 src 可以被 @ 替代的话,那么在css 样式中,也可以使用 @/assets/xxx 写路径了

7. 梯形背景容器逻辑

  • 双层循环,渲染出 margin/padding 的背景/标题/数字/提示
  • 第一层循环:循环了 margin/padding容器 及 margin/padding标题
  • 第二层循环:循环了 提示框 / margin/padding背景 / 数字及其点击事件
  • 根据是否设置,决定数字样式::class="{ 'spacing__num--hasset': elem.hasSet }"
    <template v-for="(item, index) of spacingDataList" :key="index">
      <div :class="item.outerBoxClass">
        <div class="spacing__text">{{ item.boxTitle }}</div>
        <!-- margin/padding 容器背景 -->
        <template v-for="(elem, index) of item.innerElem" :key="index">
          <el-tooltip
            effect="light"
            :content="elem.tooltip"
            :placement="elem.tooltipPosition"
            :enterable="false"
            :offset="8"
            popper-class="setclass-tooltip"
          >
            <div :class="elem.class">
              <!-- margin/padding 数字 -->
              <span
                class="spacing__num"
                :class="{ 'spacing__num--hasset': elem.hasSet }"
                @click="handleNumClick(elem, $event)"
              >
                {{ elem.number + elem.unit }}
              </span>
            </div>
          </el-tooltip>
        </template>
  • 关于 tooltip 提示框:
  1. :offset="8": 提示框箭头偏移值
  2. :placement="elem.tooltipPosition":提示框出现位置
  3. :content="elem.tooltip":提示框基本内容
  4. :enterable="false"提示框禁止鼠标划入(当鼠标划入时,提示框会消失)
  5. popper-class="setclass-tooltip" 提示框自定义样式

  • 循环这种双层结构的示例:
  • 不要直接修改遍历出来的 item,最好通过遍历出来的 index,查询到对应项,并修改
state.spacingDataList.forEach((spacingData: any, index: number) => {
  state.spacingDataList[index].innerElem.forEach((item: any, eleIndex: number) => {
    const ele = state.spacingDataList[index].innerElem[eleIndex];
    // 当遍历到当前被修改的值时,进行的而操作
    if (ele.name === info.position) {
      // 修改数值
      ele.number = info.inputValue;
...
  });
});

8. vue中,获取当前点击位置 / dom信息等

  • 给间距模块的数字部分绑定了点击事件,点击事件传递了当前被点击的值 / $event
  • @click="handleNumClick(elem, $event)"

  • 通过 $event 可以获取 当前点击的 dom元素,示例如下:
  • toChildParams.value.clickTop = e.srcElement.getBoundingClientRect().top + e.srcElement.getBoundingClientRect().height;

9. scss 中使用变量

  • $spacing-border-color: rgb(33, 33, 33);
  • &__padding-box { border: 1px solid $spacing-border-color; }

10. 渲染不同截取段的下拉内容

  • 此处的应用场景:
  • 当有自动按钮的时候,显示的下拉框列表中包含 auto;
  • 当没有自动按钮的时候,显示的下拉框列表中不包含 auto;

11. props 中 使用枚举 / 实现两种类型二选一

  • 使用枚举,限定字符串具体内容:
  •     position: {
          type: String as PropType<SpacingAndPositionEnum>,
          default: SpacingAndPositionEnum.marginTop,
        },

  • 使用数组,限定传入的值可以是字符串,也可以是数字
  •  value: {
          type: [String, Number],
          default: '0',
          required: false,
        },

  • 区分:type SpacingInputValueType = string | number;
  • 这种写法不可以在 props 中使用,但是可以在 state 中使用
  • inputValue: 0 as SpacingInputValueType,

12. slider 组件 和 input 组件之间的关系

  • 滑块绑定的数据,必须是数字类型
  • 输入框绑定的数据,可以是字符串类型,也可以是数字类型
  • 滑块的值可以设置一个范围
  • 当输入框的值大于滑块的最大值时,滑块显示在滑块最大值上,输入框显示输入的值
  • 当输入框的值小于滑块的最小值时,滑块显示在滑块最小值上,输入框显示输入的值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值