首页
工具
心境语句
相册
建站轨迹
关于
Search
1
微信小程序:计算属性的两种体现方式及应用场景
1,594 阅读
2
Antd Upload 组件上传文件接收数据流并下载
1,059 阅读
3
C#插件火车头采集器动态切换代理IP,及自动切换UserAgent
542 阅读
4
[C#]使用dnSpy对目标程序(EXE或DLL)进行反编译修改并编译运行
536 阅读
5
ADODB.Connection 错误 800a0e7a 未找到提供程序。该程序可能未正确安装解决方法
499 阅读
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
累计撰写
74
篇文章
累计收到
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日
88 阅读
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,059 阅读
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日
59 阅读
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日
205 阅读
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日
306 阅读
0 评论
0 点赞
1
2