Vue3常用的hooks方法1

useVModel

组件绑定一个v-model属性。

源码

/**
* @description 组件绑定一个v-model
* @param {Object} props 组件的props
* @param {propName} props 属性名称
* @param {Function} props Vue的emit方法
* @date
* @author
*/
export function useVModel(props: any, propName: string, emit: any) {
return computed({
get: () => {
if (typeof props[propName] === "object" && props[propName] !== null) {
const obj: any = {};
return new Proxy(props[propName], {
set(target, name, val) {
obj[name] = val; // vue更新原理只更新一次,所以当更改多个值时只会有一个值更新的bug,所以通过obj收集修改的属性,emit统一处理
emit("update:" + propName, {
...target,
...obj,
[name]: val,
});
return true;
},
});
} else {
return props[propName];
}
},
set: (val) => {
emit("update:" + propName, val);
},
});
}

示例

定义一个组件Child,使用useVModel双向绑定
<script setup lang="ts">
import { useVModel } from "m-ui/hooks";
const props = defineProps({
model: {
type: Object,
default: () => ({
input: null,
select: null,
}),
},
});
const emit = defineEmits(["update:model"]);
const _model = useVModel(props, "model", emit);
</script>

<template>
<ms-space>
<ms-input v-model:value="_model.input" />
<ms-select
class="w-[200px]"
v-model:value="_model.select"
:options="[{ value: 'select', label: '下拉框' }]"
/>
</ms-space>
</template>
使用时通过v-model双向绑定
<script setup lang="ts">
import Child from "./Child.vue";
const model = ref({
input: "你好",
select: null,
});
const handleClick = () => {
console.log(model.value);
};
</script>

<template>
<ms-card>
<Child v-model:model="model" />
</ms-card>
<ms-button class="mt-4" type="primary" @click="handleClick">
打印model
</ms-button>
</template>

useChannel

多窗口/标签页通信, 创建一个频道,广播通知。

源码

/**
* @description useChannel-- 多窗口/标签页通信, 创建一个频道,广播通知
* @param {String} name 频道key
* @param {Function} onMessage (data) => void 接收消息后的回调
* @return {Object} { channel: BroadcastChannel; postMessage: (message: any) => void }
* @return {Object.channel} channel 实例对象
* @return {Object.postMessage} 广播消息的方法
* @date
* @author
*/

export function useChannel(
name: string,
onMessage: (data) => void
): { channel: BroadcastChannel; postMessage: (message: any) => void } {
const channel = new BroadcastChannel(name);
// 监听频道 message 事件,频道收到消息时触发 message 事件
channel.addEventListener("message", (e) => {
onMessage?.(e.data);
});
window.onbeforeunload = () => {
// 断开与频道的连接
channel.close();
};
return {
channel,
postMessage: (message) => {
channel.postMessage(message);
},
};
}

useWebSocket

建立一个WebSocket长连接

源码

/**
* @description useWebSocket--创建一个WebSocket连接
* @param {String} url 连接的url
* @param {Function} onMessage (data) => void 接收消息后的回调
* @date
* @author
*/

export function useWebSocket(
url: string,
onMessage: Function
): { initWebSocket: () => void } {
function initWebSocket() {
const ws = new WebSocket(`ws://${url}`);
ws.onopen = function () {
console.log("socket连接成功");
};
// 监听socket错误信息
ws.onerror = function () {
console.log("连接错误");
};
ws.onmessage = function (msg) {
console.log(msg.data);
onMessage && onMessage(msg);
};
ws.onclose = function () {
console.log("socket已经关闭");
setTimeout(reconnectWebSocket, 3000);
};
}
initWebSocket();
//重新连接webSocket
function reconnectWebSocket() {
initWebSocket(); //重新连接
}
return { initWebSocket };
}

useScheduler

接口调度,控制请求并发数。

/**
* @description useScheduler--接口调度,控制请求并发数
* @param {Number} count 最大并发数
* @date 12/01/2023
* @author bingao.liu
*/

export function useScheduler(count: number) {
return new Scheduler(count);
}

class Scheduler {
count: number;
queue: Array<any>;
run: Array<any>;
constructor(count: number) {
this.count = count;
this.queue = [];
this.run = [];
}

add(task: any) {
return new Promise((resolve, reject) => {
this.queue.push({ task, resolve, reject });
if (this.run.length < this.count) {
this._runTask();
}
});
}

_runTask() {
const { task, resolve, reject } = this.queue.shift();
this.run.push(task);
task()
.then(
(result: any) => {
resolve(result);
},
(error: any) => {
reject(error);
}
)
.finally(() => {
this.run.splice(this.run.indexOf(task), 1);
if (this.queue.length > 0) {
this._runTask();
}
});
}
}


原文始发于微信公众号(消失的程序员):Vue3常用的hooks方法1

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/250618.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!