Skip to content

Commit

Permalink
fix(canvasShortCutPanel): add click event to quick insert component i…
Browse files Browse the repository at this point in the history
…n… (#81)

* fix(canvasShotCutPanel): add click event to quick insert component in shortcutpanel

* fix(canvasShortPanel): add deepclone utils

* feat(utils): add deepClone method

* feat(unit-test): add unit test for deepclone function
  • Loading branch information
chilingling committed Nov 30, 2023
1 parent 3ae47c8 commit 8ed61ca
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 19 deletions.
23 changes: 18 additions & 5 deletions packages/canvas/src/components/container/CanvasDragItem.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<template>
<div draggable="true" class="drag-item" @dragstart="dragstart">
<div draggable="true" class="drag-item" @dragstart="dragstart" @click="handleClick">
<slot></slot>
</div>
</template>

<script>
import { utils } from '@opentiny/tiny-engine-utils'
import { dragStart } from './container'
const { deepClone } = utils
export default {
props: {
data: Object
},
emits: ['click'],
setup(props, { emit }) {
const dragstart = (e) => {
if (props.data && e.button === 0) {
const data = JSON.parse(JSON.stringify(props.data))
emit('click', data)
if (props.data) {
const data = deepClone(props.data)
dragStart(data)
// 设置拖拽鼠标样式和设置拖拽预览图
Expand All @@ -24,8 +27,18 @@ export default {
e.dataTransfer.setDragImage(target, 10, 10)
}
}
const handleClick = () => {
if (props.data) {
const data = deepClone(props.data)
emit('click', data)
}
}
return {
dragstart
dragstart,
handleClick
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"dist"
],
"scripts": {
"build": "vite build"
"build": "vite build",
"test": "vitest"
},
"keywords": [],
"repository": {
Expand All @@ -26,9 +27,11 @@
"license": "MIT",
"homepage": "https://opentiny.design/tiny-engine",
"devDependencies": {
"vite": "^4.3.7"
"vite": "^4.3.7",
"vitest": "^0.34.6"
},
"dependencies": {
"@opentiny/vue-renderless": "~3.10.0"
"@opentiny/vue-renderless": "~3.10.0",
"vue": "^3.3.8"
}
}
167 changes: 157 additions & 10 deletions packages/utils/src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/

import { isRef, isProxy, unref, toRaw } from 'vue'
import { isObject, isArray } from '@opentiny/vue-renderless/grid/static'

export const fun_ctor = Function
Expand Down Expand Up @@ -177,3 +178,149 @@ export function generateRandomLetters(length = 1) {
}
return result
}

export function getRawValue(target) {
let res = target

if (isRef(res)) {
res = unref(res)
}

if (isProxy(res)) {
return toRaw(res)
}

return res
}

export function getType(val) {
let type = typeof val

if (type !== 'object') {
return type
}

return Object.prototype.toString.call(val).replace(/\[object (.*)\]/, '$1')
}

function cloneArray(target, map, _deepClone) {
let res = []

map.set(target, res)

target.forEach((item, index) => {
res[index] = _deepClone(item, map)
})

return res
}

function cloneMap(target, map, _deepClone) {
let res = new Map()

map.set(target, res)

target.forEach((value, key) => {
res.set(key, _deepClone(value, map))
})

return res
}

function cloneSet(target, map, _deepClone) {
let res = new Set()

map.set(target, res)

target.forEach((value) => {
res.add(_deepClone(value, map))
})

return res
}

function cloneObject(target, map, _deepClone) {
const res = {}

map.set(target, res)

Object.entries(target).forEach(([key, value]) => {
res[key] = _deepClone(value, map)
})

return res
}

export function naiveDeepClone(target) {
try {
return structuredClone(target)
} catch (error) {
// target is no serializable
}
}

/**
* 使用 JSON.stringify 进行 deep clone
* 不支持 Map、Set、Date、RegExp、ArrayBuffer 等变量类型
* 不支持循环引用
* @param {*} target target to be copy
* @param {*} callback target copyed
*/
export function jsonDeepClone(target, callback) {
try {
JSON.parse(JSON.stringify(target))
} catch (error) {
if (typeof callback === 'function') {
callback()
}
}
}

const copyMethodMap = {
Array: cloneArray,
Map: cloneMap,
Set: cloneSet,
Object: cloneObject
}

function _deepClone(target, map) {
if (map.has(target)) {
return map.get(target)
}

const copyTarget = getRawValue(target)
const basicType = ['undefined', 'number', 'string', 'boolean', 'function', 'bigint', 'symbol', 'Null']

let type = getType(copyTarget)

if (basicType.includes(type)) {
return target
}

let res = naiveDeepClone(copyTarget)

if (res) {
map.set(target, res)

return res
}

if (copyMethodMap[type]) {
res = copyMethodMap[type](target, map, _deepClone)

return res
}

return copyTarget
}

/**
* 优先使用 structuredClone 的深拷贝方法
* 不支持 拷贝 prototype、function、DOM nodes、proxy(getter、setter)
* 如果是 vue 的 ref 或者 reactive,会尝试拿到 raw value 然后进行深拷贝
* @param {*} target value to be deep clone
* @returns * deepCloned target
*/
export function deepClone(target) {
return _deepClone(target, new WeakMap())
}
Loading

0 comments on commit 8ed61ca

Please sign in to comment.