首页
工具
心境语句
相册
建站轨迹
关于
Search
1
微信小程序:计算属性的两种体现方式及应用场景
1,652 阅读
2
Antd Upload 组件上传文件接收数据流并下载
1,172 阅读
3
unlock-music工具介绍
658 阅读
4
[C#]使用dnSpy对目标程序(EXE或DLL)进行反编译修改并编译运行
653 阅读
5
C#插件火车头采集器动态切换代理IP,及自动切换UserAgent
627 阅读
react
typecho
ASP
Centos
MYSQL
PHP
Sql server
Javascript
nodejs
数据采集
.NET
git
编程算法
管理及流程
Vue
微信小程序
android
python
mongodb
登录
Search
标签搜索
kotlin
node-sass
nuxtjs
C#火车头插件
火车头采集器
火车头代理
C#反编译
程序逆向
dnSpy教程
Antd
InputNumber
NPM教程
NPM命令
rrweb教程
git慢
git镜像
vim命令
git命令
网页音乐插件
网页播放器
Elysian
累计撰写
75
篇文章
累计收到
0
条评论
首页
栏目
react
typecho
ASP
Centos
MYSQL
PHP
Sql server
Javascript
nodejs
数据采集
.NET
git
编程算法
管理及流程
Vue
微信小程序
android
python
mongodb
页面
工具
心境语句
相册
建站轨迹
关于
搜索到
6
篇与
Javascript
的结果
2022-03-16
开发工具集合
JAVASCRIPT工具LodashLodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。Lodash 遵循 MIT 开源协议发布,并且支持最新的运行环境。 查看各个构件版本的区别并选择一个适合你的版本。https://www.lodashjs.com/
2022年03月16日
98 阅读
0 评论
0 点赞
2021-10-22
Antd Upload 组件上传文件接收数据流并下载
一、应用场景主要是需要上传一个PDF文件,然后服务器会针对PDF文件,转换成WORD文件,然后返回WORD文件的下载流。二、解决方法1、默认情况下Antd的Upload组件上传文件后接收服务端返回的字符串,再返回给fileList,如果服务端返回二进制文件流,则Upload组件接收的也是二进制流的乱码字符串。2、JS接收流文件然后提供下载,主流是使用 blob对象 来将流转变为blob地址,然后提供下载。3、Ajax默认情况下,如果不设置responseType为blob则返回的内容就是字符串,但是直接返回的二进制流,转换成 blob对象 会造成数据损坏,查了资料说是utf8编码等之类的问题引起的,所以就需要设置 responseType='blob' 或者是 'arraybuffer' 然后转换为 blob对象 。4、antd的Upload组件,正好提供了一个 customRequest 属性可以自定义ajax请求。基于上述4点,我们只需要修改组件的 customRequest属性,就可以实现应用场景具体customRequest属性代码如下:customRequest(option) { const getError = (option, xhr) => { var msg = "cannot ".concat(option.method, " ").concat(option.action, " ").concat(xhr.status, "'"); var err = new Error(msg); err.status = xhr.status; err.method = option.method; err.url = option.action; return err; } const getBody = (xhr) => { debugger; if (xhr.responseType && xhr.responseType !== 'text') { return xhr.response; } var text = xhr.responseText || xhr.response; if (!text) { return text; } try { return JSON.parse(text); } catch (e) { return text; } } // eslint-disable-next-line no-undef var xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; if (option.onProgress && xhr.upload) { xhr.upload.onprogress = function progress(e) { if (e.total > 0) { e.percent = e.loaded / e.total * 100; } option.onProgress(e); }; } // eslint-disable-next-line no-undef var formData = new FormData(); if (option.data) { Object.keys(option.data).forEach(function (key) { var value = option.data[key]; // support key-value array data if (Array.isArray(value)) { value.forEach(function (item) { // { list: [ 11, 22 ] } // formData.append('list[]', 11); formData.append("".concat(key, "[]"), item); }); return; } formData.append(key, option.data[key]); }); } // eslint-disable-next-line no-undef if (option.file instanceof Blob) { formData.append(option.filename, option.file, option.file.name); } else { formData.append(option.filename, option.file); } xhr.onerror = function error(e) { option.onError(e); }; xhr.onload = function onload() { // allow success when 2xx status // see https://github.com/react-component/upload/issues/34 if (xhr.status < 200 || xhr.status >= 300) { return option.onError(getError(option, xhr), getBody(xhr)); } return option.onSuccess(getBody(xhr), xhr); }; xhr.open(option.method, option.action, true); // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179 if (option.withCredentials && 'withCredentials' in xhr) { xhr.withCredentials = true; } var headers = option.headers || {}; // when set headers['X-Requested-With'] = null , can close default XHR header // see https://github.com/react-component/upload/issues/33 if (headers['X-Requested-With'] !== null) { xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } Object.keys(headers).forEach(function (h) { if (headers[h] !== null) { xhr.setRequestHeader(h, headers[h]); } }); xhr.send(formData); return { abort: function abort() { xhr.abort(); } }; },修改上述属性后,则onChange等方法接收到的file或者fileList中的response则变为blob对象,然后将blob对象输出url放到对应的下载标签中就可以了。
2021年10月22日
1,172 阅读
0 评论
0 点赞
2021-10-14
JS异步之宏任务和微任务
.宏任务(macrotask )和微任务(microtask )macrotask 和 microtask 表示异步任务的两种分类。在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。掘金上面盗张图记录一下宏任务和微任务之间的关系先看个例子setTimeout(() => { //执行后 回调一个宏事件 console.log('内层宏事件3') }, 0) console.log('外层宏事件1'); new Promise((resolve) => { console.log('外层宏事件2'); resolve() }).then(() => { console.log('微事件1'); }).then(()=>{ console.log('微事件2') })我们看看打印结果{card-describe title="结果"}外层宏事件1外层宏事件2微事件1微事件2内层宏事件3{/card-describe}首先浏览器执行js进入第一个宏任务进入主线程, 遇到 setTimeout 分发到宏任务Event Queue中遇到 console.log() 直接执行 输出 外层宏事件1遇到 Promise , new Promise 直接执行 输出 外层宏事件2执行then 被分发到微任务Event Queue中第一轮宏任务执行结束,开始执行微任务 打印 '微事件1' '微事件2'第一轮微任务执行完毕,执行第二轮宏事件,打印setTimeout里面内容'内层宏事件3'宏任务#浏览器NodesetTimeout√√setInterval√√setImmediatex√requestAnimationFrame√x微任务#浏览器Nodeprocess.nextTickx√MutationObserver√xPromise.then catch finally√√这个例子看懂基本js执行机制就理解了//主线程直接执行 console.log('1'); //丢到宏事件队列中 setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5') }) }) //微事件1 process.nextTick(function() { console.log('6'); }) //主线程直接执行 new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { //微事件2 console.log('8') }) //丢到宏事件队列中 setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12') }) })首先浏览器执行js进入第一个宏任务进入主线程, 直接打印 console.log('1')遇到 setTimeout 分发到宏任务Event Queue中遇到 process.nextTick 丢到微任务Event Queue中遇到 Promise , new Promise 直接执行 输出 console.log('7') ;执行then 被分发到微任务Event Queue中第一轮宏任务执行结束,开始执行微任务 打印 6,8第一轮微任务执行完毕,执行第二轮宏事件,执行 setTimeout先执行主线程宏任务,在执行微任务,打印'2,4,3,5'在执行第二个 setTimeout ,同理打印 ‘9,11,10,12’整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。以上是在浏览器环境下执行的数据,只作为宏任务和微任务的分析,我在node环境下测试打印出来的顺序为:1,7,6,8,2,4,9,11,3,10,5,12。node环境执行结果和浏览器执行结果不一致的原因是:浏览器的Event loop是在HTML5中定义的规范,而node中则由libuv库实现。libuv库流程大体分为6个阶段:timers,I/O callbacks,idle、prepare,poll,check,close callbacks,和浏览器的microtask,macrotask那一套有区别。文章转载来自:https://www.cnblogs.com/wangziye/p/9566454.html
2021年10月14日
88 阅读
0 评论
0 点赞
2021-09-25
Aplayer搭配Metingjs音乐插件的使用
1. Aplayer和MetingJ的介绍Aplayer官网文档:https://aplayer.js.org/#/Metingjs官网文档:https://github.com/metowolf/MetingJSAplayer是一个功能强大的HTML5音乐播放器,Metingjs基于Aplayer插件封装好的插件,开箱即用。2. MetingJS的简单使用MetingJS支持Aplayer版本VersionAPI StatusAPlayer1.2.xSupported1.10.02.0.xLatest1.10.0支持的浏览器ChromeFirefoxSafariInternet Explorer 11Microsoft Edge简单使用<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <!-- require APlayer --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css"> <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script> <!-- require MetingJS --> <script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script> </head> <body> <meting-js server="netease" type="playlist" id="60198"></meting-js> </body> </html>解析:server="netease" type="playlist" id="60198" server指音乐平台,netease指网易云音乐, type类型,playlist列表,id指歌曲的i或者专辑或列表外链id 因此重点在于指定平台,指定外链id中文版选项选项 默认 描述id(编号) require 歌曲ID /播放列表ID /专辑ID /搜索关键字server(平台) require 音乐平台:netease,tencent,kugou,xiami,baidutype(类型) require song,playlist,album,search,artistauto(支持类种 类) options 音乐链接,支持:netease,tencent,xiamifixed(固定模式) false 启用固定模式,默认falsemini(迷你模式) false 启用迷你模式,默认falseautoplay(自动播放) false 音频自动播放,默认falsetheme(主题颜色) #2980b9 默认#2980b9loop(循环) all 播放器循环播放,值:“all”,one”,“none”order(顺序) list 播放器播放顺序,值:“list”,“random”preload(加载) auto 值:“none”,“metadata”,“'auto”volume(声量) 0.7 默认音量,请注意播放器会记住用户设置,用户自己设置音量后默认音量将不起作用mutex(限制) true 防止同时播放多个玩家,在该玩家开始播放时暂停其他玩家lrc-type(歌词) 0 歌词显示list-folded(列表折叠) false 指示列表是否应该首先折叠list-max-height(最大高度) 340px 列出最大高度storage-name(储存名称) metingjs 存储播放器设置的localStorage键3. 迷你版背景音乐根据以上参数,写好了迷你版背景音乐,默认在左下角显示,默认列表折叠,默认不显示<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <!-- require APlayer --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css"> <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script> <!-- require MetingJS --> <script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script> </head> <body> <meting-js server="netease" type="playlist" id="60198" fixed="true" autoplay="true" loop="all" order="random" preload="auto" list-folded="ture" list-max-height="500px" lrc-type="1"> </meting-js> </body> </html>抽取出来<!--css--> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css"> <!--js--> <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script> <!--使用--> <meting-js server="netease" type="playlist" id="60198" fixed="true" autoplay="true" loop="all" order="random" preload="auto" list-folded="ture" list-max-height="500px" lrc-type="1"> </meting-js>4. 网易云音乐外链获取方法1、打开网页版网易云音乐:https://music.163.com/#2、选择想要添加到音乐列表去的音乐,由于部分歌曲限制外链,只能另辟蹊径3、打开网页控制台4、选中外链元素5、复制该行代码<a data-action="outchain" data-rt="" data-href="/outchain/2/1400256289/" class="des s-fc7">生成外链播放器</a>6、取data-href的链接,前面加上https://music.163.com/#进行拼接7、访问:https://music.163.com/#/outchain/2/1400256289/,获取id成功5. 网易云音乐个人歌单id获取登陆个人网易云音乐,打开歌单,查看浏览器地址,id后面就是歌单6. 博客园引用背景音乐<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css"> <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script> <div> <meting-js server="netease" type="playlist" id="60198" fixed="true" autoplay="true" loop="all" order="random" preload="auto" list-folded="ture" list-max-height="500px" lrc-type="1"> </meting-js> </div>
2021年09月25日
253 阅读
0 评论
0 点赞
2021-09-16
web操作录制神器rrweb实现页面录像
rrweb适用场景:用户行为分析;远程debug;录制操作;实时协作;项目github:https://github.com/rrweb-io/rrweb ,觉得有用,记得帮他加个星~官网:https://www.rrweb.io/开搞!第一步:引入rrweb<script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"></script>第二步:开始录制// rrweb行为录制 let events = []; rrweb.record({ emit(event) { // 用任意方式存储 event console.log(event); events.push(event); }, });第三步:存储录制数据(本例采用php后台存储)// save 函数用于将 events 发送至后端存入,并重置 events 数组 function save() { if(events.length == 0){return;} const body = JSON.stringify({ events }); events = []; $.ajax({ type: "POST", url: "http://192.168.0.198:8067/index.php?s=v1/webtools", //访问的链接 dataType: 'text', data:{ token:"token_xxx", motion:body }, success:function(res){ //成功的回调函数 var data = JSON.parse(res); console.log(data.code); }, error: function (e) { } }); } // 每 10 秒调用一次 save 方法,避免请求过多 setInterval(save, 10 * 1000); (备注:后台php+mysql,代码省略。)录制数据已经存储好了,如何查看录像?请继续,第四步:查看录像<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css"/> <script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script> <script type="text/javascript" src="../js/jquery-3.2.0.min.js"></script> </head> <body> <p>this a test page --- test1.html --- rrweb录像演示</p> <button id="btn"> 开始演示</button><br> <script type="text/javascript"> document.querySelector("#btn").onclick = function(){ let token = 'xxxtokenxxx'; $.ajax({ type: "GET", url: "http://192.168.0.198:8067/index.php?s=v1/webtools/"+ token, //访问的链接 dataType: 'text', success:function(res){ //成功的回调函数 var events = JSON.parse(res); new rrwebPlayer({ target: document.body, // 可以自定义 DOM 元素 data: { events, }, }); }, error: function (e) { console.log("error"); } }); } </script> </body> </html>据了解,这套工具是参考LogRocket开发的。本文转至:https://blog.csdn.net/blackcat88/article/details/88972515官网文档:https://blog.csdn.net/blackcat88/article/details/88972515https://github.com/rrweb-io/rrweb下面是rrweb的原理介绍地址: rrweb:打开 web 页面录制与回放的黑盒子
2021年09月16日
412 阅读
0 评论
0 点赞
1
2