首页
友链
壁纸
留言
今日热榜
更多
关于
时光
推荐
精品流量卡
Search
1
都二十多年了,你的梦为什么还没碎!
57,062 阅读
2
2022年5个好用的 BT/ 磁力链接下载工具推荐 |Windows 、安卓系统
37,220 阅读
3
nps内网穿透实现外网访问树莓派
32,390 阅读
4
实践利用宝塔建emlog个人博客-超详细【原创】
26,120 阅读
5
Typecho-Joe-Theme主题帮助文档
24,551 阅读
闲杂乱码
Python
网站源码
微信小程序
娱乐分享
Is相册
软件工具
登录
Search
标签搜索
PHP
HTML
API
Javascript
源码
JS
Vue
Github
CloudFlare
接口
函数
SQL
ASP.NET
MVC
EF
T4模板
后台管理
CDN
微信小程序
MAC
韩小韩
累计撰写
261
篇文章
累计收到
1,302
条评论
首页
栏目
闲杂乱码
Python
网站源码
微信小程序
娱乐分享
Is相册
软件工具
页面
友链
壁纸
留言
今日热榜
关于
时光
推荐
精品流量卡
搜索到
9
篇与
Vue
的结果
2023-07-29
Ant Design Vue 4.0 a-modal弹窗组件封装
父组件(部分)<template> <div class="main"> <a-button type="primary" ghost @click="dialogPanelStatus.signIngInfoStatus = true" >签约信息</a-button> </div> <!-- 签约信息 --> <SigningInfo :signIngInfoStatus="dialogPanelStatus.signIngInfoStatus" :walletData="walletData" @closeDialog="closeDialog" /> </template> <script setup lang="ts"> import SigningInfo from '@/components/Income/SigningInfo.vue'; // DIalog弹窗状态 const dialogPanelStatus = reactive<DialogPanelStatus>({ signIngInfoStatus: false }); // 数据重载 const getMyWalletFn = ()=>{ // 数据重载 } // 关闭弹窗 const closeDialog = (k: keyof DialogPanelStatus, rest: boolean) => { dialogPanelStatus[k] = false; rest && getMyWalletFn(true); }; </script> <style lang="less" scoped> @import 'Income.less'; </style>弹窗子组件<template> <a-modal :open="visible" title="弹框" :footer="null" destroyOnClose :maskClosable="false" @cancel="closeDialogFn(false)"> <div class="zb-info"> <a-card size="small" hoverable> <p>真实姓名:{{ walletData.real_name }}</p> </a-card> <a-card size="small" hoverable> <p>身份证号:{{ walletData.card_number }}</p> </a-card> <a-card size="small" hoverable> <p>支付宝账号:{{ walletData.alipay_account }}</p> </a-card> <a-card size="small" hoverable> <p>支付宝姓名:{{ walletData.alipay_name }}</p> </a-card> </div> </a-modal> </template> <script setup lang="ts"> import { toRefs } from 'vue'; import type { WalletData } from '@/types/index'; const props = withDefaults( defineProps<{ visible: Boolean; walletData: WalletData; }>(), {} ); const { visible, walletData } = toRefs(props); // 关闭弹窗 const emits = defineEmits(['closeDialog']); const closeDialogFn = (rest: boolean = false) => { emits('closeDialog', 'visibleStatus', rest); }; </script> <style lang="less" scoped> @import 'SigningInfo.less'; </style>
2023年07月29日
8,008 阅读
0 评论
0 点赞
2023-07-28
Vue3 + Vite + Vue Router 4后端返回路由配置动态路由权限管理
动态路由// 路由递归处理 const AllRouter = import.meta.glob('@/views/**/*.vue'); interface RouterItem { path: string; name: string; component: () => any; children?: RouterItem[]; meta: { title: string; icon: string; }; } const routerFormat = (routerList: any): RouterItem[] => { if (!routerList || !Array.isArray(routerList)) return []; return routerList.map((item: any) => { return { ...item, component: AllRouter[`/src/views/${item['component']}`], children: routerFormat(item['children']) }; }); }; // 动态路由挂载 const addDynamicRoutes = (layoutRoute: RouteRecordRaw | undefined, page: RouteLocationNormalizedLoaded) => { const newRouteStr = localStorage.getItem('routerList'); if (layoutRoute && newRouteStr && layoutRoute.children!.length < 1) { const newRouteArr = routerFormat(JSON.parse(newRouteStr) as RouteRecordRaw[]); layoutRoute.children = newRouteArr; router.addRoute(layoutRoute); router.push(page); } };路由守卫// 路由守卫 router.beforeEach(async (to, from, next) => { // 每次请求判断动态路由是否挂载 const layoutRoute: RouteRecordRaw | undefined = router.options.routes.find(route=> route.name === 'Layout'); addDynamicRoutes(layoutRoute, to); // 路由拦截规则 const TOKEN_STATIC: string | null = localStorage.getItem('session'); if (to.path === '/login' && TOKEN_STATIC) { next('/Layout'); } else { !TOKEN_STATIC && to.path !== '/login' ? next('/login') : next(); } });Login获取路由信息// 路由递归处理 const routerFormat = (routerList: any[]): any[] => { if (!routerList) return []; return routerList.map((item: any) => { return { path: item['url'], name: item['title'], component: item['component'], children: routerFormat(item['children']), meta: { title: item['title'], icon: item['ico'] } }; }); }; // 获取用户信息 const getUserInfoFn = async (session: any) => { localStorage.setItem('session', session); const res = await getUserInfo(); if (res.code == 0) { const routerList = routerFormat(res.data.router_list); localStorage.setItem('userInfo', JSON.stringify(res.data.user_info)); localStorage.setItem('routerList', JSON.stringify(routerList)); router.push({ name: 'Layout' }); } };
2023年07月28日
6,982 阅读
0 评论
2 点赞
2023-02-26
Vue底层判断标签的性能优化方法
在vue中,如果写div、span等正常的html标签,vue会解析成传统的html标签,但当写不是这些标签的时候,vue会认为他是一个组件,例如:<Custom></Custom>。是如何做到这种判断的呢,首先自己来实现一个这样的判断const tags = 'div,span,img,a'.split(",") function checkTag(tag) { return tags.some(item => item === tag) } console.log(checkTag('Custom')); // false console.log(checkTag('div')); // true console.log(checkTag('a')); // true这里的实现方案有很多,可以用for、some、forEach等,但是都是离不开循环,思考这样的一个问题,传入一个a,a在字符串最后一个位置,所以会循环4次来判断是否包含a,如果页面上的标签极多,甚至会有上万次的循环再来查看Vue实现这个的方式,大致源码如下const tags = 'div,span,img,a' function makeMap(str) { var map = Object.create(null); var list = str.split(','); for (var i = 0; i < list.length; i++) { map[list[i]] = true; } return function (val) { return map[val]; } } const isHtmlTag = makeMap(tags) isHtmlTag('div') isHtmlTag('Custom') isHtmlTag('a')这里可以看出,实现出一个柯里化函数,并且也是一个闭包状态。此时,在第一次调用时,会循环一次,后续不论在去判断什么标签,都不会再去循环,因为第一次的循环结果利用闭包已经存在了内存里,这就是闭包能带来的性能优化
2023年02月26日
2,477 阅读
0 评论
1 点赞
2023-02-18
Vue.set与this.$set源码
Vue.set()和this.$set()应用的场景在 Vue 2.X 项目开发中,有时候需要对数组进行修改,或是对对象新增一个属性,但是发现页面并不会同步更新。例如:const vm = new Vue({ data: { arr: [1, 2], obj: { a: 3 } } }); vm.$data.arr[0] = 3; // 页面不会发生改变 vm.$data.obj.b = 3; // 页面不会发生改变此时就需要使用到 Vue.set() 或 this.$set()。这个2个的使用方法一样,不过一个是挂载在Vue身上,一个挂载在Vue.prototype上// Vue.set import { set } from '../observer/index' Vue.set = set // this.$set import { set } from '../observer/index' Vue.prototype.$set = se使用Vue.set或this.$set来实现页面不更新的问题:const vm = new Vue({ data: { arr: [1, 2], obj: { a: 3 } } }); // 修改数组 Vue.set(vm.$data.arr, 0, 3); vm.$set(vm.$data.arr, 0, 3); // 对象新增属性 Vue.set(vm.$data.obj, 'b', 3); vm.$set(vm.$data.obj, 'b', 3);set函数的源代码../observer/indexfunction set (target: Array<any> | Object, key: any, val: any): any { // isUndef(target):用于判断传入的target是否是undefined或null // isPrimitive(target):用于判断传入的target是否是原始数据类型 // 如果是 null 或者是 undefined 时,抛出异常 if (process.env.NODE_ENV !== 'production' &&(isUndef(target) || isPrimitive(target))) { warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`) } // 如果传入了一个数组,并且传入的key是数组的有效值 if (Array.isArray(target) && isValidArrayIndex(key)) { // 用于设置数组的最大length // Math.max(target.length, key):取数组的length和key二者中的最大值 target.length = Math.max(target.length, key) // 直接调用数组身上的splice方法,因为Vue里变异了数组方法,调用会触发dep.notify() target.splice(key, 1, val) return val } // 接下来就是对象的判断了 // 如果传入的 key 在原对象中,说明已经是响应式了,直接修改即可 if (key in target && !(key in Object.prototype)) { target[key] = val return val } // 这里到最后的代码,都是对象不在原对象上,是新增的属性值 const ob = (target: any).__ob__ // 如果是Vue实例对象,或根数据对象,则抛出警告 if (target._isVue || (ob && ob.vmCount)) { process.env.NODE_ENV !== 'production' && warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.' ) return val } // 如果没有 __ob__ 表示当前 target 不是响应式的,那么直接赋值 if (!ob) { target[key] = val return val } // 剩下就是给响应式对象增加一个 key 新属性,并通知更新 defineReactive(ob.value, key, val) ob.dep.notify() return val }
2023年02月18日
2,259 阅读
0 评论
0 点赞
2023-02-03
Vue 2与Vue 3在自定义组件v-model上的区别
{callout color="#f0ad4e"}在vue开发中,通常会对一个自定义的组件进行封装,并实现v-model双向绑定功能{/callout}在 Vue 2 中,通常这样实现父组件<template> <Child v-model="number"></Child> </template> <script> export default { data() { return { number: 0 } }, components: { Child: () => import("./Child.vue") } } </script>子组件<template> <button @click="handleClick">{{ value }}</button> </template> <script> export default { props: { value: Number }, methods: { handleClick() { // 通过emit一个input事件出去,实现 v-model this.$emit('input', this.value + 1) } } } </script>在 vue 3 中,通过这样实现父组件<template> <Child v-model="number"></Child> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; export default defineComponent({ setup() { const number = ref(0); return { number }; }, }); </script>子组件<template> <button @click="handleClick">{{ value }}</button> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ props: { // 更换成了 modelValue modelValue: Number }, setup(props, { emit }) { // 关闭弹出层 const handleClick = () => emit('update:modelValue', props.modelValue + 1); return { handleClick }; }, }); </script>
2023年02月03日
2,475 阅读
0 评论
1 点赞
2022-12-06
今日热榜HotList-Web前端开源Vue - (聚合热榜)
{message type="info" content="每日热榜前端配合后端(韩小韩聚合热榜API)一起使用,后端源接口为官方接口。"/}环境需求Nodejs >14.1.0使用框架VueElement-UI页面AND源码截图{gird column="2" gap="15"}{gird-item} {/gird-item}{gird-item}{/gird-item}{/gird}源码地址{cloud title="HotList-Web" type="github" url="https://github.com/uxiaohan/HotList-Web" password=""/}{callout color="#f0ad4e"}后端配合 韩小韩API 聚合热榜API 使用.或者自建API使用.源码自行编译 或 直接上传 dist文件夹内已编译文件.{/callout}成品演示{abtn icon="fa-link" color="#ff6800" href="https://hot.vvhan.com/" radius="" content="今日热榜 HotList-Web"/} {abtn icon="fa-link" color="#00d5ff" href="https://api.vvhan.com/hotlist.html" radius="" content="韩小韩API 聚合热榜API"/}希望给个 Star 😬
2022年12月06日
1,238 阅读
2 评论
8 点赞
2022-07-06
JS正则常用校验大全(精华篇)
手机号(mobile phone)中国(严谨), 根据工信部2019年最新公布的手机号段const reg = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/; const str = "19119255642"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);email(邮箱)const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const str = "90203918@qq.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);座机(tel phone)电话(国内),如: 0341-86091234const reg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/; const str = "0936-4211235"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);身份证号(2代,18位数字),最后一位是校验位,可能为数字或字符Xconst reg = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/; const str = "12345619991205131x"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文姓名const reg = /^(?:[\u4e00-\u9fa5·]{2,16})$/; const str = "韩小韩"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);英文姓名const reg = /(^[a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]$)/; const str = "James Han"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);网址(URL)const reg = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/; const str = "https://www.vvhan.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);必须带端口号的网址(或ip)const reg = /^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/; const str = "https://www.vvhan.com:80"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);银行卡号(10到30位, 覆盖对公/私账户, 参考[微信支付]const reg = /^[1-9]\d{9,29}$/; const str = "6222026006705354000"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线组合const reg = /^[a-zA-Z]\w{4,15}$/; const str = "han_666666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文/汉字const reg = /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/; const str = "韩小韩博客"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);密码强度校验,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符const reg = /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/; const str = "han@666vvx,"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);微信号(wx),6至20位,以字母开头,字母,数字,减号,下划线const reg = /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/; const str = "kd_-666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);邮政编码(中国)const reg = /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/; const str = "734500"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文和数字const reg = /^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/; const str = "韩小韩好6啊"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);匹配连续重复的字符const reg = /(.)\1+/; const str = "112233"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);统一社会信用代码const reg = /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/; const str = "91110108772551611J"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);子网掩码(不包含 0.0.0.0)const reg = /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(255|254|252|248|240|224|192|128|0)$/; const str = "255.255.255.0"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z](?:((\d{5}[A-HJK])|([A-HJK][A-HJ-NP-Z0-9][0-9]{4}))|[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳])$/; const str = "京AD92035"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(非新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A00599"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源+非新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A12345D"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);护照(包含香港、澳门)const reg = /(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/; const str = "s28233515"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);
2022年07月06日
1,106 阅读
7 评论
2 点赞
2022-07-04
Vue项目element组件遇到的坑(记录篇持续更新)
Input数字输入框<!-- 一般情况使用 type="number"存在问题:数字可为负数,且出现上增下减箭头 --> <el-input v-model="input" placeholder="请输入内容" type="number"></el-input> <!-- 我的解决方案 - Perfect --> <el-input v-model="input" placeholder="请输入内容" oninput="value=value.replace(/[^0-9]/g,'')"></el-input>JS校验判断姓名const reg = /^[\u4e00-\u9fa5]{2,8}$/; const name = '呜哈哈1'; console.log(`姓名校验 ${reg.test(name)?'正确':'错误'}`);JS校验判断手机号const reg = /^1[3|4|5|7|8]\d{9}$/; const mobil = '1525222222'; console.log(`手机号校验 ${reg.test(mobil)?'正确':'错误'}`);JS校验判断身份证号码const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/; const userNum = '320333199806060011X'; console.log(`身份证号码校验 ${reg.test(userNum)?'正确':'错误'}`);
2022年07月04日
489 阅读
2 评论
2 点赞
1
2