vue3到vue2组件重构方法笔记

这两天的任务是把一批做好的vue3组件放在vue2项目中使用,将组合式api分散开有一些零散的技巧,所以写一篇转化笔记以供大家参考

先上vue3一个组件的示例代码

<template>
  <div ref="GForms" :style="{background: props.background, border: '1px solid ' + props.borderColor, 'backdrop-filter': props.backBlur? 'blur(10px)': 'blur(0px)'}" style="min-width: 200px; min-height: 60px; padding: 0; margin: 0; position: relative; transition: width .8s, height .8s;">
    <!-- 四个角 -->
    <div v-if="!props.corner" :style="{background: props.cornerColor}" style="position: absolute; left: -1px; top: -1px; width: calc(100% + 2px); height: 2px;"></div>
    <div v-if="props.corner" style="position: absolute; left: -1px; top: -1px; transform: rotateZ(0deg);">
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute;"></div>
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute; transform: rotateZ(90deg); left: -2px; top: 2px;"></div>
    </div>
    <div style="position: absolute; left: -1px; bottom: -1px; transform: rotateZ(270deg);">
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute;"></div>
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute; transform: rotateZ(90deg); left: -2px; top: 2px;"></div>
    </div>
    <div v-if="props.corner" style="position: absolute; right: -1px; top: -1px; transform: rotateZ(90deg);">
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute;"></div>
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute; transform: rotateZ(90deg); left: -2px; top: 2px;"></div>
    </div>
    <div style="position: absolute; right: -1px; bottom: -1px; transform: rotateZ(-180deg);">
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute;"></div>
      <div :style="{background: props.cornerColor}" style="width: 6px; height: 2px; position: absolute; transform: rotateZ(90deg); left: -2px; top: 2px;"></div>
    </div>
    <!-- 标题栏 @mouseup="gFormsMouseup" @mousemove="gFormsMousemove"-->
    <div v-if="props.showTitle" @mousedown="gFormsMousedown" :style="{cursor: props.move? 'move': 'default'}" style="user-select: none; padding: 4px 6px; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; align-items: center;">
      <div style="margin-top: 2px; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center;">
        <div style="font-size: 16px; font-weight: bold; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{props.title}}</div>
        <img :src="data.icon" alt="logo" style="margin: -3px 0 0 3px;"/>
      </div>
      <div @click.stop="gFormsCloseWindows" class="g-forms-close-btn" style="position: relative; width: 22px; height: 22px;">
        <div class="g-forms-close-btn-bg" style="position: relative; width: 20px; height: 20px; margin: 1px;">
          <div style="position: absolute; width: 14px; height: 2px; transform: rotateZ(45deg); transform-origin: center 50%; background: #fff; top: 9px; left: 3px;"></div>
          <div style="position: absolute; width: 14px; height: 2px; transform: rotateZ(-45deg); transform-origin: center 50%; background: #fff; top: 9px; left: 3px;"></div>
        </div>
        <div style="position: absolute; left: -1px; top: -1px; width: 2px; height: 2px; background: #fff;"></div>
        <div style="position: absolute; left: -1px; bottom: -1px; width: 2px; height: 2px; background: #fff;"></div>
        <div style="position: absolute; right: -1px; top: -1px; width: 2px; height: 2px; background: #fff;"></div>
        <div style="position: absolute; right: -1px; bottom: -1px; width: 2px; height: 2px; background: #fff;"></div>
      </div>
    </div>
    <!-- 分割条 -->
    <div v-if="props.showTitle" style="display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; padding: 0 4px;">
      <div style="width: 90%; background: #4F728E; height: 3px;"></div>
      <div style="width: 10%; background: #DEE3E9; height: 3px; margin-left: 2px;"></div>
    </div>
    <slot></slot>
  </div>
</template>

<script lang="ts" setup>
// 边框
import { defineProps, reactive, defineEmits, ref, onMounted } from 'vue'

const props = defineProps({
  title: { type: String, default: "G-Forms" }, // 窗口标题
  showTitle: { type: Boolean, default: true }, // 显示标题
  move: { type: Boolean, default: true }, // 是否可以移动
  inArea: { type: Boolean, default: true }, // 是否在区域内移动
  corner: { type: Boolean, default: true }, // 四个角是否为尖角
  cornerColor: { type: String, default: "#FFF" }, // 四角装饰颜色
  backBlur: { type: Boolean, default: true }, // 开启背景模糊
  background: { type: String, default: "#001820ab" }, // 背景颜色
  borderColor: { type: String, default: "#2F739A" }, // 边框线条颜色
})

const GForms = ref<HTMLElement | null>()
let gflag = ref(false)
const data = reactive({
  icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAZCAYAAAC2JufVAAABYElEQVRIx2P4//8/w2DDDKOOGnXUiHKUqW/cAyD+j4Qb5m478QCI/yPhBkrU/b/k+wCI/yPhBkKOckAz5H/5hEUpaJb9jy5uSSFX3bZFwSlojgJhA7zRB9Q4Ac2gC0ALJqBZeIESdUBHTEBz1AVCjhJAD3bHyKwO9OiZuGpPB7nqfGNjOghFI0Z8DoZoxJr6BzoacTlqQKMRZ1kB1JiAHuxACxLQo4cSdUBHJGBEI4GQ+oBsgFN0TiXQ8A/IFk1YsauSXHX+cTGVQEd8QHNUAT5HHUDz1Qag4QfQfL+BEnVABxxAc9AGfLmvAc2AB9M3HOpAs+iBdXBKB7nqPp/y60BzEChtCeAqpwLQDPhQN31lIZpFH0JyagvJVXdkdVAhmoM+oJfqyA5SQI/3oKzqEvT00TBzdQm56nKKIkuwpKMEfHXfBTRfLQCVMWi+X0CJOnBZhOqgBaPtqVFHjVhHAQDOW7xzUODHCgAAAABJRU5ErkJggg==",
  // 鼠标位置
  gfMX: 0,
  gfMY: 0,
  // 偏移量
  deltaX: 0,
  deltaY: 0,
  // 页面尺寸
  pageW: 0,
  pageH: 0
})

const emit = defineEmits(['close'])

onMounted(() => {
  data.pageW = window.innerWidth
  data.pageH = window.innerHeight
  window.onresize = () => {
    data.pageW = window.innerWidth
    data.pageH = window.innerHeight
  }
  if (data.deltaX != 0 || data.deltaY != 0) setPosition()
})

// 设置窗体位置
const setPosition = () => setTimeout(() => {
  if (GForms.value == null || GForms.value == undefined) return;
  if (props.inArea) {
    if (data.deltaX < 1) data.deltaX = 1
    if (data.deltaY < 80) data.deltaY = 80
    if (data.deltaX + GForms.value?.offsetWidth > data.pageW) data.deltaX = data.pageW - GForms.value?.offsetWidth
    if (data.deltaY + GForms.value?.offsetHeight > data.pageH) data.deltaY = data.pageH - GForms.value?.offsetHeight
  }
  GForms.value.style.top = data.deltaY + "px"
  GForms.value.style.left = data.deltaX + "px"
}, 0)

// 关闭方法
const gFormsCloseWindows = () => {
  emit('close')
}
// 窗体移动方法
const gFormsMousedown = (e:any) => {
  if (!props.move) return

  gflag.value = true
  data.gfMX = e.offsetX
  data.gfMY = e.offsetY
  // 防抖
  if (data.deltaX != 0 || data.deltaY != 0) setPosition()
  // 移动过程
  document.onmousemove = (e: any) => {
    if (!gflag.value) return;
    data.deltaX = e.clientX - data.gfMX
    data.deltaY = e.clientY - data.gfMY
    setPosition()
  }
  // 鼠标抬起
  document.onmouseup = (e: any) => {
    setPosition()
    gflag.value = false
    document.onmousemove = null
    document.onmouseup = null
  }
}


</script>

<style scoped>

.g-forms-close-btn-bg {
  background: #2E454C;
}
.g-forms-close-btn:hover .g-forms-close-btn-bg {
  background: #4b96a3;
  cursor: pointer;
}
.g-forms-close-btn:active .g-forms-close-btn-bg {
  background: #2E454C;
  cursor: pointer;
}

.div-l-shape-s {
  border-style: solid;
  border-width: 0 0 3px 3px;
  position: relative;
  right: -3px;
  top: -3px;
  background: white;
  width: 4em;
  height: 4em;
}
</style>

上面是其中一个vue3组件样式表,在vue3的项目中展示效果为下图所示:
vue3到vue2组件重构方法笔记_第1张图片
组件中还有一些其他的功能都要完整保留,所以现在开始整理:

要将 Vue 3 组件转换为 Vue 2 组件,需要注意一些语法和功能上的差异。下面是我总结的 Vue 3 组件转换为 Vue 2 组件的一般步骤:
1、首先是template里的内容,可以看到在vue3模板里使用属性要这么写:

:style="{background: props.background}" //取出在props里面的值

在 Vue 3 中,使用 props 选项来声明组件的属性,而Vue 3 中的 props 默认是不响应式的,所以可以看到代码中套了一层defineProps方法,defineProps 方法是 Vue 3 中用于声明组件属性的函数。它的作用是定义组件接收的属性,并使其在组件内部成为响应式的。

而在vue2中可以直接使用props里面的值,语法为下面代码:

:style="{background: background}"
export default {
props: {
      title: { type: String, default: "G-Forms" }, // 窗口标题
      showTitle: { type: Boolean, default: true }, // 显示标题
      move: { type: Boolean, default: true }, // 是否可以移动
      inArea: { type: Boolean, default: true }, // 是否在区域内移动
      corner: { type: Boolean, default: true }, // 四个角是否为尖角
      cornerColor: { type: String, default: "#FFF" }, // 四角装饰颜色
      backBlur: { type: Boolean, default: true }, // 开启背景模糊
      background: { type: String, default: "#001820ab" }, // 背景颜色
      borderColor: { type: String, default: "#2F739A" }, // 边框线条颜色
    },
}

因为里面的数据都是可以直接使用的

2、在vue2中要去掉

你可能感兴趣的:(重构,笔记,javascript,vue)