From bd8348b4324167180cd9c1d2ac7c36fe50f2eb04 Mon Sep 17 00:00:00 2001 From: xiaoxian521 <1923740402@qq.com> Date: Wed, 14 Apr 2021 23:33:38 +0800 Subject: [PATCH] feat: ready add SeamlessScroll component --- src/components/Cropper/src/Cropper.tsx | 9 +- src/components/SeamlessScroll/index.ts | 10 ++ .../SeamlessScroll/src/SeamlessScroll.vue | 15 +++ src/components/SeamlessScroll/src/utils.ts | 114 ++++++++++++++++++ types/global.d.ts | 8 +- 5 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 src/components/SeamlessScroll/index.ts create mode 100644 src/components/SeamlessScroll/src/SeamlessScroll.vue create mode 100644 src/components/SeamlessScroll/src/utils.ts diff --git a/src/components/Cropper/src/Cropper.tsx b/src/components/Cropper/src/Cropper.tsx index e7b3eb980..661cfbc52 100644 --- a/src/components/Cropper/src/Cropper.tsx +++ b/src/components/Cropper/src/Cropper.tsx @@ -1,7 +1,7 @@ import type { CSSProperties } from 'vue' -import { defineComponent, onBeforeMount, nextTick, ref, unref, computed, PropType, getCurrentInstance } from 'vue' - +import { defineComponent, onBeforeMount, nextTick, ref, unref, computed, PropType } from 'vue' +import { templateRef } from '@vueuse/core' import { useAttrs } from '/@/utils/useAttrs' import { emitter } from '/@/utils/mitt' @@ -64,8 +64,8 @@ export default defineComponent({ } }, setup(props) { - let vm: any const cropper: any = ref>(null) + const imgElRef = templateRef('imgElRef', null) const isReady = ref(false) @@ -88,7 +88,7 @@ export default defineComponent({ ) async function init() { - const imgEl = vm.refs.imgElRef + const imgEl = unref(imgElRef) if (!imgEl) { return } @@ -102,7 +102,6 @@ export default defineComponent({ } onBeforeMount(() => { - vm = getCurrentInstance() nextTick(() => { init() // tsx语法返回渲染模板,外部组件想调用内部方法或者获取setup里面的实例,暂时想到的办法是通过公共事件 diff --git a/src/components/SeamlessScroll/index.ts b/src/components/SeamlessScroll/index.ts new file mode 100644 index 000000000..921ca15e7 --- /dev/null +++ b/src/components/SeamlessScroll/index.ts @@ -0,0 +1,10 @@ +import { App } from "vue" +import seamlessScroll from "./src/SeamlessScroll.vue" + +export const SeamlessScroll = Object.assign(seamlessScroll, { + install(app: App) { + app.component(seamlessScroll.name, seamlessScroll) + } +}) + +export default SeamlessScroll \ No newline at end of file diff --git a/src/components/SeamlessScroll/src/SeamlessScroll.vue b/src/components/SeamlessScroll/src/SeamlessScroll.vue new file mode 100644 index 000000000..50abd38c3 --- /dev/null +++ b/src/components/SeamlessScroll/src/SeamlessScroll.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/components/SeamlessScroll/src/utils.ts b/src/components/SeamlessScroll/src/utils.ts new file mode 100644 index 000000000..de87589bb --- /dev/null +++ b/src/components/SeamlessScroll/src/utils.ts @@ -0,0 +1,114 @@ +/** + * @desc AnimationFrame简单兼容hack + */ +const animationFrame = () => { + window.cancelAnimationFrame = (function () { + return window.cancelAnimationFrame || + window.webkitCancelAnimationFrame || + window.mozCancelAnimationFrame || + window.oCancelAnimationFrame || + window.msCancelAnimationFrame || + function (id) { + return window.clearTimeout(id) + } + })() + window.requestAnimationFrame = function () { + return ( + window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function (callback) { + return window.setTimeout(callback, 1000 / 60) + } + ) + }() +} + +/** + * @desc 判断数组是否相等 + * @param {arr1,arr2} + * @return {Boolean} + */ +const arrayEqual = (arr1: Array, arr2: Array) => { + if (arr1 === arr2) return true + if (arr1.length !== arr2.length) return false + for (let i = 0; i < arr1.length; ++i) { + if (arr1[i] !== arr2[i]) return false + } + return true +} + +/** + * @desc 深浅合并拷贝 + */ +function copyObj() { + if (!Array.isArray) { + // @ts-expect-error + Array.isArray = function (arg) { + return Object.prototype.toString.call(arg) === '[object Array]' + } + } + let name, options, src, copy, copyIsArray, clone, + i = 1, + target = arguments[0] || {}, // 使用||运算符,排除隐式强制类型转换为false的数据类型 + deep = false, + len = arguments.length + if (typeof target === 'boolean') { + deep = target + target = arguments[1] || {} + i++ + } + if (typeof target !== 'object' && typeof target !== 'function') { + target = {} + } + // 如果arguments.length === 1 或typeof arguments[0] === 'boolean',且存在arguments[1],则直接返回target对象 + if (i === len) { + return target + } + for (; i < len; i++) { + //所以如果源对象中数据类型为Undefined或Null那么就会跳过本次循环,接着循环下一个源对象 + if ((options = arguments[i]) != null) { + // 如果遇到源对象的数据类型为Boolean, Number for in循环会被跳过,不执行for in循环// src用于判断target对象是否存在name属性 + for (name in options) { + // src用于判断target对象是否存在name属性 + src = target[name] + // 需要复制的属性当前源对象的name属性 + copy = options[name] + // 判断copy是否是数组 + copyIsArray = Array.isArray(copy) + // 如果是深复制且copy是一个对象或数组则需要递归直到copy成为一个基本数据类型为止 + if (deep && copy && (typeof copy === 'object' || copyIsArray)) { + if (copyIsArray) { + copyIsArray = false + // 如果目标对象存在name属性且是一个数组 + // 则使用目标对象的name属性,否则重新创建一个数组,用于复制 + clone = src && Array.isArray(src) ? src : [] + } else { + // 如果目标对象存在name属性且是一个对象则使用目标对象的name属性,否则重新创建一个对象,用于复制 + clone = src && typeof src === 'object' ? src : {} + } + // 深复制,所以递归调用copyObject函数 + // 返回值为target对象,即clone对象 + // copy是一个源对象 + // @ts-expect-error + target[name] = copyObj(deep, clone, copy) + } else if (copy !== undefined) { + // 浅复制,直接复制到target对象上 + target[name] = copy + } + } + } + } + return target +} + +export default { + animationFrame, + arrayEqual, + copyObj +} + + + diff --git a/types/global.d.ts b/types/global.d.ts index 47bfbfcbc..86a033092 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -18,7 +18,13 @@ declare global { } declare interface Window { // Global vue app instance - __APP__: App + __APP__: App, + mozCancelAnimationFrame: (id?: any) => any, + oCancelAnimationFrame: (id?: any) => any, + msCancelAnimationFrame: (id?: any) => any, + mozRequestAnimationFrame: (id?: any) => any, + oRequestAnimationFrame: (id?: any) => any, + msRequestAnimationFrame: (id?: any) => any } // vue