sinter-compositions
Version:
vue3 composition 工具库
575 lines (555 loc) • 20.7 kB
JavaScript
/*
*****************************************************************
* *
* author:xiangxinji *
* github:https://github.com/xiangxinji/sinter-compositions *
* *
*****************************************************************
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SinterCompositions = {}, global.Vue));
}(this, (function (exports, vue) { 'use strict';
/**
* 处理区间问题 , 如数字 , 数组区间
*/
function computedCurrentIndexLoop(isLoop, current, min, max) {
if (isLoop === void 0) { isLoop = false; }
if (!isLoop) {
return current > max ?
max : (current < min ? min : current);
}
else {
return current > max ?
min : (current < min ? max : current);
}
}
function useNumberScope(min, max, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.loop, loop = _c === void 0 ? false : _c, _d = _b.step, step = _d === void 0 ? 1 : _d, _e = _b.onChange, onChange = _e === void 0 ? null : _e, _f = _b.onInitState, onInitState = _f === void 0 ? null : _f;
var state = vue.reactive({
current: min,
min: min,
max: max
});
if (onInitState) {
onInitState(state);
}
var isMin = vue.computed(function () { return state.current === state.min; });
var isMax = vue.computed(function () { return state.current === state.max; });
function next() {
state.current += step;
}
function prev() {
state.current -= step;
}
vue.watch(function () { return state.current; }, function (v) {
state.current = computedCurrentIndexLoop(loop, v, state.min, state.max);
// 有越界 , 或者进行循环
if (v !== state.current && onChange) {
onChange(state.current, v);
}
});
return [
state,
{
next: next,
prev: prev,
isMin: isMin,
isMax: isMax,
},
];
}
/**
* 指令组 composition
* @param commands 指令集合
* @param defaultIndex 默认索引
*/
function useCommands(commands, _a) {
if (commands === void 0) { commands = []; }
var _b = _a === void 0 ? {} : _a, _c = _b.defaultIndex, defaultIndex = _c === void 0 ? -1 : _c, _d = _b.onInitState, onInitState = _d === void 0 ? null : _d, _e = _b.onChange, onChange = _e === void 0 ? null : _e;
var state = vue.reactive({
commands: commands,
currentIndex: defaultIndex
});
if (onInitState)
onInitState(state);
var currentCommand = vue.computed(function () {
if (state.currentIndex === -1 || state.currentIndex >= state.commands.length)
return null;
return state.commands[state.currentIndex];
});
var isHeader = vue.computed(function () { return state.currentIndex === 0; });
var isFooter = vue.computed(function () { return state.currentIndex === state.commands.length - 1; });
function swapIndex(targetIndex, originIndex) {
if (originIndex === void 0) { originIndex = state.currentIndex; }
if (targetIndex < 0 || originIndex < 0)
return;
else if (targetIndex >= state.commands.length || originIndex >= state.commands.length)
return;
var temp = state.commands[targetIndex];
state.commands[targetIndex] = state.commands[originIndex];
state.commands[originIndex] = temp;
}
function activeIndex(index) {
state.currentIndex = index;
}
function activeCommand(command) {
var i = -1;
if (typeof command === 'string') {
i = state.commands.findIndex(function (item) { return item.command === command; });
}
else {
i = state.commands.findIndex(function (item) { return item.command === command.command; });
}
if (i === -1)
return;
state.currentIndex = i;
}
vue.watch(function () { return state.currentIndex; }, function (v) {
if (v < 0) {
return state.currentIndex = 0;
}
else if (v >= state.commands.length) {
return state.currentIndex = state.commands.length - 1;
}
if (onChange)
onChange(v);
});
return [
state,
{
currentCommand: currentCommand,
isHeader: isHeader,
isFooter: isFooter,
swapIndex: swapIndex,
activeIndex: activeIndex,
activeCommand: activeCommand
}
];
}
/**
* 负责状态的一些管理
*/
/**
* 将一个数据进行备份
* Return:Array
* Array[0]: 备份的数据 , 通过Ref 进行保存
* Array[1]: reset 方法 , 调用可以将 state 恢复到一开始的状态
* @param data
*/
function useBackupData(data) {
function deepClone(value) {
return JSON.parse(JSON.stringify(value));
}
var temp = deepClone(data);
var state = vue.ref(data);
function reset() {
state.value = deepClone(temp);
}
var res = [state, reset];
return res;
}
function noop() { }
// 倒计时
function useCountDown(timer, callback, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.step, step = _c === void 0 ? 1000 : _c, _d = _b.done, done = _d === void 0 ? noop : _d, _e = _b.immediate, immediate = _e === void 0 ? false : _e;
var current = vue.ref(timer);
var i = null;
function callDone() {
if (i !== null) {
clearTimeout(i);
}
done && done.call(null);
}
function run() {
return setTimeout(function () {
current.value -= step;
if (current.value <= 0) {
callDone();
}
else {
callback && callback(current.value, step);
i = run();
}
}, step);
}
var context = {
run: function () {
i = run();
},
toSecond: vue.computed(function () { return (current.value / 1000); })
};
if (immediate) {
context.run();
}
return [current, context];
}
/**
* 栈
* @param data 处理栈数据
* @param observer 是否开启响应式
*/
function useStack(data, _a) {
if (data === void 0) { data = []; }
var _b = _a === void 0 ? {} : _a, _c = _b.observer, observer = _c === void 0 ? false : _c;
var state = (observer ? vue.reactive(data) : data);
function push(item) {
state.push(item);
}
function pop() {
if (state.length === 0)
return null;
var t = state.pop();
if (t)
return t;
return null;
}
return [
state,
{
push: push,
pop: pop
}
];
}
function querySelector(el) {
var result = null;
if (typeof el === 'string') {
result = document.querySelector(el);
}
else if (el instanceof HTMLElement) {
result = el;
}
else
result = el.value;
if (!result)
return null;
return result;
}
/**
* 处理用户滚动的一些操作
*/
// 计算滚动方向
function createComputedScrollDirective(bTop, bLeft) {
var beforeTop = bTop;
var beforeLeft = bLeft;
function computedDirection(top, left, beforeDirection) {
if (top !== beforeTop) {
beforeTop = top;
beforeLeft = left;
return 'vertical';
}
if (left !== beforeLeft) {
beforeTop = top;
beforeLeft = left;
return 'horizontal';
}
return beforeDirection;
}
return computedDirection;
}
/**
* 将一个容器订阅scroll 事件
* @param contain 容器 el
* @param observer scroll 数据是否需要响应式
* @param immediate 是否在一开始默认执行获取容器和绑定事件
*/
function useScroll(contain, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.observer, observer = _c === void 0 ? false : _c, _d = _b.immediate, immediate = _d === void 0 ? false : _d;
var t = { top: 0, left: 0, direction: 'none' };
var state = (observer ? vue.reactive(t) : t);
var isVertical = vue.computed(function () { return state.direction === 'vertical'; });
var isHorizontal = vue.computed(function () { return state.direction === 'horizontal'; });
var handler = null;
var container = null;
var onScroll = null;
function start() {
var computedDirection = createComputedScrollDirective(state.top, state.left);
container = querySelector(contain);
console.log(container);
if (container === null) {
return console.warn('[useScroll]:找不到 scroll 容器');
}
handler = function (event) {
var target = event.target;
state.top = target.scrollTop;
state.left = target.scrollLeft;
state.direction = computedDirection(state.top, state.left, state.direction);
if (onScroll) {
onScroll(state, event);
}
};
if (handler !== null) {
container.addEventListener('scroll', handler);
}
}
function stop() {
if (container && handler)
container.removeEventListener('scroll', handler);
}
function defineScroll(callback) {
onScroll = callback;
}
vue.onMounted(function () {
if (immediate) {
start();
}
});
return [
state,
{ start: start, stop: stop, isVertical: isVertical, isHorizontal: isHorizontal, defineScroll: defineScroll }
];
}
// 这个方法只会被执行一次
function useOnce(callback) {
var called = false;
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (called)
return;
callback.apply(args);
called = true;
};
}
// 开关 , 每次调用 toggle 都会进行 boolean 的取反
function useToggle(defaultValue, callback) {
var state = vue.reactive({
value: !!defaultValue
});
function toggle() {
state.value = !state.value;
if (callback) {
return callback(state.value);
}
}
return [state, toggle];
}
var EventEmitter = /** @class */ (function () {
function EventEmitter() {
this.eventData = new Map();
}
EventEmitter.prototype.on = function (eventName, handler, once) {
if (once === void 0) { once = false; }
if (this.include(eventName, handler))
return;
var data = (this.eventData.has(eventName) ? this.eventData.get(eventName) : []);
data.push({
once: once,
handler: handler
});
this.eventData.set(eventName, data);
};
EventEmitter.prototype.once = function (eventName, handler) {
this.on(eventName, handler, true);
};
EventEmitter.prototype.emit = function (eventName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var r = this.eventData.get(eventName);
if (!r)
return;
r.forEach(function (data) {
try {
data.handler.apply(null, args);
}
catch (e) {
console.error('[EventEmitter]: handler 执行异常', e);
}
});
r = r.filter(function (i) { return !i.once; });
this.eventData.set(eventName, r);
};
EventEmitter.prototype.include = function (eventName, handler) {
var data = this.eventData.get(eventName);
if (!data)
return false;
var ind = data.findIndex(function (d) { return d.handler === handler; });
if (ind === -1)
return false;
return true;
};
EventEmitter.prototype.off = function (eventName, handler) {
if (!this.include(eventName, handler))
return;
var r = this.eventData.get(eventName);
var t = r.filter(function (i) { return i.handler !== handler; });
this.eventData.set(eventName, t);
};
return EventEmitter;
}());
var scopeEvents = new Map();
function createInstance(scopeKey) {
if (scopeKey) {
var event_1 = scopeEvents.get(scopeKey);
if (!event_1) {
var d = new EventEmitter();
scopeEvents.set(scopeKey, d);
return d;
}
else
return event_1;
}
return new EventEmitter();
}
function useEventEmitter(options) {
var evt = createInstance(options.scopeKey);
if (options === null || options === void 0 ? void 0 : options.providerKey) {
vue.provide(options.providerKey, evt);
}
return evt;
}
var defaultProps = {
key: 'id',
children: 'children'
};
function useTree(_a, d) {
var _b = _a === void 0 ? {} : _a, _c = _b.props, props = _c === void 0 ? defaultProps : _c;
var data = vue.ref([]);
function each(callback) {
var _each = function (d, _a) {
var level = _a.level, parentIndex = _a.parentIndex, parent = _a.parent;
for (var i = 0; i < d.length; i++) {
var node = d[i];
var hasChildren = node[props.children] && Array.isArray(node[props.children]) && node[props.children].length > 0;
var res = callback(d[i], { level: level, parentIndex: parentIndex, hasChildren: hasChildren, parent: parent, index: i });
if (typeof res === 'undefined' && hasChildren) {
return _each(node[props.children], {
level: level + 1, parentIndex: i, parent: node
});
}
return res;
}
};
return _each(data.value, {
level: 1,
parentIndex: -1,
parent: null
});
}
function find(key) {
var r = null;
each(function (node) {
if (node[props.key] === key)
return r = node;
});
return r;
}
function set(d) {
data.value = d;
}
function remove(key) {
each(function (node, _a) {
var level = _a.level, parent = _a.parent, index = _a.index;
if (node[props.key] === key) {
if (level === 1)
data.value.splice(data.value.find(function (i) { return i[props.key] === key; }), 1);
else {
parent[props.children].splice(index, 1);
}
return node;
}
});
}
function append(key, node) {
var current = find(key);
if (current !== null) {
if (!current[props.children] || !Array.isArray(current[props.children])) {
current[props.children] = [];
}
current.push(node);
}
}
var handlers = {
each: each,
find: find,
remove: remove,
append: append,
set: set
};
var result = [data, handlers];
return result;
}
/**
* 负责文件的导出/下载操作
*/
function exportFile(res, name) {
var url = window.URL.createObjectURL(new Blob([res], { type: 'application/vnd.ms-excel;charset=utf-8' }));
var link = document.createElement('a');
link.style.display = 'none';
link.href = url;
var nd = new Date();
var fileName = name || (nd.getFullYear() + "-" + (nd.getMonth() + 1) + "-" + nd.getDate());
link.setAttribute('download', fileName + '.xlsx');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
function exportPath(path) {
var elink = document.createElement("a");
elink.style.display = "none";
elink.href = path;
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
}
function useCreateExporter() {
return {
exportFile: exportFile,
exportPath: exportPath
};
}
function useWrapperFetch(handler, options) {
if (options === void 0) { options = {
immediate: true,
lock: true
}; }
var state = vue.reactive({
loaded: false,
loading: false,
success: false,
});
function fetch() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (options.lock && state.loading) {
return undefined;
}
state.loading = true;
var t = handler.apply(null, args);
if (t instanceof Promise || (typeof t.then === 'function' && typeof t.finally === 'function' && typeof t.catch === 'function')) {
t.then(function () {
state.success = true;
}).catch(function () { return state.success = false; }).finally(function () {
state.loaded = true;
state.loading = false;
});
}
return t;
}
return [state, fetch];
}
exports.useBackupData = useBackupData;
exports.useCommands = useCommands;
exports.useCountDown = useCountDown;
exports.useCreateExporter = useCreateExporter;
exports.useEventEmitter = useEventEmitter;
exports.useNumberScope = useNumberScope;
exports.useOnce = useOnce;
exports.useScroll = useScroll;
exports.useStack = useStack;
exports.useToggle = useToggle;
exports.useTree = useTree;
exports.useWrapperFetch = useWrapperFetch;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=index.js.map