首页
统计
赞助
留言
关于
更多
友链
壁纸
直播
Search
1
Joe — 一款个人类型Typecho主题
32,346 阅读
2
Joe开源目录程序系统
11,900 阅读
3
Typecho自定义后台编辑器功能
8,305 阅读
4
Joe主题实现自动更新
7,555 阅读
5
Joe主题自定义搭配色教程
4,451 阅读
WEB前端
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
小程序
苹果CMS
其他
生活
登录
Search
https://78.al
累计撰写
76
篇文章
累计收到
3,730
条评论
首页
栏目
WEB前端
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
小程序
苹果CMS
其他
生活
页面
统计
赞助
留言
关于
友链
壁纸
直播
搜索到
55
篇与
WEB前端
的结果
2021-02-24
JS封装下载blob类型文件的函数
export const downloadFile = (blob, fileName) => { let a = document.createElement('a'); a.href = window.URL.createObjectURL(blob); a.download = fileName; a.click(); };
2021年02月24日
627 阅读
3 评论
6 点赞
2021-02-23
JS正则限制只能输入数字、或带小数点的数字,并且小数后面限制多少位
length 代表如果输入含小数位的时候,小数位的个数const length = 2 const reg = new RegExp(`^\\d+(\\.\\d{1,${length}})?$`)
2021年02月23日
640 阅读
2 评论
3 点赞
2021-02-22
Object.defineProperty与Proxy的使用
这个方法的主要用处是用来做数据劫持的,在vue2.x主要使用这个方法,在3.0中换成了proxy做数据劫持,数据劫持就是监听到数据的变化,然后可以做什么等Object.defineProperty/* 随便定义一个对象 */ let obj = { name: 'hello', age: 18, child: { sex: '女' } } observer(obj) function observer(obj) { /* 判断传入进来的是否是对象 */ if (obj.constructor === Object) { /* 循环对象 */ for (let key in obj) { /* 如果值不是对象,则做劫持 */ if (obj[key].constructor !== Object) { /* 定义一个临时变量,用于return出去 */ let _value = obj[key] Object.defineProperty(obj, key, { /* 设置属性可以被删除,可以被修改 */ configurable: true, /* 设置属性可以被遍历 */ enumerable: true, get() { console.log('触发读取') return _value }, set(newVal) { console.log('触发修改') _value = newVal } }) } else { /* 否则进行递归,再次判断 */ observer(obj[key]) } } } }Proxylet obj = { name: '小红', age: 1 } obj = new Proxy(obj, { get(target, key) { console.log(target) console.log(key) }, set(target, key, newVal) { console.log(target) console.log(key) console.log(newVal) } }) console.log(obj)
2021年02月22日
259 阅读
2 评论
3 点赞
2021-02-21
简单的模拟Vue替换插值表达式的功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="app"> {{ msg }}111{{ msg }} <div>{{msg}}</div> </div> <script> class Vue { constructor(options) { this.options = options /* 初始化编译dom */ this.compile() } compile() { let el = document.querySelector(this.options.el) if (!el) return console.warn('element not exist!') let childNodes = el.childNodes /* 递归编译节点 */ childNodes.length && this.compileNodes(childNodes) } compileNodes(childNodes) { /* 循环节点 */ childNodes.forEach(node => { /* 如果是文本节点,则进行替换插值表达式 */ if (node.nodeType === 3) { let reg = /\{\{\s*([^\{\{\}\}\s]+)\s*\}\}/g if (reg.test(node.textContent)) { /* $1就是插值表达式里面的属性值 */ let $1 = RegExp.$1 node.textContent = node.textContent.replace(reg, this.options.data[$1]) } } else { /* 如果不是文本节点,则进行递归,并且有子节点 */ node.childNodes.length && this.compileNodes(node.childNodes) } }) } } new Vue({ el: '#app', data: { msg: '测试数据' } }) </script> </body> </html>
2021年02月21日
258 阅读
0 评论
3 点赞
2021-02-20
自行封装一个深拷贝的函数
在实际项目中,经常使用到深拷贝,索性封装成一个函数function deepCopy(obj) { // 1、为了兼容数组和对象,所以写一个兼容性赋值 let newObj = Array.isArray(obj) ? [] : {} // 2、接下来进行循环传进来的对象 (for...in...也会循环原型链上的内容) for(let key in obj) { // 3、因为for...in会循环原型链上的内容,而我们深拷贝的新对象无需原型链上的内容,因此加一层原型链判断 if(obj.hasOwnProperty(key)) { // 判断是非原型上的数据 // 4、接着判断是复杂数据类型,还是基本数据类型,如果是基本数据类型,直接赋值就行 if(typeof(obj[key]) !== 'object') { // 基本数据类型 newObj[key] = obj[key] } else { // 复杂数据类型,递归再次进行判断 newObj[key] = deepCopy(obj[key]) } } } return newObj } // 接着验证上面函数 let obj = { name: 'lis', fn: () => { console.log(1) }, child: { age: 1, son: [] } } let newObj = deepCopy(obj) console.log(newObj)
2021年02月20日
299 阅读
2 评论
8 点赞
2021-02-20
为你的网站添加点击散开特效
将以下代码复制到你网站最底部即可实现<canvas id="fireworks" style="position: fixed; left: 0px; top: 0px; pointer-events: none; z-index: 2147483647; width: 1920px; height: 151px;" width="3840" height="302"></canvas> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/animejs@3.0.1/lib/anime.min.js"></script> <script type="text/javascript"> function updateCoords(e) { pointerX = (e.clientX || e.touches[0].clientX) - canvasEl.getBoundingClientRect().left, pointerY = e.clientY || e.touches[0].clientY - canvasEl.getBoundingClientRect().top } function setParticuleDirection(e) { var t = anime.random(0, 360) * Math.PI / 180, a = anime.random(50, 180), n = [-1, 1][anime.random(0, 1)] * a; return { x: e.x + n * Math.cos(t), y: e.y + n * Math.sin(t) } } function createParticule(e, t) { var a = {}; return a.x = e, a.y = t, a.color = colors[anime.random(0, colors.length - 1)], a.radius = anime.random(16, 32), a.endPos = setParticuleDirection(a), a.draw = function() { ctx.beginPath(), ctx.arc(a.x, a.y, a.radius, 0, 2 * Math.PI, !0), ctx.fillStyle = a.color, ctx.fill() }, a } function createCircle(e, t) { var a = {}; return a.x = e, a.y = t, a.color = "#F00", a.radius = .1, a.alpha = .5, a.lineWidth = 6, a.draw = function() { ctx.globalAlpha = a.alpha, ctx.beginPath(), ctx.arc(a.x, a.y, a.radius, 0, 2 * Math.PI, !0), ctx.lineWidth = a.lineWidth, ctx.strokeStyle = a.color, ctx.stroke(), ctx.globalAlpha = 1 }, a } function renderParticule(e) { for (var t = 0; t < e.animatables.length; t++) e.animatables[t].target.draw() } function animateParticules(e, t) { for (var a = createCircle(e, t), n = [], i = 0; i < numberOfParticules; i++) n.push(createParticule(e, t)); anime.timeline().add({ targets: n, x: function(e) { return e.endPos.x }, y: function(e) { return e.endPos.y }, radius: .1, duration: anime.random(1200, 1800), easing: "easeOutExpo", update: renderParticule }).add({ targets: a, radius: anime.random(80, 160), lineWidth: 0, alpha: { value: 0, easing: "linear", duration: anime.random(600, 800) }, duration: anime.random(1200, 1800), easing: "easeOutExpo", update: renderParticule, offset: 0 }) } function debounce(fn, delay) { var timer return function() { var context = this var args = arguments clearTimeout(timer) timer = setTimeout(function() { fn.apply(context, args) }, delay) } } var canvasEl = document.querySelector("#fireworks"); if (canvasEl) { var ctx = canvasEl.getContext("2d"), numberOfParticules = 30, pointerX = 0, pointerY = 0, tap = "mousedown", colors = ["#FF1461", "#18FF92", "#5A87FF", "#FBF38C"], setCanvasSize = debounce(function() { canvasEl.width = 2 * window.innerWidth, canvasEl.height = 2 * window.innerHeight, canvasEl.style.width = window.innerWidth + "px", canvasEl.style.height = window.innerHeight + "px", canvasEl.getContext("2d").scale(2, 2) }, 500), render = anime({ duration: 1 / 0, update: function() { ctx.clearRect(0, 0, canvasEl.width, canvasEl.height) } }); document.addEventListener(tap, function(e) { "sidebar" !== e.target.id && "toggle-sidebar" !== e.target.id && "A" !== e.target.nodeName && "IMG" !== e.target.nodeName && (render.play(), updateCoords(e), animateParticules(pointerX, pointerY)) }, !1), setCanvasSize(), window.addEventListener("resize", setCanvasSize, !1) } </script>
2021年02月20日
1,276 阅读
7 评论
22 点赞
2021-02-20
Vue中解决对象内存地址一致的几种方案
在开发vue项目中,经常会遇到内存地址一样的问题,导致修改这里,另一处同时发生改变解决方案:1、利用JSON方法(极其不推荐,会丢失属性,例如函数、undefined)let obj = {} let newObj = JSON.parse(JSON.stringify(obj))2、深拷贝3、利用Object.assig方法export default { data() { return { test: {} } }, methods: { change(obj) { this.test = Object.assign({}, obj) } } }4、利用对象展开运算符let obj1 = { a: 1, b: 2 } let obj2 = {...obj1}
2021年02月20日
196 阅读
0 评论
1 点赞
2021-02-20
JS封装获取文件大小的函数
封装的函数function formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i]; }使用方法formatBytes(file.size, decimals = 2)
2021年02月20日
241 阅读
0 评论
3 点赞
2021-02-20
Vue中this.$options.data() 重置data里的数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <button @click="btnClick">click</button> <button @click="btnReset">reset</button> <p><input type="text" v-model="message"></p> <p>{{message}}</p> </div> <script src="./vue.js"></script> <script> let vm = new Vue({ el: "#app", data() { return { message: '' } }, methods: { btnClick() { this.message = 'bbbbbbbbbb' }, btnReset() { Object.assign(this.$data, this.$options.data.call(this)) } }, }) </script> </body> </html>
2021年02月20日
295 阅读
0 评论
3 点赞
2021-02-20
-webkit-box-orient属性编译时被删除时的解决办法
例如打包编译如下scss代码时,会将-webkit-box-orient属性删除掉display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;解决办法,在该属性的前后加上防编译注释display: -webkit-box; -webkit-line-clamp: 3; /*! autoprefixer: off */ -webkit-box-orient: vertical; /* autoprefixer: on */ overflow: hidden; text-overflow: ellipsis;
2021年02月20日
427 阅读
0 评论
2 点赞
2021-02-20
Vue解决路由重复点击报错的问题
router.js文件// 加上这个 const originalPush = Router.prototype.push; Router.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) }
2021年02月20日
252 阅读
0 评论
2 点赞
2021-02-20
原生JS实现一个验证码功能
定义一个用于显示验证码的canvas<canvas width="100" height="40"></canvas>生成JS的业务逻辑// 获取canvas let canvas = document.querySelector("canvas") let context = canvas.getContext("2d"); // 定义初始化验证码内容 let nums = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R','S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x','y', 'z']; drawCode() // 绘制验证码 function drawCode() { context.beginPath() /* 绘制背景色 */ context.fillStyle = "cornflowerblue"; context.fillRect(0, 0, canvas.width, canvas.height) /* 绘制验证码 */ context.fillStyle = "white"; context.font = "25px Arial"; let rand = [], x = [], y = [] for (let i = 0; i < 5; i++) { rand[i] = nums[Math.floor(Math.random() * nums.length)] x[i] = i * 16 + 10; y[i] = Math.random() * 20 + 20; context.fillText(rand[i], x[i], y[i]); } /* rand就是生成后的结果, 后面用来判断验证码输入框是否与该值相等 */ console.log(rand); //画3条随机线 for (let i = 0; i < 3; i++) { drawline(canvas, context); } // 画30个随机点 for (let i = 0; i < 30; i++) { drawDot(canvas, context); } } // 随机线 function drawline(canvas, context) { //随机线的起点x坐标是画布x坐标0位置,y坐标是画布高度的随机数 context.moveTo(Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height)); //随机线的终点x坐标是画布宽度,y坐标是画布高度的随机数 context.lineTo(Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height)); context.lineWidth = 0.5; context.strokeStyle = 'rgba(50,50,50,0.3)'; context.stroke(); } // 随机点 function drawDot(canvas, context) { let px = Math.floor(Math.random() * canvas.width); let py = Math.floor(Math.random() * canvas.height); context.moveTo(px, py); context.lineTo(px + 1, py + 1); context.lineWidth = 0.2; context.stroke(); }
2021年02月20日
672 阅读
6 评论
6 点赞
1
...
3
4
5