关于javascript:复习学习-闭包

明天的内容其实挺有重量的,首先我要说一下明天是温习的最初一天,过后学到这里就断了,心田有点小冲动,因为终于完结了温习的苦楚,还是承受新常识比拟有能源,明天的内容也是挺够重量的是一些对于闭包、递归、以及函数的办法的一些利用 1、 先来一个开胃小菜,es5新增的扭转this指向的一个办法,bind,我感觉他与另外两个不同,认为他不会被调用,刚开始意识我还认为这个用的起码应该,其实才察觉这才是大哥,他用的最多,他的一个案例也很经典,点击一个按钮,点过后就禁用三秒后就须要回到能够点击的状态,对于定时器的this指向问题,在正文外面也说了 <!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> <button>点击</button> <script> var btn = document.querySelector('button') btn.addEventListener('click', function() { this.disabled = true setTimeout(function() { this.disabled = false }.bind(this),3000) // 这里不能用call apply 因为这里不能立刻执行 什么叫做立刻执行 也就是当运行完禁用按钮过后运行定时器的时候 不必期待立刻执行 所以就看不到咱们须要的成果 所以这里就要利用bind来达到即实现了扭转this又不会立刻执行 }) </script></body></html>2. 而后明天的第二个案例是对于闭包的,点击li输入索引号,感觉与闭包打交道最多的明天哈,根本都是解决一些回调函数的异步问题 <!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> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> // 以前的办法就增加类名点哪个取哪个即可,当初要用闭包的想法实现 var lis = document.querySelectorAll('li') for (var i = 0; i < lis.length; i++) { /* 这里间接输入i是不行的,为什么不行因为这关乎到一个同步与异步工作的状况,后面的for循环是同步工作,最先执行完,而异步工作也就是 回调函数,典型的事件、定时器、ajax这三个必须等到同步工作执行完了才回去执行异步工作,所以这里间接输入i的话只会失去最初一个i 这里不必以前老办法,那就须要用到闭包的利用了,for循环四次那就失去四个立刻执行函数,把i传进去,再在外面绑定事件,接管i的值 */ (function(i) { lis[i].onclick = function() { console.log(i); // 还有这里是有闭包的产生的,用到了局部变量i } })(i) } </script></body></html>3. ...

September 29, 2022 · 2 min · jiezi

关于javascript:BS结构下使用JS开发NFC读写器

随着NFC读写器在BS架构下的需要越来越多,应用JS语言在web浏览器下操作NFC读写器就变得尤其重要.然而web浏览器不容许其显示内容间接操作硬件,所以咱们必须应用IC卡读卡器web插件来实现这个性能.作为web前端工程师,咱们首先要理解在web中实现操作NFC读写器的步骤:1、下载友我科技IC卡读卡器web插件。2、插上NFC读写器YW-607HC。3、能够应用JS开发了。3.1、在web页面中引入js申明文件YOWOCloudRFIDReader.js, <script language="javascript" src="http://127.0.0.1:8008/YOWOCloudRFIDReader.js"></script>3.2、在引入申明文件后,就能够创立读写器操作的object。也能够间接下载YOWOReaderBase.js文件,这个文件里创立了读写器操作的object,名称为rfidreader。3.3、以上所有准备就绪后,就能够开始编写rfidreader的返回后果的回调函数rfidreader.onResult(function(resultdata),所有的构造就从这里返回。3.4、在页面中能够应用rfidreader的接口和办法调用实现相应的性能。

September 29, 2022 · 1 min · jiezi

关于javascript:分享一种超简单的js解密方法

加密代码如下eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('(E["Y"]=E["Y"]||[]).1h([["1z-1A"],{"1y":4(e,t,c){"1n 1l";c.r(t);7 n=4(){7 e=3,t=e.c,c=e.1w.1F||t;9 e.v?c("R",{q:"j-8-D"},[c("R",{q:"j-8-1G",S:{x:e.K}}),c("R",{q:"j-8-1E"},[c("O",{q:"j-8-1D",1j:{1g:e.17,1d:"1b"},S:{x:e.K}}),c("O",{q:"j-8-1p",1j:{1g:e.6.O,1d:"1t"},S:{x:e.1a}})])]):e.1s()},i=[],a=(c("1u"),c("1W"),c("1X"),c("1T")),r=c("1Y"),s=c.n(r),o=c("22"),u=c("23"),d=c("21"),l=c("20"),h=c("1c"),p=c.n(h),f=c("1K");4 g(e,t){7 c=5.1L(e);V(5.1e){7 n=5.1e(e);t&&(n=n.1J((4(t){9 5.13(e,t).1H}))),c.1h.1P(c,n)}9 c}4 A(e){1N(7 t=1;t<T.Q;t++){7 c=F!=T[t]?T[t]:{};t%2?g(5(c),!0).12((4(t){5(a["a"])(e,t,c[t])})):5.X?5.1O(e,5.X(c)):g(5(c)).12((4(t){5.1R(e,t,5.13(c,t))}))}9 e}7 b={1Q:"1M-1I",1S:[f["a"],l["a"]],1Z:{},1i:4(){9{v:!1,6:{},W:[],17:p.a,1U:!1,z:!1,C:!1,B:!1,k:""}},1V:A({},5(o["c"])({N:"N",M:"M"})),1r:4(){},1v:{N:{15:4(e){1o.1q(e)&&e.Q>0&&!3.B&&(3.B=!0,3.W=e,3.C&&3.P())},18:!0},M:{15:4(e){e.k&&!3.C&&(3.k=1C*e.k,3.C=!0,3.B&&3.P())},18:!0}},1B:4(){},1x:{P:4(){7 e=5(d["b"])(3.W,3.k);3.v=e.Q>0,3.v&&(3.6=e[0],3.19(),5(u["b"])({L:"I-J-D-2B",H:3.6.G}))},19:4(e){V(3.6&&3.6.U){7 t=s()(e),c=t.2D("2F-2E-2A"),n=16.2w(3.6.U),i=1;V(n){7 a=n.14(0,10),r=t.2v(a,"2x");(0===r||r<=3.6.2z)&&(i=+n.14(11)+1)}16.2G(3.6.U,"".Z(c,"-").Z(i))}},1a:4(e){7 t=3;3.z||(3.z=!0,5(u["b"])({L:"I-J-D-x",H:3.6.G}),2R((4(){t.z=!1,E.2J(t.6.2I)}),2H))},K:4(){5(u["b"])({L:"I-J-D-1b",H:3.6.G}),3.v=!1}}},y=b,w=(c("1m"),c("2c")),m=5(w["a"])(y,n,i,!1,F,"29",F);t["2C"]=m.1f},"1m":4(e,t,c){"1n 1l";c("1k")},"1c":4(e,t){e.1f="1i:2r/2q;2p,2u////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2t+2s/2k+2j/2i/2n+2f/2l+2m+2o/27+28/24/25+26/2a/2e/2g/2h/2b/2d+2K/2L/2M/2N+2O/2P/2Q+2y"},1k:4(e,t,c){}}]);',62,178,'|||this|function|Object|currentGuidance|var|operate|return||||||||||nd|servertime||||||staticClass|||||guidanceShow||click||locking||listReady|timeReady|guidance|window|null|id|from|web|index|closeGuidance|type|yunData|popupAd|img|showGuidance|length|div|on|arguments|localKey|if|allGuidance|getOwnPropertyDescriptors|webpackJsonp|concat|||forEach|getOwnPropertyDescriptor|slice|handler|localStorage|closeUrl|deep|setTimeStorage|golink|close|9e8f|alt|getOwnPropertySymbols|exports|src|push|data|attrs|b4bc|strict|95a7|use|Array|guidance__img|isArray|created|_2|经营图片|3822|watch|_0|methods|0045|chunk|0e9daeac|mounted|1e3|guidance__close|guidance__body|_1|guidance__mask|enumerable|plugin|filter|0a4e|keys|operateGuidance|for|defineProperties|apply|name|defineProperty|mixins|b76f|hasSet|computed|2637|e5fc|2ed8|components|79f8|7f0d|c6b7|30fa|mmUlf5XUXQ8b7W8RWKJVZXdoPOZoxx3ZWP8j|hJptc3wTXj|I6|WTdJUSRNrf8n7RdWvW7uL9XxwINDXN9HN1cXV0zz2zKcT4Tldpoq7NGdJyHiyB76JNjZMrne0UzSgsPahOZ3a8GRM9kLLNhLRoHMyIjWS4|waMeU1jS9PdOQEEWItKM453qmkpNkamp7pfjYzyVvKc5HPhXlXejiUIh2gt5DPeUB|63f6c2e0|5usqwLRG7AmRkhu3j5TjVgkoyj2Oliz460QKLts|2yxWojx2zJlkbpRHWZCP25zjY3KzKmcFWV4Byt6PiCvA|deb0|9Lxv|nkt8pKcL||j6F9caknYMQny84jsHWADPy|UGqDh9XyLHVKKaCm45VkszpJLM8t8njAQz7fCItHAykCs0EADYyFJw2zEMHJw5RkILjIE9QjWMDDrKxc4DjFS2bgIN0cJBQeJmjeH1WzFnKYcag9IdPtwV0uQqH3yocOlxlcSS3CpgU4nA6JPexrpgU6eANIDgAO0nhHXjLWThNtrYtx5tcckzKTS6PFSTMMSmOFR9kyUmSDzKXDoP7ApiRu9YsHaJY9cwxSYX|q9wCa7Gkpbtaf740PLa5EubBrCZupWHUxVkWVCdDuVNwb9M7S|t6gjAMhlNOclKYTHAinnbi|OT48YVwIdXgx1XnodzRFJxPG5hkMirCsKxJNdlaHV29sJlwswAAAi1JREFUSMedl|NRnEwWiyIo|XV|5aFh|lS|base64|png|image|wYCnqT|NgkbwAAAAKHRSTlMAA|iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAMAAACfWMssAAAAe1BMVEUAAAD|diff|getItem|days|HHyKjcAYx6uLPAAAAAElFTkSuQmCC|showDay|DD|show|default|format|MM|YYYY|setItem|400|href|open|b8L1b|q9y|efBvV|wbJP|WzL8J9G87|Rtd|9bav5nnz4dOfz50js|setTimeout'.split('|'),0,{}))js解密后(window["webpackJsonp"] = window["webpackJsonp"] || []).push([ ["chunk-0e9daeac"], { "0045": function(e, t, c) { "use strict"; c.r(t); var n = function() { var e = this, t = e.c, c = e._0._1 || t; return e.guidanceShow ? c("div", { staticClass: "nd-operate-guidance" }, [c("div", { staticClass: "nd-operate-guidance__mask", on: { click: e.closeGuidance } }), c("div", { staticClass: "nd-operate-guidance__body" }, [c("img", { staticClass: "nd-operate-guidance__close", attrs: { src: e.closeUrl, alt: "close" }, on: { click: e.closeGuidance } }), c("img", { staticClass: "nd-operate-guidance__img", attrs: { src: e.currentGuidance.img, alt: "经营图片" }, on: { click: e.golink } })])]) : e._2() }, i = [], a = (c("3822"), c("2637"), c("e5fc"), c("b76f")), r = c("2ed8"), s = c.n(r), o = c("c6b7"), u = c("30fa"), d = c("7f0d"), l = c("79f8"), h = c("9e8f"), p = c.n(h), f = c("0a4e"); function g(e, t) { var c = Object.keys(e); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); t && (n = n.filter((function(t) { return Object.getOwnPropertyDescriptor(e, t).enumerable }))), c.push.apply(c, n) } return c } function A(e) { for (var t = 1; t < arguments.length; t++) { var c = null != arguments[t] ? arguments[t] : {}; t % 2 ? g(Object(c), !0).forEach((function(t) { Object(a["a"])(e, t, c[t]) })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(c)) : g(Object(c)).forEach((function(t) { Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(c, t)) })) } return e } var b = { name: "operateGuidance-plugin", mixins: [f["a"], l["a"]], components: {}, data: function() { return { guidanceShow: !1, currentGuidance: {}, allGuidance: [], closeUrl: p.a, hasSet: !1, locking: !1, timeReady: !1, listReady: !1, servertime: "" } }, computed: A({}, Object(o["c"])({ popupAd: "popupAd", yunData: "yunData" })), created: function() {}, watch: { popupAd: { handler: function(e) { Array.isArray(e) && e.length > 0 && !this.listReady && (this.listReady = !0, this.allGuidance = e, this.timeReady && this.showGuidance()) }, deep: !0 }, yunData: { handler: function(e) { e.servertime && !this.timeReady && (this.servertime = 1e3 * e.servertime, this.timeReady = !0, this.listReady && this.showGuidance()) }, deep: !0 } }, mounted: function() {}, methods: { showGuidance: function() { var e = Object(d["b"])(this.allGuidance, this.servertime); this.guidanceShow = e.length > 0, this.guidanceShow && (this.currentGuidance = e[0], this.setTimeStorage(), Object(u["b"])({ type: "web-index-guidance-show", from: this.currentGuidance.id })) }, setTimeStorage: function(e) { if (this.currentGuidance && this.currentGuidance.localKey) { var t = s()(e), c = t.format("YYYY-MM-DD"), n = localStorage.getItem(this.currentGuidance.localKey), i = 1; if (n) { var a = n.slice(0, 10), r = t.diff(a, "days"); (0 === r || r <= this.currentGuidance.showDay) && (i = +n.slice(11) + 1) } localStorage.setItem(this.currentGuidance.localKey, "".concat(c, "-").concat(i)) } }, golink: function(e) { var t = this; this.locking || (this.locking = !0, Object(u["b"])({ type: "web-index-guidance-click", from: this.currentGuidance.id }), setTimeout((function() { t.locking = !1, window.open(t.currentGuidance.href) }), 400)) }, closeGuidance: function() { Object(u["b"])({ type: "web-index-guidance-close", from: this.currentGuidance.id }), this.guidanceShow = !1 } } }, y = b, w = (c("95a7"), c("deb0")), m = Object(w["a"])(y, n, i, !1, null, "63f6c2e0", null); t["default"] = m.exports }, "95a7": function(e, t, c) { "use strict"; c("b4bc") }, "9e8f": function(e, t) { e.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAMAAACfWMssAAAAe1BMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////NgkbwAAAAKHRSTlMAA+wYCnqT/OT48YVwIdXgx1XnodzRFJxPG5hkMirCsKxJNdlaHV29sJlwswAAAi1JREFUSMedl+t6gjAMhlNOclKYTHAinnbi/q9wCa7Gkpbtaf740PLa5EubBrCZupWHUxVkWVCdDuVNwb9M7S/5aFh+2f/NRnEwWiyIo+XV+lS/WTdJUSRNrf8n7RdWvW7uL9XxwINDXN9HN1cXV0zz2zKcT4Tldpoq7NGdJyHiyB76JNjZMrne0UzSgsPahOZ3a8GRM9kLLNhLRoHMyIjWS4+waMeU1jS9PdOQEEWItKM453qmkpNkamp7pfjYzyVvKc5HPhXlXejiUIh2gt5DPeUB/mmUlf5XUXQ8b7W8RWKJVZXdoPOZoxx3ZWP8j/hJptc3wTXj+I6/5usqwLRG7AmRkhu3j5TjVgkoyj2Oliz460QKLts/nkt8pKcL/j6F9caknYMQny84jsHWADPy/UGqDh9XyLHVKKaCm45VkszpJLM8t8njAQz7fCItHAykCs0EADYyFJw2zEMHJw5RkILjIE9QjWMDDrKxc4DjFS2bgIN0cJBQeJmjeH1WzFnKYcag9IdPtwV0uQqH3yocOlxlcSS3CpgU4nA6JPexrpgU6eANIDgAO0nhHXjLWThNtrYtx5tcckzKTS6PFSTMMSmOFR9kyUmSDzKXDoP7ApiRu9YsHaJY9cwxSYX/2yxWojx2zJlkbpRHWZCP25zjY3KzKmcFWV4Byt6PiCvA/9Lxv+b8L1b/q9y/efBvV/wbJP+WzL8J9G87/Rtd/9bav5nnz4dOfz50js+HHyKjcAYx6uLPAAAAAElFTkSuQmCC" }, b4bc: function(e, t, c) {} }]);如何解密的办法很简略 ...

September 29, 2022 · 3 min · jiezi

关于javascript:Optional源码解析与实践

1 导读NullPointerException在开发过程中常常遇到,稍有不慎小BUG就呈现了,如果防止这个问题呢,Optional就是专门解决这个问题的类,那么Optional如何应用呢?让咱们一起摸索一下吧! 2 源码解析2.1 Optional定义Optional类是Java8为了解决null值判断问题而创立的容器类,在java.util 下,应用Optional类能够防止显式的null值判断,防止null导致的NullPointerException。首先,Optional是一个容器,它能够保留类型T的值,也能够为null的容器对象。Optional容器只能存一个值。 2.2 Optional的属性1)源码: /** * Common instance for {@code empty()}. */private static final Optional<?> EMPTY = new Optional<>(); /** * If non-null, the value; if null, indicates no value is present */private final T value;依据源码能够看到Optional有两个属性,一个是为空值筹备的EMPTY和泛型值value; 2.3 Optional的办法Optional除toString()、hashCode() 、equals()等Object的办法外,还蕴含以下办法。 2.3.1 公有构造方法 /** * Constructs an empty instance. * * @implNote Generally only one empty instance, {@link Optional#EMPTY}, * should exist per VM. */private Optional() { this.value = null;} /*** Constructs an instance with the value present.** @param value the non-null value to be present* @throws NullPointerException if value is null*/private Optional(T value) { this.value = Objects.requireNonNull(value);}别离是创立一个空实例和结构一个具备以后值的实例。 ...

September 29, 2022 · 4 min · jiezi

关于javascript:javaScript正则表达式

JavaScript RegExp 对象RegExp:是正则表达式(regular expression)的简写正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的弱小工具 语法: var patt=new RegExp(pattern,modifiers);或者 var patt=/pattern/modifiers;其中:pattern:代表正则表达式modifiers:代表修饰符 修饰符: i 执行对大小写不敏感的匹配。g 执行全局匹配(查找所有匹配而非在找到第一个匹配后进行)。m 执行多行匹配。案例(匹配hello、疏忽大小写): var str = "HELLO world!";var patt1 = /hello/i;document.write(str.match(patt1));输入: HELLO留神:当应用构造函数发明正则对象时,须要惯例的字符本义规定(在后面加反斜杠 \)。如,匹配\w时须要加\,以下是等价的: // +示意匹配一次或屡次var re = new RegExp("\\w+");var re = /\w+/;方括号 用于查找某个范畴内的字符: [abc] 查找方括号之间的任何字符。[^abc] 查找任何不在方括号之间的字符。[0-9] 查找任何从 0 至 9 的数字。[a-z] 查找任何从小写 a 到小写 z 的字符。[A-Z] 查找任何从大写 A 到大写 Z 的字符。[A-z] 查找任何从大写 A 到小写 z 的字符。[adgk] 查找给定汇合内的任何字符。[^adgk] 查找给定汇合外的任何字符。元字符领有非凡含意的字符 . 查找单个字符,除了换行和行结束符。\w 查找数字、字母及下划线。\W 查找非单词字符。\d 查找数字。\D 查找非数字字符。\s 查找空白字符。\S 查找非空白字符。\b 匹配单词边界。\B 匹配非单词边界。\0 查找 NULL 字符。\n 查找换行符。\f 查找换页符。\r 查找回车符。\t 查找制表符。\v 查找垂直制表符。量词定义正则匹配的次数 ...

September 29, 2022 · 1 min · jiezi

关于javascript:mapboxgl加载tiff

缘起近期在我的项目中遇到这么一个需要,须要在地图上展现一组格网数据,格网大小为2m*2m,地图api用的mapboxgl。起初拿到这个须要感觉很easy,在地图上增加一个fill图层就好啦。把格网面数据增加到地图上之后,在大比例尺下显示失常,然而当地图层级小于15级时,渲染出的后果会隐没。 简略理一下起因,应该是在地图放大后,每个网格所占的像素太小,所以就隐没了。 mapboxgl在解决symbol图层的时候,会遇到点位主动避让问题,导致局部点位不显示。解决办法是把layout中的icon-allow-overlap设置为true,这样就相当于敞开了主动避让性能,所有点图标放弃可见状态。然而针对fill图层却没有这么一个属性。然而这种状况又须要查看数据,要如何实现呢? 首先剖析下数据,我的原始数据是通过模型导出的tiff格局的栅格数据,而后在后盾依据tiff格局数据中每个像素所在行列号以及其灰度值生成带属性的格网数据,其中像素的灰度值就是在渲染时须要分类展现的值。既然原始tiff数据的灰度值就是所用的属性值,那是不是间接增加到地图就好了。接下来的解决方案就是看是否能间接用mapboxgl间接加载tiff数据,并渲染出本人想要的成果。 mapboxgl加载tiff查看mapboxgl文档,能够看到mapboxgl反对image图层,只需传入url和coordinates // 增加至地图map.addSource('some id', { type: 'image', url: 'https://www.mapbox.com/images/foo.png', coordinates: [ [-76.54, 39.18], [-76.52, 39.18], [-76.52, 39.17], [-76.54, 39.17]]});可是,当我把地址换成tiff数据时却报错了。上面为报错内容: Could not load image because of The source image could not be decoded.. Please make sure to use a supported image type such as PNG or JPEG. Note that SVGs are not supported能够简略了解为不反对tiff格局。 tiff文件解析既然mapboxgl的image图层不反对tiff格局,那是不是能够把tiff数据导出成png呢,于是应用arcmap关上了tiff数据,导出数据格式也反对png,然而在保留时又报错了。 通过剖析,发现是tiff数据波段数量的起因,我的这份数据波段数为1,从网上下载了一份测试数据,波段数为3,能够胜利导出。 在查找相干解决方案的时候,看到这么个工具,geotiff.js,能够通过js解析tiff数据并渲染,leaflet有个扩大就是用的这个工具,https://github.com/stuartmatt...。查看geotiff.js相干文档,发现其实用起来还是挺不便的,通过简略的代码实现的我的需要。 先应用geotiff.js解析tiff数据,再配合应用canvas绘制图片导出base64格局数据,而后就能够应用增加到mapboxgl图层了。 外围代码如下: async function getData() { GeoTIFF.fromUrl(url).then(tiff => { console.log(tiff) getImage(tiff) });}async function getImage(tiff) { const image = await tiff.getImage(); let bbox = await image.getBoundingBox(); let data = await image.readRasters({ samples: rgbBands // 波段数量,一个波段:[0],三个波段:[2,1,0] }); let base64Image = getBase64Image(data) addToMapboxgl(base64Image)}function getBase64Image(data) { let thumbnailPixelHeight = data.height let thumbnailPixelWidth = data.width let canvas = document.createElement('canvas') canvas.width = thumbnailPixelWidth canvas.height = thumbnailPixelHeight let ctx = canvas.getContext("2d") let totalPixelCount = 0 for (let y = 0; y < thumbnailPixelHeight; y++) { for (let x = 0; x < thumbnailPixelWidth; x++) { let colour = 'rgb(0, 0, 0, 0)' // let the default be no data (transparent) // 依据灰度值所在范畴渲染色彩 if (data[0][totalPixelCount] > 0) { if (data[0][totalPixelCount] > 50 && data[0][totalPixelCount] <= 55) { colour = `rgb(15, 255, 0, 1)` } else if (data[0][totalPixelCount] > 55 && data[0][totalPixelCount] <= 60) { colour = `rgb(155, 255, 0, 1)` } else if (data[0][totalPixelCount] > 60 && data[0][totalPixelCount] <= 65) { colour = `rgb(255, 255, 0, 1)` } else { colour = `rgb(255, 255, 0, 1)` } } ctx.fillStyle = colour ctx.fillRect(x, y, 1, 1) totalPixelCount++ } } let canvasImage = canvas.toDataURL("image/png") return canvasImage}// 将图片增加到地图function addToMapboxgl(image) { map.addSource('tiff-source', { "type": "image", "url": image, "coordinates": [ [114.425597191307, 38.1091563484708], [114.538187627939, 38.1091563484708], [114.538187627939, 37.9627378349512], [114.425597191307, 37.9627378349512] ] }); map.addLayer({ id: 'tiff-layer', 'type': 'raster', 'source': 'tiff-source', 'paint': { 'raster-fade-duration': 0 } });}本认为到这里问题曾经解决,然而在查看地图时,发现图片图层数据叠加到底图有不小的偏移。 ...

September 29, 2022 · 2 min · jiezi

关于javascript:复习高级语法对象原型es5新增语法

明天的开始进入了js的高级语法 我马上也要温习完了,之前学到闭包递归,就回去温习去了,复都温习这么久而且,温习的过程真的比学常识的过程难熬的多,只不过终于要温习完了,再来点es6的新语法马上就要步入vue了,想想都有点小冲动,明天首先来的第一个案例我称之为目前为止的史诗级难度,第一次做的时候懵懵懂懂的,这第二次温习到再做缓缓的有点感觉了,也懂了很多但还是有一些局部本人独立实现不了,这是一个基于面向对象的tab栏,我第一次做的时候应该也在上面开贴了,这一次做收货照样很多,不多说了先看成果吧先来html代码吧,js上面再说 <!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>面向对象 Tab</title> <link rel="stylesheet" href="./styles/tab.css"> <link rel="stylesheet" href="./styles/style.css"></head><body> <main> <h4> Js 面向对象 动静增加标签页 </h4> <div class="tabsbox" id="tab"> <!-- tab 标签 --> <nav class="fisrstnav"> <ul> <li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li> <li><span>测试2</span><span class="iconfont icon-guanbi"></span></li> <li><span>测试3</span><span class="iconfont icon-guanbi"></span></li> </ul> <div class="tabadd"> <span>+</span> </div> </nav> <!-- tab 内容 --> <div class="tabscon"> <section class="conactive">测试1</section> <section>测试2</section> <section>测试3</section> </div> </div> </main><script src="./js/index.js"></script></body></html>html其实还是蛮简略的,js就有说头了,全副是基于class类来实现的,做这一个案例我感觉就能够对类有一个很分明的认知了,做下来很有帮忙,第二次做有点小bug哈,应该让里面与外面串联起来所以最好还是类承受一个id传进来但我这里间接就开始了啥也没传所以要看传id的版本在我最开始几篇应该有 // 纯纯的相当于第一次做了 很久之后再次回归我就大多数拿来冥想了 想看具体的思维步骤的在我前几篇随笔外面那个写的清晰地多var thatclass Tab { constructor() { that = this // 1.1 获取元素在这里获取 this.ul = document.querySelector('ul') // 1.3面板对应切换 this.tabscon = document.querySelector('.tabscon') // 2.点击加号能够增加tab栏和内容 this.add = document.querySelector('.tabadd span') this.init() } // 2.4这里是拿来获取最新的数据 以便增删改查的操作 getNew() { this.lis = this.ul.querySelectorAll('li') this.sections = this.tabscon.querySelectorAll('section') this.close = document.querySelectorAll('.icon-guanbi') this.spans = this.ul.querySelectorAll('li span:first-child') } // 2.3须要一个初始化函数 一开始就让所有组件绑定事件 init() { this.getNew() this.add.onclick = that.addSection for (var i = 0 ; i < this.lis.length; i++) { this.lis[i].setAttribute('data-index', i) this.lis[i].onclick = this.togge // 3.1同样在初始化外面为删除绑定点击事件 this.close[i].onclick = this.remove this.spans[i].ondblclick = this.dbclick this.sections[i].ondblclick = this.dbclick } } clearCLass() { // 1.2因为这里要用到this 且等会会被调用 所以要筹备一个that // 2.2因为上面要用到分明款式的中央还有点多 for (var i = 0 ; i < this.lis.length; i++) { this.lis[i].classList.remove('liactive') that.sections[i].classList.remove('conactive') } } // 1.点击切换成果 togge() { that.clearCLass() this.classList.add('liactive') var index = this.getAttribute('data-index') that.sections[index].classList.add('conactive') } // 2.1增加成果 addSection() { // 2.5这里这个新语法很重要 如果用原来的appendchild 得不到及时的新数据 就会不晓得插入在哪里去就会报错 var li = '<li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li>' that.ul.insertAdjacentHTML('beforeend', li) var section = '<section class="conactive">测试'+Math.random()+'</section>' that.tabscon.insertAdjacentHTML('beforeend', section) that.clearCLass() that.init() } // 3.删除成果 remove(e) { // 3.1这里有个疑难点卡了我半天 因为点的是小close 这里有个冒泡成果 而li也有个点击成果所以你一点击小叉 就回升到li也会被点击 先不说 // 这个点击重不重要 如果不关的话 这里点击了 那你上面还有个点击上一个按钮的行为就不会触发 因为同一时间只能点一个li e.stopPropagation() var index = this.parentNode.getAttribute('data-index') that.ul.removeChild(this.parentNode) that.tabscon.removeChild(that.sections[index]) that.lis[index - 1] && that.lis[index - 1].click() } // .4.双击批改性能 dbclick() { // console.log(val); window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty() var str = this.innerHTML this.innerHTML = '<input type="text">' this.children[0].value = str this.children[0].onblur = function() { this.parentNode.innerHTML = this.value } }}var tab = new Tab()2. ...

September 29, 2022 · 3 min · jiezi

关于javascript:vue滚动事件滚动出现按钮回到顶部底部请求分页数据

最近呈现了很多页面都须要滚动翻页的需要 示例图 template<div id="order" @scroll="scrollEvent" ref="scrollWrapper"> 滚动条两头内容略...<div>// 只做示例,就用按钮简略实现性能。<el-button round icon="el-icon-top" @click="toTop('order')" v-if="showTop">顶部</el-button>script// 表格滚动scrollEvent(e) { if (e.srcElement.scrollTop>你心愿滚动到哪个数字会呈现‘回到顶部’,例如300) { this.showTop = true; } else { this.showTop = false; } let top = e.srcElement.scrollTop; // 保留加载前的滚动条高度 // 滑到最底部 if (e.srcElement.scrollTop + e.srcElement.clientHeight >= e.srcElement.scrollHeight ) { // 非最初一页都要持续申请 if (this.page.total > (this.page.pageNum * this.page.pageSize)) { let self = this; // 除分页以外还有其余搜寻条件 self.searchData.pageNum = self.page.pageNum+1; self.searchData.pageSize = self.page.pageSize; 后端分页接口.then((res) => { if (后端正确返回下一页数据) { self.page.list.push(...res.result.list); self.page.pageNum = res.result.pageNum; self.page.total = res.result.total; // 滚动条定位 this.$nextTick(() => { this.$refs.scrollWrapper.scrollTo(0, top); }) } }); } }},// 回到顶部toTop(name) { let e = document.getElementById(name); e.scroll({top: 0, left: 0, behavior: 'smooth' }); // smooth滚动不至于太快},

September 28, 2022 · 1 min · jiezi

关于javascript:华南首场零代码教练员研修班圆满结束

9月24日,明道云首场华南地区零代码教练员研修班圆满结束。为期一天,二十位明道云客户和搭档共同完成培训,其中包含广汽本田、沃尔玛、富璟科技、广州皑讯、英赛特软件等企业代表。 本期零代码教练员研修班在一期课程根底上,更器重传授实际办法与实操演练。明道云提前为学员们发送课前预习材料《零代码教练指南》,通过自学打好认知根底。课堂上,讲师着重解说课程设计原理、课程内容设计办法等须要教训积攒和讲师疏导了解的知识点。 明道云COO曾前志介绍“为什么要成为零代码教练员”讲师介绍艾默生电气内训胜利的案例讲师领导学员学习正手击球 下午,讲师率领学员们以小组为单位实操教案设计和课程试讲。现场四个小组各自探讨,为其余小组设计企业零代码培训需要的命题。小组支付题目后,再在组内探讨,合作实现课程的设计方案及课件,派代表下台汇报与试讲。不少学员感叹:上手和听课的感觉很不一样,霎时肾上腺素就上来了。 小组学员为对面小组出培训案例题目小组成员独特筹备公开试讲内容广汽本田学员合影 师父领进门,修行在个人。随同结业典礼实现,研修班也正式完结。咱们期待学员们在公司外部或客户我的项目里施展领导力,使用培训常识,策动和发展公司外部的零代码利用搭建培训流动,或者能为客户提供私教培训服务。 第三期零代码教练员研修班行将在11月与宽广搭档和用户再次见面。如果您有趣味参加下期研修班,记得注意明道云微信公众号音讯,勿错过流动报名资讯。

September 28, 2022 · 1 min · jiezi

关于javascript:微信小程序使用scrollview横线滚动条并展示模拟进度条

之前开发过一个性能,点击按钮展现一个弹层,弹层外面展现商品,商品能够滑动,并且上面有一个进度条。思路就是scroll-view外面展现图片,而后应用这个组件的api。关上弹层,须要思考到一种状况:图片宽度无奈撑满scroll-view,那就须要模仿进度条撑满。我定义的scroll-view宽度就是屏幕的宽度。所以接口返回图片的数量后,我须要计算图片列表汇合的总宽度。上面是代码: <scroll-view class="scroll" scroll-x="true" bindscroll="scroll" bindscrolltolower='scrollEnd' style="width: 100%" throttle="{{false}}"> <view class="product-item" wx:for="{{detailInfo.productList}}"> <image class="imgUrl" mode="aspectFill" src="{{item.imgUrl}}"></image> <view class="productName">{{item.productName}}</view> <view class="price">¥ {{item.price}}</view> </view> </scroll-view> 进度条 <view class="dots1" > <view class="dots1-item" style="width:{{left}}"></view> </view> /** * 页面的初始数据 */ data: { left: 0, },弹层关上的时候进度条设置默认的地位: // 设置进动条初始地位 let query = wx.createSelectorQuery(); // 获取图片父盒子定义的的宽度 query.select('.product-item').boundingClientRect(rect => { // 返回的图片汇合总宽度 let width = rect.width * this.data.detailInfo.productList.length; // scroll-view的宽度和屏幕宽度统一 let windowWidth = wx.getSystemInfoSync().windowWidth; if (width <= windowWidth) { this.setData({ left: `100%` }) } else { this.setData({ left: `${windowWidth / width * 100}%` }) } }).exec();滚动的时候: ...

September 27, 2022 · 1 min · jiezi

关于javascript:Javascript笔记varletconst的异同

一、问题的提出在学习js的过程中,很多小伙伴会理解变量的知识点。其实每个变量只是更好的表白数据的占位符。在ECMAScript中,有三个关键字能够申明变量:var,const和let。 然而为什么简简单单的申明变量还须要三个关键字呢?他们有什么异同呢? 二、呈现工夫的不同通过查问材料咱们发现,let、const两个变量只能在ES6以及更晚的版本中应用,var在ES的所有版本中均可应用。集体了解为let和const两个变量是对于var毛病的补充。 三、三者区别节约工夫,先说后果再说起因!! var 全局作用域、函数作用域。 同一作用域下,能够屡次申明同一变量(能够在后续代码中从新赋值)。 能够在申明前调用(先调用后申明)。 let 作用域:全局作用域、函数作用域、块级作用域。 同一作用域下,不能够屡次申明同一变量。 不能够在申明前调用。 const 作用域:全局作用域、函数作用域、块级作用域。 同一作用域下,不能够屡次申明同一变量。 不能够在申明前调用。 由此可见 const 的行为与 let 基本相同,惟一一个重要的区别是用它申明变量时必须同时初始化变量,且尝试批改 const 申明的变量会导致运行时谬误。而var只能用于全局作用域和函数作用域。刚刚提到了一个名词叫块级作用域,指的范畴是: 循环判断同一级{ }外面的货色上面咱们来详解一下这些关键字吧~~ 四、详解关键字var关键字1.1 var关键字 此处是对于var的函数作用域的展现,在办法中申明的var变量,只对于该办法外部起到成果。 function Test() { var a = "hi"; // 局部变量} test(); console.log(a); // 出错!解决此类问题,能够抹去var变量,间接定义一个全局变量如下 ,不过个别不举荐这么做,会造成困惑,保护起来也麻烦。 function test() { a = "hello world"; // 局部变量} test(); console.log(a); // "hello world" 1.2 var申明的晋升这一条看起来就很诡异,在作用域内先输入变量,再定义的模式,在Js中不会报错,因为申明的变量会主动提到函数作用域顶部 举个例子: function foo() { console.log(score); var score = 26; } foo(); // undefined这个代码中,先输入了score,之后才进行赋值 。这里是因为在ES运行时,会主动把所有关键字var申明的变量放在顶部。然而此时未赋值。所以输入undefined。在解决的过程中,ES把上述代码等同于: ...

September 27, 2022 · 1 min · jiezi

关于javascript:进阶提取图片主色调

原文参考我的公众号文章 进阶!八叉树色调量化法提取图片次要色彩 体验地址,接我上一篇文章!大抵思路1.构建八叉树,将 rgb 色彩循环增加到树里(雷同的色彩会跑到同一层的同一个叶子结点上,累加 count);2.当叶子结点数量超过指定最大色彩数时,进行叶子结点合并(类似的色彩会跑到同一个父节点,与兄弟结点同级,因而能够合并到他们的父节点);3.计算调色盘(递归遍历八叉树,累加所有叶子节点的 r,g,b 色彩值再均匀);为什么是八叉树?比方有这么一个色彩 rgb = [31, 31, 30],给出它的入树过程!//r = 31 => 00011111//g = 31 => 00011111//b = 30 => 00011110r,g,b每个色彩位转换成了8位二进制用0,1示意,同时从左到右取r,g,b的每一位组成3位二进制数。比方取第1位,组成列:000,转换成十进制就是 0,进入八叉树中第1层,的第1个结点;比方取第2位,组成列:000,转换成十进制就是 0,进入八叉树中第2层,的第1个结点;比方取第3位,组成列:000,转换成十进制就是 0,进入八叉树中第3层,的第1个结点;比方取第4位,组成列:111,转换成十进制就是 7,进入八叉树中第4层,的第8个结点;比方取第5位,组成列:111,转换成十进制就是 7,进入八叉树中第5层,的第8个结点;比方取第6位,组成列:111,转换成十进制就是 7,进入八叉树中第6层,的第8个结点;比方取第7位,组成列:111,转换成十进制就是 7,进入八叉树中第7层,的第8个结点;比方取第8位,组成列:110,转换成十进制就是 6,进入八叉树中第8层,的第7个结点(叶子结点,累加r,g,b重量,累加pixelCount);依照上述规定,可能将反复呈现的色彩累加到第 8 层的某一个叶子结点中!网上找了个图形象阐明一下!(图片来源于网络) // 比方有这么几个像素色彩信息:let pixels = [ [31, 31, 30], [31, 31, 31], [31, 31, 31],]// 最终失去色彩的统计状况会是:let colors = { '31,31,30': 1, '31,31,31': 2 }构建树结点class OctTreeNode { constructor(level) { this.color = []; this.level = level; this.isLeaf = false; this.pixelCount = 0; //该节点呈现次数,当为叶子结点时,代表了某种色彩呈现次数 this.r = 0; //red通道累加值 this.g = 0; //green通道累加值 this.b = 0; //blue通道累加值 this.children = [null, null, null, null, null, null, null, null]; //八个子节点 this.next = null; //在 reducible 链表中的下一个节点 }}顺次载入像素信息,生成八叉树结构function dec2bin(decnum, displayLength) { let bin = decnum.toString(2); if (displayLength) { while (bin.length < displayLength) { bin = `0${bin}`; } } return bin;}function addColor(parentNode, color, level) { if (!color) { throw new Error("color must be provided,like [255, 0, 0]"); } let [r, g, b] = color; if (parentNode.isLeaf) { // console.warn(`已满八层,是叶子节点,rgb(${color})`); parentNode.pixelCount++; parentNode.r += r; parentNode.g += g; parentNode.b += b; return; } let binR = dec2bin(r, 8); let binG = dec2bin(g, 8); let binB = dec2bin(b, 8); // 逐列合并bin,共3行8列,需递归执行8次,生成8层树结构 let concatColBin = `${binR[level]}${binG[level]}${binB[level]}`; let index = bin2dec(concatColBin); if (!parentNode.children[index]) { parentNode.children[index] = createNode(level); } // 递归生成下一层 addColor(parentNode.children[index], color, level + 1);}为什么须要进行叶子结点合并?一个图片中的色彩信息会十分多,通过八叉树量化后,某些像素色彩占比很大,有些很小。很小的起因可能是这种色彩自身就少,也有可能是因为它们是类似的色彩,那么将类似的色彩合并,缩小提取的色彩躁点(数量极多却极其类似的色彩)稀释就是精髓! ...

September 27, 2022 · 3 min · jiezi

关于javascript:程序员炒股一年亏损28去做量化交易准备逆风翻盘

事件是这样的,最近大A跌的很惨,再一次打响了3000点保卫战,作为一个股民,我深受其害呀!往年的亏损曾经达到了-28%,惆怅! 于是我总结了下我亏损的起因:感情用事! 人之所以会亏损,很大水平和情感无关,比方你上午捡到100元,下午又丢了100元,这个时候,往往人悲伤的情绪会大于喜悦的情绪,如果是机器就不会这样,很单纯的指令钱大于0开心,钱小于0惆怅,钱等于0平静,最终机器的感情是平静的,而人的感情是惆怅的。 于是我决定做一量化软件来帮忙我进步胜率。 而后我去抓取了股票数据,写好了本人的量化策略,通过历史数据进行回测,测试半年数据,把收益率进步到了90%,下图是软件的模仿后果。 我打算每日进行实盘记录,验证策略的可用性,大家能够关注我抖音账号,我会一步步欠缺本人的软件和交易策略!如果实盘成果OK,也会把软件部署到线上给大家应用。

September 27, 2022 · 1 min · jiezi

关于javascript:复习jQuery

咱就是说,发现了一个更好的办法每次把效果图制作成了一个gif,另外举荐个免费软件GIFcam很不便制作gif图,毕竟js是一门动静交互的语言对吧,没有动静的图那就是没有灵魂的所以当前就用这种形式来上传一些页面的成果交互,明天是对jQuery的温习,尽管说当初用jq的少了然而学一学还是能够的,学了不吃亏,还别说这外面还是有难得案例的逻辑性很强,就比方jq那个表单插件validate次要还是外面的属性办法这些要搞清楚。 1. 第一个案例是一个登录切换的案例,用到了jq的自触发事件,而后都在代码里了,看图吧霍,不错不错,终于实现了动静交互,我的博客实现了一大停顿,人类进入了一个新社会,而后还是一样html对应局部➕js的代码出现,这个案例有个陈腐的点 <!DOCTYPE html><html lang="zh"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>demo - 微博登录</title> <link rel="stylesheet" href="./css/style.css" /> </head> <body> <div class="login"> <div class="wrap-box"> <!-- 切换登录场景 --> <div class="multi-type"> <a href="javascript:;" data-label="#account" class="label active"> 账号登录 </a> <a href="javascript:;" data-label="#secure" class="label">平安登录</a> <a href="javascript:;" data-label="#phone" class="icon"></a> </div> <div class="login-type"> <!-- 账号登录 --> <div class="account" id="account"> <div class="input-box username"> <input type="text" /> </div> <div class="input-box password"> <input type="text" /> </div> <div class="extra-box"> <label for="login_status"> <input id="login_status" type="checkbox" /> <span>记住我</span> </label> <a href="javascript:;">遗记明码</a> </div> <div class="button-box"> <button>登录</button> </div> <p class="text-box"> 还没有微博? <a href="javascript:;">立刻注册!</a> </p> <p class="social-box"> <span>基它登录:</span> <a href="javascript:;" class="taobao"></a> <a href="javascript:;" class="qq"></a> <a href="javascript:;" class="yidong"></a> <a href="javascript:;" class="tianyi"></a> <a href="javascript:;" class="qihu"></a> </p> </div> <!-- 平安登录 --> <div class="secure" id="secure"> <div class="qrcode"> <img src="./images/weibo.png" alt="" /> <span>请用最新版微博客户端扫码</span> </div> <p>还没有微博?<a href="javascript:;">立刻注册!</a></p> </div> <!-- 手机号登录 --> <div class="phone" id="phone"> <div class="input-box phone-number"> <input type="text" /> </div> <div class="verify-box"> <button>获取短信验证码</button> <input class="code" type="text" /> </div> <div class="extra-box"> <label for="login_status"> <input id="login_status" type="checkbox" /> <span>记住我</span> </label> <a href="javascript:;">遗记明码</a> </div> <div class="button-box"> <button>登录</button> </div> <p class="text-box"> 还没有微博? <a href="javascript:;">立刻注册!</a> </p> <p class="social-box"> <span>基它登录:</span> <a href="javascript:;" class="taobao"></a> <a href="javascript:;" class="qq"></a> <a href="javascript:;" class="yidong"></a> <a href="javascript:;" class="tianyi"></a> <a href="javascript:;" class="qihu"></a> </p> </div> </div> </div> </div> <!-- 引入 jQuery --> <script src="./assets/jquery/jquery-3.5.1.min.js"></script> <script> // 1.先实现点击切换的性能 var flag = true $('.multi-type').children('a').click(function() { var label = $(this).attr('data-label').substr(1) $('.multi-type').children('.active').removeClass('active') $(this).addClass('active') // 3.小图标的切换应该有一个开关阀 管制再次点击切换到平安登录 // 2.对应的内容面板切换 $('.login-type').children('div').css('display', 'none') $('.login-type').children('.'+label+'').css('display', 'block') // 3.1这里我用jq对象来相等如同不太行的样子不晓得为什么 // 这个案例陈腐点在这里 一个是怎么来控制点了第三个图标两次 一个是这段代码的摆放地位也有作用 放在后面就会执行不了 if (this === document.querySelector('.icon')) { // console.log(11); if (flag) { console.log(11); this.click() flag = false } else { flag = true console.log(11); document.querySelector('.multi-type').children[1].click() } } }) </script> </body></html>2. ...

September 27, 2022 · 3 min · jiezi

关于javascript:独立开发者工具electronegg桌面软件开发框架

过来两年,我做两个我的项目:1:小明云存储,能够了解为一个聚合图床。2:GitHub阅读器,利用GitHub1s,能够不便的浏览GitHub我的项目源码。 但因为种种原因,软件没有达到我预期成果。 起初把用到的技术做成了一个开源框架,反而有了不少用户。 框架名称是:electron-egg,一个桌面软件开发框架。 想做桌面软件的独立开发者,能够尝试一下 我的项目地址:● gitee: https://gitee.com/wallace5303... ● github: https://github.com/wallace530...

September 27, 2022 · 1 min · jiezi

关于javascript:webapi3-今天真真真全是大经典案例

这个我的项目一多起来了,还是分个序号比价好一点,你好我好大家好,而后对于这个标点符号的问题,我打字真的很不喜爱打标点符号,不是不好按,按个逗号其实也是顺便的事件,可能就是养成习惯了,就喜爱按个空格来离开,也不知道你们看有标点和没得标点看起来有区别没得,如果有区别的话我就缓缓养成习惯打上标点吧!!!欧尔整点感叹号这些还是能够,咱们明天书接上回因为是大我的项目所以用了另一种出现的办法。 1. 咱们后这个章节前面的内容的我的项目根本都要以一个本人编写的缓冲动画的函数为根底,所以我先把这个函数贴上来 缓冲动画函数终极版 <!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> <style> .box { position: absolute; top: 50px; width: 100px; height: 100px; background-color: skyblue; } </style></head><body> <div class="box"></div> <button>500</button> <button>800</button> <script> var box = document.querySelector('div') var btns = document.querySelectorAll('button') function animate(obj, target, callback) { clearInterval(obj.timer) obj.timer = setInterval(function() { if (obj.offsetLeft == target) { clearInterval(obj.timer) // callback必须写到完结定时器这里 if (callback) { callback() } } var step = (target - obj.offsetLeft) / 10 step = step < 0 ? Math.floor(step) : Math.ceil(step) obj.style.left = obj.offsetLeft + step + 'px' }, 15) } btns[0].onclick = function() { animate(box, 500) } btns[1].onclick = function() { animate(box, 800, function() { box.style.backgroundColor = 'red' }) } </script></body></html>2. ...

September 27, 2022 · 5 min · jiezi

关于javascript:SAP-UI5-Simple-Form-属性-columnsLcolumnsMcolumnsXL-的属性深入剖析试读版

一套适宜 SAP UI5 初学者循序渐进的学习教程本专栏打算的文章数在 300 篇左右,到 2022年9月22日为止,目前曾经更新了 133 篇,专栏完成度为 44.3%.作者简介Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后退出 SAP 成都研究院工作至今。Jerry 是 SAP 社区导师,SAP 中国技术大使。在长达 15 年的 SAP 规范产品开发生涯里,Jerry 已经先后参加 SAP Business ByDesign, SAP CRM, SAP Cloud for Customer, SAP S/4HANA, SAP Commerce Cloud(电商云)等规范产品的研发工作。 Jerry 工作中应用 ABAP, Java, JavaScript 和 TypeScript 进行开发, 对包含 SAP UI5 在内的多款 SAP 自研框架有深刻的钻研。 教程目录SAP UI5 本地开发环境的搭建SAP UI5 利用开发教程之一:Hello WorldSAP UI5 利用开发教程之二:SAP UI5 的疏导过程 BootstrapSAP UI5 利用开发教程之三:开始接触第一个 SAP UI5 控件SAP UI5 利用开发教程之四:XML 视图初探SAP UI5 利用开发教程之五:视图控制器初探SAP UI5 利用开发教程之六 - 理解 SAP UI5 的模块(Module)概念SAP UI5 利用开发教程之七 - JSON 模型初探SAP UI5 利用开发教程之八 - 多语言的反对SAP UI5 利用开发教程之九 - 创立第一个 ComponentSAP UI5 利用开发教程之十 - 什么是 SAP UI5 利用的描述符 DescriptorSAP UI5 利用开发教程之十一 :SAP UI5 容器类控件 Page 和 PanelSAP UI5 利用开发教程之十二 - 应用 CSS 类对 UI 进行进一步丑化SAP UI5 利用开发教程之十三 - 如何增加自定义 CSS 类SAP UI5 利用开发教程之十四 - 嵌入视图的应用形式SAP UI5 利用开发教程之十五 - 对话框和 Fragments 的应用形式SAP UI5 利用开发教程之十六 - 图标 icon 的应用SAP UI5 利用开发教程之十七 - 聚合绑定在 UI5 复合控件中的应用SAP UI5 利用开发教程之十八 - SAP UI5 数据绑定语法里的特殊符号,以及相对绑定和绝对绑定概念详解SAP UI5 利用开发教程之十九 - SAP UI5 数据类型和简单的数据绑定SAP UI5 利用开发教程之二十 - SAP UI5 的表达式绑定用法解说SAP UI5 利用开发教程之二十一 - SAP UI5 的自定义格局器 Custom FormatterSAP UI5 利用开发教程之二十二 - 过滤器 filter 的开发和应用SAP UI5 利用开发教程之二十三 - 列表控件的排序 Sort 和分组 GroupSAP UI5 利用开发教程之二十四 - 如何应用 OData 数据模型SAP UI5 利用开发教程之二十五 - 应用自开发的代理服务器解决 SAP UI5 利用拜访远端 OData 服务的跨域问题SAP UI5 利用开发教程之二十六 - OData 服务配合 Mock 服务器的应用步骤详解SAP UI5 利用开发教程之二十七 - SAP UI5 利用的单元测试工具 QUnit 介绍SAP UI5 利用开发教程之二十八 - SAP UI5 利用的集成测试工具 OPA 介绍SAP UI5 利用开发教程之二十九 - SAP UI5 的路由和导航性能介绍SAP UI5 利用开发教程之三十 - SAP UI5 的路由过程中进行参数传递SAP UI5 利用开发教程之三十一 - SAP UI5 的路由历史和路由回退(Routing back and history)SAP UI5 利用开发教程之三十二 - 如何创立一个自定义 SAP UI5 控件SAP UI5 利用开发教程之三十三 - SAP UI5 利用的响应式布局个性(Responsiveness)SAP UI5 利用开发教程之三十四 - SAP UI5 利用基于设施类型的页面适配性能(Device Adaptation)SAP UI5 利用开发教程之三十五 - 如何把本地开发的 SAP UI5 利用部署到 ABAP 服务器上SAP UI5 利用开发教程之三十六 - 应用 Chrome 开发者工具 Elements 标签动静批改 CSS 类SAP UI5 利用开发教程之三十七 - 应用 Chrome 开发者工具 Console 面板进行元素审查SAP UI5 利用开发教程之三十八 - 应用 Chrome 开发者工具查看程序执行出错时的上下文信息SAP UI5 利用开发教程之三十九 - SAP UI5 利用呈现白屏的一些常见谬误和分析方法分享SAP UI5 利用开发教程之四十 - 如何制作蕴含了 component-preload.js 在内的 SAP UI5 公布版本SAP UI5 利用开发教程之四十一 - Chrome 扩大 UI5 Inspector 的离线装置和应用办法SAP UI5 利用开发教程之四十二 - SAP UI5 自带的 Diagnostics 诊断工具应用办法介绍SAP UI5 利用开发教程之四十三 - SAP UI5 自带的 Support Assistant 工具应用办法介绍SAP UI5 利用开发教程之四十四 - Label 和 Input 控件文本没有程度对齐的起因剖析和解决方案SAP UI5 利用开发教程之四十五 - 如何在 SAP UI5 利用里应用 jQuery 和原生的 DOM APISAP UI5 利用开发教程之四十六 - 应用 Message Manager 实现开箱即用的验证(Validation)信息抛出SAP UI5 利用开发教程之四十七 - 如何自定义 SAP UI5 字符串类型输出字段的校验逻辑SAP UI5 利用开发教程之四十八 - 如何在 SAP UI5 利用里开发条形码扫描性能SAP UI5 利用开发教程之四十九 - 如何在桌面电脑端调试运行在手机上的 SAP UI5 利用SAP UI5 利用开发教程之五十 - 如何应用 Cordova 将 SAP UI5 利用生成一个能在 Android 手机上安装的混合利用SAP UI5 利用开发教程之五十一 - 如何应用 Chrome 调试运行在手机上的 SAP UI5 Cordova 混合利用SAP UI5 利用开发教程之五十二 - 如何应用 SAP UI5 的规范控件联合 Cordova 插件调用手机摄像头进行条形码扫描SAP UI5 利用开发教程之五十三 - 如何自定义 SAP UI5 数据类型(Data Type)SAP UI5 利用开发教程之五十四 - 如何将本地 SAP UI5 利用配置到本地 Fiori Launchpad 中SAP UI5 利用开发教程之五十五 - 如何将本地 SAP UI5 利用通过 Node.js Express 部署到公网上SAP UI5 利用开发教程之五十六 - SAP UI5 树控件(tree)的开发SAP UI5 利用开发教程之五十七 - 基于 OData 注解的 Smart Field 应用办法学习SAP UI5 利用开发教程之五十八 - 应用工厂办法在运行时动态创建不同类型的列表行我的项目控件SAP UI5 利用开发教程之五十九 - 如何在 SAP UI5 利用里显示世界地图SAP UI5 利用开发教程之六十 - SAP UI5 地图控件的一些高级用法SAP UI5 利用开发教程之六十一 - 在 SAP UI5 利用里绘制甘特图 Gantt ChartSAP UI5 利用开发教程之六十二 - 基于 OData V4 的 SAP UI5 表格控件应用办法介绍SAP UI5 利用开发教程之六十三 - 基于 OData V4 的本地 Mock Server 实现的深刻介绍SAP UI5 利用开发教程之六十四 - 基于 OData V4 的 SAP UI5 表格控件如何实现 filter(过滤) 和 sort(排序)性能SAP UI5 利用开发教程之六十五 - 基于 OData V4 的 SAP UI5 表格控件如何实现创立,编辑和保留性能SAP UI5 利用开发教程之六十六 - 基于 OData V4 的 SAP UI5 表格控件如何实现删除性能SAP UI5 利用开发教程之六十七 - 基于 OData V4 的 SAP UI5 List-Detail(列表-明细)布局的实现形式SAP UI5 利用开发教程之六十八 - 如何实现 SAP UI5 路由失败时显示自定义的 NOT Found 页面SAP UI5 利用开发教程之六十九 - 如何从 SAP UI5 Not Found 页面跳转回到失常的利用页面SAP UI5 利用开发教程之七十 - 如何应用按钮控件触发页面路由跳转SAP UI5 利用开发教程之七十一 - SAP UI5 页面的嵌套路由SAP UI5 利用开发教程之七十二 - SAP UI5 页面路由的动画成果设置SAP UI5 利用开发教程之七十三 - 应用自定义 Query 实现 SAP UI5 页面路由的书签性能SAP UI5 利用开发教程之七十四 - SAP UI5 利用应用 OData V4 显示 Table 表格数据的一个陷阱SAP UI5 利用开发教程之七十五 - 如何采纳SAP UI5 主从表格的联动技术显示简单表格内容SAP UI5 利用开发教程之七十六 - 如何实现 SAP UI5 的 Lazy Loading(提早加载,懒加载)SAP UI5 利用开发教程之七十七 - SAP UI5 动静页面路由的高级用法:路由记录 routes 和 target 的一对多关系SAP UI5 利用开发教程之七十八 - 如何通过 url 放弃 SAP UI5 搜寻的状态,让其反对书签性能SAP UI5 利用开发教程之七十九 - 采纳测试驱动开发理念(Test Driven Development)进行 SAP UI5 利用的性能开发(一)SAP UI5 利用开发教程之八十 - 采纳测试驱动开发理念(Test Driven Development)进行 SAP UI5 利用的性能开发(二)SAP UI5 利用开发教程之八十一 - 采纳 OPA5 进行 SAP UI5 集成测试(Integration Test)的一个例子SAP UI5 利用开发教程之八十二 - 采纳 OPA5 开发反对页面跳转的 SAP UI5 集成测试用例SAP UI5 利用开发教程之八十三 - SAP UI5 的自动化测试套件页面的开发步骤介绍SAP UI5 利用开发教程之八十四 - 如何指定 SAP UI5 应用程序基于某个特定的版本运行SAP UI5 利用开发教程之八十五 - 如何用 OPA5 编写测试用例来测试用户输出文本的性能SAP UI5 利用开发教程之八十六 - 入手开发一个最简略的本地 Mock 数据服务器SAP UI5 利用开发教程之八十七 - 如何让 SAP UI5 Mock 服务器反对自定义 url 参数SAP UI5 利用开发教程之八十八 - SAP UI5 Mock 服务器如何实现自定义 Function ImportSAP UI5 利用开发教程之八十九 - 如何给 SAP UI5 列表控件削减多个图形界面的过滤器SAP UI5 利用开发教程之九十 - 基于 OData V2 的 SAP UI5 List-Detail(列表-明细)布局的实现形式SAP UI5 利用开发教程之九十一 - 如何应用客户端 JSON 模型构建一个 Master-Detail-Detail 布局中的列表页面SAP UI5 利用开发教程之九十二 - 基于 SAP UI5 JSONModel 客户端模型的列表分页显示(Table Pagination)前提SAP UI5 利用开发教程之九十三 - 基于 JSONModel 数据模型的列表控件显示数据的深刻探讨SAP UI5 利用开发教程之九十四 - 基于 JSONModel 数据模型的 SAP UI5 列表控件分页显示数据的残缺解决方案SAP UI5 利用开发教程之九十五 - SAP UI5 下拉菜单(Select) 控件的应用形式SAP UI5 利用开发教程之九十六 - SAP UI5 列表控件分页显示数据时,如何自定义分页大小SAP UI5 利用开发教程之九十七 - 如何应用客户端 JSON 模型构建一个 Master-Detail-Detail 布局中的明细页面SAP UI5 利用开发教程之九十八 - 从 viewId 这个属性谈起,聊聊 SAP UI5 的 HTML 源代码生成机制SAP UI5 利用开发教程之九十九 - 深入探讨 SAP UI5 本地开发环境里的 package.json 和 ui5.yamlSAP UI5 利用开发教程之一百 - 如何批改 SAP UI5 框架的源代码实现,以及应用本地部署的 SAP UI5 SDKSAP UI5 利用开发教程之一百零一 - SAP UI5 利用的 Locale 决定机制SAP UI5 利用开发教程之一百零二 - SAP UI5 利用的打印(Print)性能实现详解SAP UI5 利用开发教程之一百零三 - 如何在 SAP UI5 利用中生产第三方库SAP UI5 利用开发教程之一百零四 - SAP UI5 表格控件的反对复选(Multi-Select)以及如何用代码一次选中多个表格行我的项目SAP UI5 利用开发教程之一百零五 - SAP UI5 Master-Detail 布局模式的联动成果实现明细介绍SAP UI5 利用开发教程之一百零六 - 如何进步 SAP UI5 利用路由 url 的可读性SAP UI5 利用开发教程之一百零七 - SAP UI5 OverflowToolbar 容器控件以及 resize 事件处理的一些细节介绍SAP UI5 利用开发教程之一百零八 - SAP UI5 图片显示控件 Avatar 的应用形式介绍SAP UI5 利用开发教程之一百零九 - 应用 SAP UI5 FileUploader 控件上传本地文件SAP UI5 利用开发教程之一百一十 - SAP UI5 FileUploader 控件深刻介绍 - 为什么须要一个暗藏的 iframeSAP UI5 利用开发教程之一百一十一 - SAP UI5 FileUploader 控件实现本地文件上传,接管服务器端的响应时遇到跨域拜访谬误SAP UI5 利用开发教程之一百一十二 - 应用自开发的代理服务器解决 SAP UI5 FileUploader 上传文件时遇到的跨域拜访谬误SAP UI5 利用开发教程之一百一十三 - 授人以渔 - 如何自行查问任意 SAP UI5 控件属性的文档和技术实现细节SAP UI5 利用开发教程之一百一十四 - 如何通过单步调试的形式找到引起 Fiori Launchpad 路由谬误的起因SAP UI5 利用开发教程之一百一十五 - 对于将本地 SAP UI5 利用配置到本地 Fiori Launchpad 的技术实现深刻解说SAP UI5 利用开发教程之一百一十六 - 在 SAPGUI 里应用 ABAP 报表上传 SAP UI5 利用到 ABAP 服务器SAP UI5 利用开发教程之一百一十七 - 本地开发好的 SAP UI5 利用部署到 ABAP 服务器时,中文字符变成乱码的起因剖析和解决方案SAP UI5 利用开发教程之一百一十八 - 如何剖析因为 SAP UI5 版本差别带来的问题SAP UI5 利用开发教程之一百一十九 - 对于 SAP UI5 Container 控件 aggregation 的深入分析SAP UI5 利用开发教程之一百二十 - 如何依据 SAP UI5 框架代码抛出的谬误音讯,反查出是哪一行代码引起的谬误音讯SAP UI5 利用开发教程之一百二十一 - 一键部署开箱即用的代理服务器,解决 SAP UI5 利用开发过程中拜访远端 OData 服务的跨域问题SAP UI5 利用开发教程之一百二十二 - 在 SAP UI5 利用中应用浏览器原生的 Fetch API 发动网络申请SAP UI5 利用开发教程之一百二十三 - 应用 Busy Dialog 动画阻止 SAP UI5 利用按钮短时间内疾速被点击SAP UI5 利用开发教程之一百二十四 - 应用函数节流思维防止 SAP UI5 利用里按钮短时间内被高频反复点击SAP UI5 利用开发教程之一百二十五 - SAP UI5 进阶 - XML 视图里定义的 UI 控件,运行时实例化的技术细节分析SAP UI5 利用开发教程之一百二十六 - SAP UI5 进阶 - JSON 模型字段里的值,显示在最终 UI5 界面上的神秘剖析SAP UI5 利用开发教程之一百二十七 - SAP UI5 利用的全局配置(Global Configuration) 的设计和应用SAP UI5 利用开发教程之一百二十八 - SAP UI5 智能控件 Smart Controls 的初步意识SAP UI5 利用开发教程之一百二十九 - 如何给 SAP UI5 SmartField 增加 Value Help 性能SAP UI5 利用开发教程之一百三十 - 如何使 SAP UI5 SmartField 在运行时渲染成超链接的模式并反对跳转SAP UI5 利用开发教程之一百三十一 - SAP UI5 Cross Application Navigation (跨利用间跳转)的本地模仿实现SAP UI5 利用开发教程之一百三十二 - SAP UI5 Simple Form 控件的应用办法介绍SAP UI5 利用开发教程之一百三十三 - SAP UI5 利用元数据文件 manifest.json 的加载和解析原理解说SAP UI5 利用开发教程之一百三十四 - SAP UI5 Simple Form 属性 columnsL,columnsM,columnsXL 的属性深刻分析SAP UI5 利用开发教程之一百三十五 - 正在写作中......阐明Jerry 从 2014 年退出 SAP成都研究院 CRM Fiori 开发团队之后开始接触 SAP UI5,已经在 SAP 社区和 汪子熙 微信公众号上发表过多篇对于 SAP UI5 工作原理和源码解析的文章。 ...

September 26, 2022 · 6 min · jiezi

关于javascript:nodemodules-文件夹下-bin-隐藏文件夹的作用

如下图所示: 答案:That is a folder where binaries (executables) from your node modules are located. node modules 可执行文件的存储文件夹所在。 本地装置(默认):将货色放在以后包根目录的 ./node_modules 中。全局装置(应用 -g):将内容放在 /usr/local 或装置节点的任何地位。如果您要 require() 它,请在本地装置它。如果要在命令行上运行它,请全局装置它。如果两者都须要,则将其装置在两个地位,或应用 npm 链接。前缀配置默认为装置节点的地位。 在大多数零碎上,这是 /usr/local. 在 Windows 上,它是 %AppData%\npm. 在 Unix 零碎上,它是上一级的,因为 node 通常装置在 {prefix}/bin/node 而不是 {prefix}/node.exe。 设置全局标记后,npm 会将内容装置到此前缀中。 如果未设置,则应用以后包的根目录,如果不在包中,则应用当前工作目录。 executables在全局模式下,可执行文件链接到 Unix 上的 {prefix}/bin,或间接链接到 Windows 上的 {prefix}。 确保门路位于终端的 PATH 环境中以运行它们。 在本地模式下,可执行文件链接到 ./node_modules/.bin 以便它们可用于通过 npm 运行的脚本。 (例如,当您运行 npm test 时,测试运行程序将在门路中。) 临时文件默认存储在 tmp 配置指定的文件夹中,默认为 TMPDIR、TMP 或 TEMP 环境变量,或在 Unix 上为 /tmp,在 Windows 上为 c:\windows\temp。 ...

September 26, 2022 · 1 min · jiezi

关于javascript:html2canvas常见踩坑问题

一、html2canvas图片留白 图片留白的问题应该是页面有滚动条,所以导致截屏又留白,解决形式有两种: 1. 将页面window.scrollTo(0,0)这样能够解决,然而有的时候滚动会让用户看到,体验不好,所以,咱们能够看下另外一种形式 2. 设置参数this.$html2canvas(document.getElementById('attack'),{scrollY: 0}) 这样也能解决问题;二、html2canvas生成图片那一刻,控制台有报错 遇到这样的问题就要查看本人html代码加载图片的那局部,通常是,截屏的时候某个图片加载谬误,万能的解决办法是在加载图片的中央加上判断 v-if 这样三、html2canvas生成图片过大,跳转页面无奈传到下个页面 这个问题我已经找了一个通宵,最初定位到这图片太大太大了,存本地也不行,存数据库更不行,倡议大家如果有携带截图到下个页面的操作就通过hash模式扭转页面url,或者生成图片的时候尽量少的html构造以上几点是自己开发过程中遇到的问题,如有问题,请斧正,心愿多多交换

September 26, 2022 · 1 min · jiezi

关于javascript:数字孪生全要素场景介绍L0L5-级

明天与大家分享,数字孪生全因素场景分类(L0-L5 级) 一、 全因素场景概述图观的全因素场景,基于实在的地理信息,汇合物理世界各种因素,通过计算机实时渲染而生成的可交互三维仿真场景,能够广泛应用于各行业数字孪生利用构建。 全因素场景是构建数字孪生利用的外围,依据数据源、应用环境和场景精密度,从宏观到宏观,划分为 L0-L5 六个级别,基于全因素场景,能够便捷高效地进行二次开发、构建行业数字孪生利用。 二、 场景级别划分介绍1. L0 地块级 场景形容:包含地形、区域边界、卫星影像,不辨别世界、国家、省、市等级别最小观看间隔:10000m模型规范:依据 GIS 区域 Shp 信息、高程信息、卫星影像信息生成模型,不蕴含建筑物贴图规范:卫星影像图 2. L1 城市级 场景形容:大概 500 平方公里以内,蕴含地形、次要修建、路网(准确到县道)、水系的低精度模型,蕴含下一级行政区划分界线和下一级行政区划地名散点标牌最小观看间隔:3000m修建模型规范:依据 GIS 修建轮廓和修建层高信息生成模型修建贴图规范:随机贴图 3. L2 城区级 场景形容:大概 25 平方公里以内,蕴含地形、次要修建、路网(准确到 1 级路线)、水系、次要植被的低精度模型,蕴含下一级行政区划分界线和下一级行政区划地名散点标牌最小观看间隔:1000m修建模型规范:依据 GIS 修建轮廓和修建层高信息生成模型修建贴图规范:随机贴图 4. L3 园区级 场景形容:大面积城市由设计资产主动生成摆放,蕴含地形地貌、次要修建、路网、水系、植被、城市基础设施的高精度模型建模,重点修建进行手工建模超高精度还原。最小观看间隔:200m修建模型规范:形态靠近修建贴图规范色彩靠近 5. L4 修建级 场景形容:基于模型资产进行超高拟真建模,准确还原修建 / 设施外观材质、纹理细节、简单构造,蕴含修建外围设施、植被、部件、车道线、车辆、行人、楼体构造、高空、墙面、栏杆、窗框等因素的超高精度模型和贴图成果。修建模型规范:精度 0.1 米修建贴图规范:拟真度 > 90% 6. L5 设施 / 室内精模 场景形容:超高精密度、拟真建模还原,可高精度还原室内修建 / 设施外观材质、纹理细节、简单构造、外部零部件、管线等细节,精确还原因素对象材质质感。修建模型规范:形态拟真修建贴图规范:色彩拟真 理解更多数字孪生常识欢送关注:数字冰雹官网微信公众号

September 26, 2022 · 1 min · jiezi

关于javascript:有关大文件上传和下载相关知识的整合

一.后期筹备 做大文件上传和下载,是须要肯定的常识储备的。其中综合了不少畛域的知识点,很综合的一项技能,能够对技能做一次很好的整合。写一篇这样的文章,也很考验文字水平,心愿这一篇文章之后,可能晋升本人的了解水平,有一个比拟粗浅的印象。 说到文件,那必定少不了前端中的文件(File)、二进制(Blob)、文件读取(FileReader)。大文件上传,一次性上传必定是不事实的,须要对文件进行分片,而后后端获取后进行整合,那么,Blob.prototype.slice或者File.prototype.slice也是切片时必不可少的。 因为前端会将资源分块,而后独自发送申请,也就是说,原来 1 个文件对应 1 个上传申请,当初可能会变成 1 个文件对应 n 个上传申请(HTTP2的多路复用),所以前端能够基于 Promise.all将这多个接口整合,上传实现在发送一个合并的申请,告诉服务端进行合并。合并时可通过 nodejs 中的读写流(readStream/writeStream),将所有切片的流通过管道(pipe)输出最终文件的流中。 而在发送申请资源时,前端会定好每个文件对应的序号(spark-md5),并将以后分块、序号以及文件 hash 等信息一起发送给服务端(因为计算内容的hash须要工夫,还须要思考 WebWorker),服务端在进行合并时,通过序号进行顺次合并即可。 而一旦服务端某个上传申请失败,会返回以后分块失败的信息,其中会蕴含文件名称、文件 hash、分块大小以及分块序号等,前端拿到这些信息后能够进行重传,同时思考此时是否须要将 Promise.all 替换为 Promise.allSettled 更不便。 二.相干知识点串讲1.File,Blob以及FileReadera. File: b. Blob: c. FileReader:

September 26, 2022 · 1 min · jiezi

关于javascript:JS算法之回溯法

强大和无知不是生存的阻碍,高傲才是 --《三体·死神永生》大家好,我是柒八九。 明天,咱们持续摸索JS算法相干的知识点。咱们来谈谈对于回溯法的相干知识点和具体的算法。 如果,想理解其余数据结构的算法介绍,能够参考咱们曾经公布的文章。如下是算法系列的往期文章。 文章list整数惯例排序算法数组字符串链表栈队列二叉树好了,天不早了,干点闲事哇。 你能所学到的知识点何为回溯法汇合的组合、排列利用回溯算法解决其余问题何为回溯法回溯法能够看做暴力法的升级版,它在解决问题时的每一步都尝试所有可能的选项,最终找出所有可行的解决方案。回溯法非常适合解决由多个步骤组成的问题,并且每个步骤都有多个选项。 用回溯法解决问题的过程能够形象的用一个树形构造示意,求解问题的每个步骤能够看作树中的一个节点。如果在某一步有n个可能的选项,那每个选项是树中的一条边,通过这些边就能够达到该节点的n个子节点。在采纳回溯法解决问题时, 如果达到树形构造的叶节点,就找到了问题的一个解。如果心愿找到更多的解,能够回溯到以后节点的父节点,再尝试父节点其余的选项如果父节点所有可能的选项都曾经试过,那么再回溯到父节点的父节点,持续尝试其余选项,这样逐层回溯到树的根节点。因而,采纳回溯法解决问题的过程本质上是在树形构造中从根节点开始进行深度优先遍历通常,回溯法的深度优先遍历用递归代码实现。 如果在返回某个节点时对问题的解的状态进行了批改,那么在回溯到它的父节点时,要革除相应的批改。 剪枝因为回溯法是在所有选项造成的树上进行深度优先遍历,如果解决问题的步骤较多或每个步骤都面临多个选项,那么遍历整颗树将须要较多的工夫。如果明确晓得某些子树没有必要遍历,那么在遍历的时候应该避开这些子树以优化效率。 通常将应用回溯法时防止遍历不必要的子树的办法称为剪枝。 汇合的组合、排列从一个蕴含m个元素的汇合中挑选出n个元素(0≤n≤m)造成一个<span style="font-weight:800;color:#FFA500;font-size:18px">{子集|Subset}</span>。一个子集又称为一个组合。如果两个子集(组合)的元素完全相同只是程序不同,那么它们能够看作同一个子集(组合)。 从一个蕴含m个元素的汇合中挑选出n个元素(0≤n≤m)并依照某种程序造成一个排列。 m等于n的排列有称为全排列。如果两个排列的元素完全相同只是程序不同,那么它们就是两个不同的排列。 排列与元素的程序相干。 所有子集题目形容: 输出一个不含反复数字的数据汇合,请找出它的所有子集输出:nums = [1,2,3]输入:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]剖析子集就是从一个汇合中选出若干元素。 如果汇合中蕴含n个元素,那么生成子集能够分为n步每一步从汇合中取出一个数字,此时面临两个抉择 将该数字增加到子集中不将该数字增加到子集中生成一个子集能够分成若干步,并且每一步都面临若干抉择 -- 回溯法 代码实现function subsets(nums){ let result = []; if(nums.length == 0) return result; (function helper(nums,index,subset,result){ if(index === nums.length){ // 基线条件 result.push([...subset]) }else if(index < nums.length){ helper(nums,index + 1, subset,result); // 不将数字增加到子集 subset.push(nums[index]); // 将数字增加到子集中 helper(nums,index + 1,subset,result); subset.pop(); } })(nums,0,[],result) return result;}代码解释 递归函数helper有四个参数 nums 是数组nums,蕴含输出汇合的所有数字。能够逐个从汇合中取出一个数字并抉择是否将数字增加到子集中。index是以后取出的数字在数组nums中下标subset是以后子集result是所有曾经生成的子集每当从数组nums中取出一个下标为index的数字时,都要思考是否将该数字增加到子集subset中。 不将数字增加到子集的情景。不对子集进行任何操作,只须要调用递归函数helper解决数组nums中的下一个数字(下标减少1) helper(nums,index + 1,subset,result)将下标为index的数字增加到子集subset中。 ...

September 26, 2022 · 3 min · jiezi

关于javascript:一比一手写迷你版vue彻底搞懂vue运行机制

前言当初前端面试Vue中都会问到响应式原理以及如何实现的,如果你还只是简略答复通过Object.defineProperty()来劫持属性可能曾经不够了。 本篇文章通过学习文档及视频教程实现手写一个繁难的Vue源码实现数据双向绑定,解析指令等。 几种实现双向绑定的做法目前几种支流的mvc(vm)框架都实现了单向数据绑定,而我所了解的双向数据绑定无非就是在单向绑定的根底上给可输出的元素(input, textare等)增加了change(input)事件,来动静批改model和view,并没有多浅近,所以无需太过介怀是实现的单向或双向绑定。 实现数据绑定的做法有大抵如下几种:发布者-订阅者模式(backbone.js) 脏值查看(angular.js) 数据劫持(Vue.js) 发布者-订阅者模式个别是通过sub, pub的形式来实现数据和试图的绑定坚听,更细数据办法通常做法是vm.set('property', value)这种形式当初毕竟太low来,咱们更心愿通过vm.property = value这种形式更新数据,同时自动更新视图,于是有来上面两种形式。 脏值查看angular.js是通过脏值检测的形式比照数据是否有变更,来决定是否更新视图,最简略的形式就是通过setInterval()定时轮询检测数据变动,当然Google不会这么low,angular只有在制订的事件触发时进入脏值检测,大抵如下 * DOM事件,臂如用户输出文本,点击按钮等(ng-click)* XHR响应事件($http)* 浏览器location变更事件($location)* Timer事件($timeout, $interval)* 执行$diaest()或¥apply()数据劫持Vue.js则是通过数据劫持联合发布者-订阅者模式的形式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时公布音讯给订阅者,触发相应的监听回调。 vue全家桶视频解说:进入学习Vue源码实现index.html <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript" src="./compile.js"></script> <script type="text/javascript" src="./observe.js"></script> <script type="text/javascript" src="./myvue.js"></script> </head> <body> <div id="app"> <h2>{{person.name}} -- {{person.age}}</h2> <h3>{{person.sex}}</h3> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <div v-text="msg"></div> <div>{{msg}}</div> <div v-text="person.name"></div> <div v-html="htmlStr"></div> <input type="text" v-model="msg" /> <button type="button" v-on:click="btnClick">v-on:事件</button> <button type="button" @click="btnClick">@事件</button> </div> <script type="text/javascript"> let vm = new Myvue({ el: '#app', data: { person: { name: '只会番茄炒蛋', age: 18, sex: '男' }, msg: '学习MVVM实现原理', htmlStr: '<h1>我是html指令渲染的</h1>' }, methods: { btnClick() { console.log(this.msg) } } }) </script> </body></html>第一步 - 实现一个指令解析器(Compile)compile次要做的事件是解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,增加监听数据的订阅者,一旦数据有变动,收到告诉,更新视图 ...

September 26, 2022 · 5 min · jiezi

关于javascript:函数柯里化

函数柯里化什么是函数柯里化在计算机可迷信中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把承受多个参数的函数变换成承受一个繁多参数(最后函数的第一个参数)的函数,并且返回承受余下的参数而且返回后果的新函数的技术。 柯里化疾速入门接下来,咱们来通过一个例子来领会一下柯里化。 现有一个求两个数之和函数: function add(a,b){ return a + b;}将add函数柯里化变成: function addCurrying(a){ return function (b){ return a + b; }}能够看出,函数addCurrying承受原函数的第一个参数,并且返回了一个承受余下参数的函数,利用了闭包的个性存储了a的值。所以咱们通过下面的代码示例,咱们可能理解到柯里化函数的特点: 1、一个柯里化的函数首先会承受一下参数,承受了这些参数之后该函数并不会立刻求值,而是返回了另一个函数,刚承受的参数会在函数造成的闭包中保留下来。2、等到函数须要被真正求值时即原函数所需参数全副接管完,会对闭包中存储的数据一并求值。 函数柯里化的理论利用通过下面的例子,咱们体验到了什么是柯里化函数。 然而问题来了,费了这么大劲封装一层,到底有什么用途呢 没有益处想让咱们程序员多干事件是不可能滴,这辈子都不可能 所以接下来咱们就来看一下函数柯里化的二个理论利用。 参数复用就是将雷同的参数固定下来 // 失常正则验证字符串reg.test(txt)//函数封装后function check(reg,txt){ return reg.test(txt);}//即便是雷同的正则表达式,也须要从新传递一次console.log(check(/\d+/,'test1')) //trueconsole.log(check(/\d+/,'testt')) //false//柯里化(currying)后function checkCurrying(reg){ return function (txt){ return reg.test(txt); }}var hasNumber = checkCurring(/\d+/);console.log(hasNumber('test1'));console.log(hasNumber('testt'));能够看出当将check函数柯里化后能够固定同一正则表达式这一参数,失去一个只须要接管须要检测的字符串的函数。达到了参数复用的目标。 提前确认var on = function(element,event,handler){ if(document.addEventListener){ if(element && event && handler){ element.addEventListener(event,handler,false); } }else{ if(element && event && handler){ element.attachEvent('on' + event,handler) } }}on(div,'click',function(){})var onCurrying = (function(){ if(document.addEventListener){ return function(element,event,handler){ if(element && event && handler){ element.addEventListener(event,handler,false); } } }else{ return function(element,event,handler){ if(element && event && handler){ element.attachEvent('on' + event,handler); } } }})()on(div,'click',function(){})咱们在做我的项目的过程中,封装DOM的操作能够说再失常不过,下面第一种写法也是比拟常见,然而咱们看看第二种写法,它绝对于第一种写法就是自执行而后返回一个新的函数,这样就提前确定了会走哪一个办法,防止每次都进行判断。 ...

September 25, 2022 · 1 min · jiezi

关于javascript:webapi2-今天全是大经典案例

明天的案例又大又经典 我想想怎么搞呢因为要用到外联款式之类的了 写入内联也太大了 1. 先来一个独自小页面的吧 一个仿淘宝右侧侧边栏的案例 不多说都在正文里了 <!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> <style> header { width: 80%; height: 500px; background-color: aqua; } nav { width: 80%; height: 600px; margin: 20px 0; background-color: saddlebrown; } section { width: 80%; height: 1500px; background-color: gold; } aside { position: absolute; top: 60%; right: 17%; width: 60px; height: 100px; background-color: sandybrown; } </style></head><body> <header></header> <nav></nav> <section></section> <aside></aside> <script> // 这小小的一道题 还真不轻松 前面还要再做几遍 先来复盘一下 // 第一步先取得nav的一个offsettop实际上就是咱们要转为fixed的像素点 而后这里有个关键点 同时用aside也就是侧边栏的offsettop减去nav的top // 作为等会转为fixed的一个top值 这个很要害 不然等会依照相对定位的top值来 就会忽然挑一下 不够天然 var aside = document.querySelector('aside') var nav = document.querySelector('nav') var navTop = nav.offsetTop var asideOffsetTop = aside.offsetTop var asideTop = asideOffsetTop - navTop // 第二局部 滚动到section的offsettop的时候显示返回顶部 var section = document.querySelector('section') // 失去这两个值便能够进入滚动事件 document.onscroll = function() { if (window.pageYOffset >= navTop) { aside.style.position = 'fixed' aside.style.top = asideTop + 'px' } else { aside.style.position = 'absolute' aside.style.top = asideOffsetTop + 'px' } if (window.pageYOffset >= section.offsetTop) { aside.innerText = '返回顶部' } else { aside.innerText = '' } } </script></body></html>2. ...

September 25, 2022 · 4 min · jiezi

关于javascript:一个关于React数据不可变的无聊问题

对于一个React的开发者来说不晓得你有没有想过为什么React谋求数据不可变这个范式; 一个月前我想过一个问题如果我在应用useState这个hooks的时候传入的是一个扭转后的援用类型对象会产生什么? 例如: import {useState} from "react"function App() { const [list,setList] = useState([0,1,2]) const handleClick = ()=>{ list.push(list.length) setList(list) } return ( <div className="App"> <button onClick={handleClick}>click me--conventionality</button> {list.map(item=><div key={item}>{item}</div>)} </div> );}export default App;而后当咱们点击按钮的时候会产生什么呢?答案是从咱们的视觉感官来讲什么也没有产生!列表数据始终是012;对于这个后果我置信百分之99的react开发者都是能够意料的!也必定有百分之80以上的人会说因为你的新数据和老数据是同一个(newState===oldState)===true在这个问题上答案也的确是这个一个。那么newState与oldState是在哪里做的比拟,又是在哪里做的拦挡呢?我之前想的是会在render阶段update时的reconcileChildFibers中打上effectTag标记判断前做的判断,然而当我明天在给beginWork后我发现以上这个代码压根走不到beginWork (mount阶段),带着好奇我决定从源码登程去摸索一下(答案可能会有点无聊); 咱们晓得useState这个hooks生成 const [list,setList] = useState([0,1,2])是dispatchAction这个办法 mountState阶段而useState分为两种mountState与updateState,因为setList是在mount时被创立的所以咱们先去查看他是如何被创立的 function mountState(initialState) { var hook = mountWorkInProgressHook(); if (typeof initialState === 'function') { // $FlowFixMe: Flow doesn't like mixed types initialState = initialState(); } hook.memoizedState = hook.baseState = initialState; var queue = { pending: null, interleaved: null, lanes: NoLanes, dispatch: null, lastRenderedReducer: basicStateReducer, lastRenderedState: initialState }; hook.queue = queue; //创立dispatch办法并保留到链式当中 //dispatch是通过dispatchSetState这个办法创立的 var dispatch = queue.dispatch = dispatchSetState.bind(null, currentlyRenderingFiber$1, queue); //这一步return出链式当中的list与setList return [hook.memoizedState, dispatch];}dispatch是通过dispatchSetState这个办法创立的,而后咱们去dispatchSetState中去查看 ...

September 25, 2022 · 4 min · jiezi

关于javascript:继续我们的复习之路webapi

后面断更几天是因为在住安心温习DOM BOM的内容 不得不说 还得是DOM 在这一章节的复习内容中 涌现出了很多又代表意义 经典的一些小案例 而且 还是有些难度的 有一两个我反正是本人独立实现不了 可能是不相熟 我曾经做了记号了反正,下次间接抓住这些第一次没有独立实现的来做,这一次的案例很多我可能要分两篇随笔能力写进去我先来前几天的案例吧 先来第一个,间接上狠的,这个是第一个卡我的案例,有点绕,我正文的是我本人做的时候的逻辑,前面是看着他人做进去想的逻辑不得不说还是过来人有教训,化骨绵掌一样给我的问题在无形中就解决了,很简略经典的一个案例就是全选全不选然而充斥逻辑 <!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> <style> * { padding: 0; margin: 0; } .wrap { width: 300px; margin: 100px auto 0; } table { border-collapse: collapse; border-spacing: 0; border: 1px solid #c0c0c0; width: 300px; } th, td { border: 1px solid #d0d0d0; color: #404060; padding: 10px; } th { background-color: #09c; font: bold 16px "微软雅黑"; color: #fff; } td { font: 14px "微软雅黑"; } tbody tr { background-color: #f0f0f0; } tbody tr:hover { cursor: pointer; background-color: #fafafa; } </style></head><body> <div class="wrap"> <table> <thead> <tr> <th> <input type="checkbox" id="j_cbAll"/> </th> <th>商品</th> <th>价格</th> </tr> </thead> <tbody id="j_tb"> <tr> <td> <input type="checkbox" /> </td> <td>iPhone8</td> <td>8000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>iPad Pro</td> <td>5000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>iPad Air</td> <td>2000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>Apple Watch</td> <td>2000</td> </tr> </tbody> </table> </div> <script> // 第一个需要点击下面全选 上面全副选中 再点一次全选 全副不选中 /* var checkAll = document.getElementById('j_cbAll') var tbody = document.getElementById('j_tb') var checkSingles = tbody.querySelectorAll('input') var flag = 1 checkAll.addEventListener('click', function() { if (flag == 1) { for (var i = 0; i < checkSingles.length; i++) { checkSingles[i].setAttribute('checked','true') } flag = 0 } else { for (var i = 0; i < checkSingles.length; i++) { checkSingles[i].removeAttribute('checked') } flag = 1 } }) // 第二个需要就是上面 顺次点满 全选会勾上 var counts = 0 for (var i = 0; i < checkSingles.length; i++) { checkSingles[i].onclick = function() { if (this.checked) { counts++ } else { counts-- } } } if (counts == 4) { checkAll.setAttribute('checked','true') } */ // 全选 var checkAll = document.getElementById('j_cbAll') var tbody = document.getElementById('j_tb') var checkSingles = tbody.querySelectorAll('input') checkAll.onclick = function() { for (var i = 0; i < checkSingles.length; i++) { checkSingles[i].checked = this.checked } } // 单选全选 for (var i = 0; i < checkSingles.length; i++) { checkSingles[i].onclick = function() { for (var i = 0; i < checkSingles.length; i++) { var flag = true if (!checkSingles[i].checked) { flag = false break } } checkAll.checked = flag } } // 这个案例 还是有点不相熟啊 属实有点太绕了 下面正文的是我第一次本人做的的想法 前面感觉有点做不上来了 无奈又看了看原来的代码 还是原来的比拟优良 还是没有了解其中奥秘 </script></body></html>而后是一个删除留言案例,这道题实现起来 其实是挺简略的 然而有一个问题 我搞了老半天也没解决下来 就先存在这里前面再来弄 就是在公布进去的留言栏那里 也就是每一个li外面的文字 我输出多了 他会始终往后面延长 超出范围了还在前面延长 我要的成果是超出范围就换行 可能听起来挺简略 然而我始终没弄对代码 ...

September 24, 2022 · 5 min · jiezi

关于javascript:JavaScript4错误类型及常见报错

SyntaxError 示意语法错误。当谬误的应用曾经预约义的语法时会抛出此谬误TypeError 示意类型谬误。当值不是预期数据类型、调用有效办法时都会抛出此谬误ReferenceError 示意援用谬误。当找不到变量的援用、在变量作用域范畴之外应用变量、应用未声明的变量时、在暂时性死区期间应用变量时都会抛出此谬误URIError 示意 URI 谬误。当 URI 的编码和解码呈现问题时,会抛出 URIError。JavaScript 中的 URI 操作函数包含:decodeURI、decodeURIComponent 等。如果应用了谬误的参数(有效字符),就会抛出 URIErrorRangeError 示意范畴谬误。将变量设置在其限定的范畴之外、将值传递给超出范围的办法、调用一个不会完结的递归函数时就会抛出此谬误Uncaught SyntaxError: Unexpected token '<' 代表‘<’ 这个符号不应该存在Uncaught SyntaxError: Invalid or unexpected token 语法错误,当呈现这句话的时候,应该查看标点符号是否正确Uncaught TypeError: Cannot read property 读取一个未定义的对象的属性或调用其办法时Failed to load resource 文件没有被找到,阐明文件援用的门路有问题,或文件损坏Uncaught ReferenceError: $ is not defined 文件加载的程序不对,没有被定义就被应用了,jQuery文件的程序要在后面Uncaught TypeError: Cannot set property 'onclick' of null 绑定了onclick事件的js文件放在head外面时就会呈现这样的谬误,当浏览器从上向下解析时,找不到onclick绑定的按钮节点,所以报错。须要把js文件放在底部加载。Cannot use import statement outside a module 用了es6的语法, 浏览器默认将它作为js解析会呈现问题,须要将它作为模块导入,script标签默认type="text/javascript",须要改为type="module"微信小程序APP-SERVICE-SDK:setStorageSync:fail write DB data fail 存储数据失败,将存储和读取数据的代码封装成模块,定义一个全局变量,存储数据时先保留一份在全局变量中,而后try-wx.setStorageSync catch-wx.setStorage,保留两次。读取时同样的。let storageObj = {};function getKey(key) { if (storageObj[key]) { return storageObj[key]; } else { try { return wx.getStorageSync(key); } catch (err) { return wx.getStorage({ key: key, success: function(res) { return res.data; } }); } }}function setKey(key, value) { storageObj[key] = value; try { wx.setStorageSync(key, value); } catch (e) { wx.setStorage({ key: key, data: value }); }}http申请状态码1xx 长期响应并须要请求者继续执行操作的状态代码2xx 申请胜利3xx 重定向4xx 申请出错5xx 服务器谬误 ...

September 24, 2022 · 1 min · jiezi

关于javascript:Module-Federation-模块联邦-在Vue3中使用Vue2搭建的微服务

前言:备注:本文基于对webpack Module Federation有肯定理解的状况下 个别状况下应用模块联邦都是会应用雷同的版本,如Vue2的组件时在Vue2中应用,但我为什么会在Vue3我的项目中去应用Vue2的组件呢,其实是因为历史起因。好几个老的外围的我的项目都是应用Vue2来写的,在中期以及闲暇的时候团队是有机会应用Vue3去重构,然而并没有这样做,到了当初这个阶段曾经太晚了,我的项目变得宏大,人员也缩小了。最近在保护一个我的项目,被折磨得不行,比方一个.vue文件有3千行代码,框架设计不合理,不易于保护,更不易于多人保护。所以,我决定抽空去重构。Vue3绝对于Vue2的益处显而易见,故索性应用Vue3 + ts + pinia + element-plus + webpack,因为要应用module federation,所以应用webpack,因为Vite 对module federation反对还是不太好一、如何应用:尽管webpack官网并没有介绍,然而在GitHub中找到了Module Federation demo,传送门。 首先,咱们把demo跑起来。 1.将代码拉下来:https://github.com/module-fed... 2.在最外层目录装置依赖 yarn3.进入vue2-in-vue3这个目录,执行命令启动 yarn start这时候会启动两个服务,其中vue3应用了vue2的Button组件: 应用方HOST (vue3): localhost:3002提供方REMOTE (vue2): localhost:3001webpack相干配置: vue2 webpack配置plugins: [ ... new ModuleFederationPlugin({ name: 'vue2App', filename: 'remoteEntry.js', library: { type: 'var', name: 'vue2App' }, exposes: { './vue2': './node_modules/vue/dist/vue', // 留神点:这里须要把vue裸露进来,起因前面讲 './Button': './src/components/Button', }, }), ... ],vue3 webpack配置plugins: [ ... new ModuleFederationPlugin({ name: 'vue3', filename: 'remoteEntry.js', remotes: { vue2App: '[email protected]://localhost:3001/remoteEntry.js', }, }), ... ],vue3我的项目 App.vue文件<template> <div> <h3>Vue3 App</h3> <Content :count="count"/> <!--这里跟咱们应用一般组件有一点区别 1、失常状况咱们只须要这样写: <Button @btnClick="inc"/> 2、而这里则须要应用一个元素来将挂载组件 --> <div id="vue2Button"></div> <vue2-button @btnClick="inc"/> </div></template><script>import { ref } from "vue";import Content from "./components/Content";import { vue2ToVue3 } from './utils';import Button from 'vue2App/Button';export default { components: { Content, // 通过一个办法,将vue2的组件转为vue3的组件,并挂载在id为'vue2Button'的元素上 vue2Button: vue2ToVue3(Button, 'vue2Button'), }, setup() { const count = ref(0); const inc = () => { count.value++; }; return { count, inc, }; }};</script>utils.js,外围在于应用vue2ToVue3办法,应用vue2渲染函数将vue2组件挂载到指定元素import Vue2 from 'vue2App/vue2';function bindSlotContext(target = {}, context) { return Object.keys(target).map(key => { const vnode = target[key]; vnode.context = context; return vnode; });}/* 外围 * Transform vue2 components to DOM.(官网正文) * 了解:这里通过应用vue2的渲染函数,将导入的组件挂载在指定的节点上,奇妙地让vue2的组件能在vue3中应用 * * 的确解决了问题,然而在应用的时候会有一些弊病: * * 1、存在弊病:每应用一个组件就须要写一个元素去承载,在应用比拟频繁的组件中,如:button、input 等罕用组件, * 一个页面可能应用十分多个,那么在书写的时候就须要创立很多元素去承载,所以在这种场景下不太适宜应用 * * 2、应用场景:应用频率低,有交互的、略微简单一点的组件 */export function vue2ToVue3(WrapperComponent, wrapperId) { let vm; return { mounted() { const slots = bindSlotContext(this.$slots, this.__self); vm = new Vue2({ render: createElement => { return createElement( WrapperComponent, { on: this.$attrs, attrs: this.$attrs, props: this.$props, scopedSlots: this.$scopedSlots, }, slots, ); }, }); vm.$mount(`#${wrapperId}`); }, props: WrapperComponent.props, render() { vm && vm.$forceUpdate(); }, };}vue2我的项目,Button.vue, 留神点:<template> <button @click="click">vue2 button click</button></template><script>export default { methods: { click() { this.$emit("btnClick"); // vue3 事件命名须要应用大驼峰,并且前以on结尾 this.$emit("onBtnClick"); } }}</script>二、常见问题:一、Uncaught Error: Shared module is not available for eager consumption其实webpack官网是有给出解决办法的,详情见这里 ...

September 24, 2022 · 2 min · jiezi

关于javascript:JavaScript入门

JavaScript 概述介绍JavaScript是一门脚本语言,不须要编译就能够间接被浏览器解析执行。它是运行在浏览器中的,每一个浏览器都有本人的JavaScript解析引擎。 JavaScript能够用来加强用户和html页面的交互过程,能够来管制html元素。让页面有一些动静的成果,以此来加强用户的体验。 特点交互性(它能够做的就是信息的动静交互)安全性(不容许间接拜访本地硬盘)跨平台性(只有是能够解释 JS 的浏览器都能够执行,和平台无关)发展史1992年,Nombase公司,开发出第一门客户端脚本语言,专门用于表单的校验。命名为 C– ,起初更名为ScriptEase1995年,Netscape(网景)公司,开发了一门客户端脚本语言:LiveScript。起初,请来SUN公司的专家,批改LiveScript,命名为JavaScript1996年,微软剽窃JavaScript开发出JScript语言1997年,ECMA(欧洲计算机制造商协会),制订出客户端脚本语言的规范:ECMAScript,就是对立了所有客户端脚本语言的编码方式。JavaScript = ECMAScript + JavaScript本人特有的货色(BOM+DOM)JavaScript根底语法与html联合形式JavaScript与Html联合的办法总有两种,即——外部JS和内部JS。 外部JS概述间接在html页面中书写JavaScript代码,所书写的JavaScript代码应用Script标签包围起来。 格局<script type="text/javascript"> JS代码</script>演示<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Demo</title> <!--在外部定义JS--> <script type="text/javascript"> alert("Hello World"); </script></head><body></body></html>内部JS概述应用script标签,通过src属性引入内部的js文件。 格局<script type="text/javascript" src="JS文件地址"></script>演示<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Demo</title> <!--援用内部JS--> <script type="text/javascript" src="../JavaScript/one.js"></script></head><body></body></html>script标签能够定义在html页面的任何中央,然而定义的地位会影响其执行程序。script标签也能够在一个html页面,同时定义多个。JavaScript正文概述JavaScript的正文格局和Java的完全一致,无论是单行正文,还是多行正文。 单行正文格局//正文内容演示//这是一个单行正文多行正文格局/* 正文内容 */演示/* 这是一个多行正文 */JavaScript数据类型概述JavaScript也同Java一样,数据类型分为两类,即——原始数据类型、援用数据类型。 原始数据类型number类型整数小数NaN(not a number,一个不是数字的数字类型)string类型单引号与双引号定义的都是字符串类型,Javascript没有字符类型的概念。 boolean类型truefalsenull类型一个对象为空的占位符。 undefined类型未定义。如果一个变量没有给初始化值,则会被默认赋值为undefined。 援用数据类型对象。Javascript中的援用数据类型也都是对象。 JavaScript变量概述JavaScript与Java中的变量很相识,但又并不完全相同。根本原因为Javascript为弱类型语言,而Java为强类型语言。什么是弱类型语言,什么是强类型语言呢?上面我来简略的阐明一下: 弱类型语言:在开拓变量存储空间时,不定义空间未来的存储数据类型,而是能够寄存任意类型的数据。强类型语言:在开拓变量存储空间时,定义了空间未来存储的数据的数据类型,只能存储固定类型的数据。正是因为语言类型的不同,导致了两种语言的变量也有不同的用意,下文我次要表述其不同之处。 格局//定义变量(默认赋值为undefined)var 变量名;//定义并初始化值var 变量名 = 初始值;演示//定义变量(默认赋值为undefined)var num01;var num02;var num03;//接管number类型值num01 = 1;num02 = 3.14;num03 = NaN;//定义并初始化string类型值var str01 = '2';var str02 = "two";var str03 = '我是一个二';//定义并初始化boolean类型值var flag01 = true;var flag02 = false;//定义并初始化null类型值var obj = null;//定义并初始化undefined类型值var und01 = undefined;var und02;//默认赋值为undefined新个性ES2015(ES6) 新减少了两个重要的 JavaScript 关键字: let 和 const。 ...

September 24, 2022 · 4 min · jiezi

关于javascript:关于-SAP-UI5-Web-Components

SAP UI5 Web Components 是 UI5 Evolution 我的项目的要害支柱,以实现 UI5 的 UI 元素的轻量级和独立生产。 顾名思义,它们是应用 Web 组件规范构建的。 Web 组件实用于所有支流浏览器。 它们基于一组 Web 规范,例如自定义元素、Shadow DOM、HTML 模板和 ES6 类和模块。 Web 组件容许创立自定义 HTML 标签,扩大浏览器的规范 HTML 标签词汇。 在这些自定义 HTML 标签的背地,它们提供了通过 HTML 和 CSS 定义的视觉外观以及应用 JavaScript 实现的行为。 最初,Web 组件的长处在于它们能够与任何应用 HTML 标记的 Web 框架一起工作。 看个具体的例子: UI5 Web Components 是 UI5 的新产品,提供根本的和选定的高级 UI 元素作为 Web 组件。 就像 UI5 控件一样,这些 UI 元素是依据 SAP Fiori 设计指南施行的,并联合了 SAP Fiori 3 设计。 因而,它们非常适合确保动态网站和 Web 应用程序的视觉和行为一致性。 UI5 Web 组件的外观和行为就像 UI5 控件一样。 此外,它们还具备相熟的企业级性能,例如稳定性、国际化、可拜访性和主题反对。 与 UI5 控件相比,UI5 Web 组件的占用空间要小得多,因为 UI5 控件嵌入在应用程序编程模型中,而 UI5 Web 组件不是。 正是这将 UI5 Web 组件与 UI5 控件辨别开来。 它们使您可能将咱们的 UI 元素与您抉择的任何基于 HTML 的 UI 技术一起应用。 ...

September 24, 2022 · 1 min · jiezi

关于javascript:前端必读30如何在-Angular-中使用SpreadJS实现导入和导出-Excel-文件

在之前的文章中,咱们为大家别离具体介绍了在JavaScript、React中应用SpreadJS导入和导出Excel文件的办法,作为带给宽广前端开发者的“三部曲”,本文咱们将为大家介绍该问题在Angular中的实现。Excel 电子表格自 1980 年代以来始终为各行业所宽泛应用,至今已领有超过3亿用户,大多数人都相熟 Excel 电子表格体验。许多企业在其业务的各个环节中应用了 Excel 电子表格进行估算和布局。通常状况下,刚开始时咱们的业务流程中的数据简略,也不波及简单的格局和数据关系。但随着组织的倒退,可能很难不开始依赖 Excel 的性能。 在你的应用程序中装置 SpreadJS 组件残缺的Demo请点击此处下载:https://gcdn.grapecity.com.cn... 应该留神的是,因为咱们应用的是 Angular CLI,咱们须要确保它与 NPM 一起装置: npm install -g @angular/cli因为咱们将应用 SpreadJS 的 Excel 导入和导出性能,因而咱们须要 ExcelIO 组件。你能够应用 NPM 装置它和根本的 SpreadJS 文件: npm install @grapecity/spread-sheets @grapecity/spread-excelio @grapecity/spread-sheets-angular实例化 SpreadJS 组件SpreadJS 能够增加到 app.component.html 页面,如下所示: <gc-spread-sheets [backColor]=”spreadBackColor” [hostStyle]="hostStyle" (workbookInitialized)="workbookInit($event)"></gc-spread-sheets>实例化 SpreadJS 组件并在 app.component.ts 文件中创立 ExcelIO 类的对象,代码如下: @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']})export class AppComponent { spreadBackColor = 'aliceblue'; hostStyle = { width: '95vw', height: '80vh' }; private spread; private excelIO; constructor() { this.spread = new GC.Spread.Sheets.Workbook(); this.excelIO = new Excel.IO(); } workbookInit(args: any) { const self = this; self.spread = args.spread; const sheet = self.spread.getActiveSheet(); sheet.getCell(0, 0).text('Test Excel').foreColor('blue'); sheet.getCell(1, 0).text('Test Excel').foreColor('blue'); sheet.getCell(2, 0).text('Test Excel').foreColor('blue'); sheet.getCell(3, 0).text('Test Excel').foreColor('blue'); sheet.getCell(0, 1).text('Test Excel').foreColor('blue'); sheet.getCell(1, 1).text('Test Excel').foreColor('blue'); sheet.getCell(2, 1).text('Test Excel').foreColor('blue'); sheet.getCell(3, 1).text('Test Excel').foreColor('blue'); sheet.getCell(0, 2).text('Test Excel').foreColor('blue'); sheet.getCell(1, 2).text('Test Excel').foreColor('blue'); sheet.getCell(2, 2).text('Test Excel').foreColor('blue'); sheet.getCell(3, 2).text('Test Excel').foreColor('blue'); sheet.getCell(0, 3).text('Test Excel').foreColor('blue'); sheet.getCell(1, 3).text('Test Excel').foreColor('blue'); sheet.getCell(2, 3).text('Test Excel').foreColor('blue'); sheet.getCell(3, 3).text('Test Excel').foreColor('blue'); } ...

September 23, 2022 · 2 min · jiezi

关于javascript:微信跳转到支付宝App自动领取赏金红包

对于支付宝赏金红包这件事,其实曾经好几年了,我记得2020年就曾经有这个了,当初通过一个链接在微信点击,就会主动跳转到支付宝支付赏金,那一年我的赏金就曾经赚了2w多,起初支付宝为了避免这个滥用,封禁了这个办法。 新的计划先看动图演示: 也是一个URL,而后点击进去,因为微信做了相干的限度,只有是在微信内关上其它的app都得有个弹窗,不然的话就间接跳了,所以会有一个弹窗,点击确定就间接跳转到支付宝。 这个计划其实就是应用了钉钉的一个API的跳转到支付宝的。 代码<!DOCTYPE html><html><head> <title>拼手气红包,支付宝官网流动!</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style type="text/css"> *{ margin:0; padding:0; } /*body{ background: url(./bg.png); }*/ #bg{ width: 100%; height: 100%; position: fixed; top: 0; } #bg img{ width: 100%; height: 100%; } </style></head><body> <div id="bg"> <a href="https://ulink.alipay.com/?scheme=alipays%3A%2F%2Fplatformapi%2Fstartapp%3FsaId%3D10000007%26clientVersion%3D3.7.0.0718%26qrcode%3Dhttps%253A%252F%252Frender.alipay.com%252Fp%252Fc%252Falipay-red-qrcode%252Fshared.html%253Fchannel%253Dsearch_pwd%2526shareId%253D2088602294611742%2526token%253D196139496tmg2vcinfrii8chMb%2526campStr%253DkPPFvOxaCL3f85TiKss2wsBZgIjulHjG%2526sign%253DqsiVOoa7TuphryWxyBdONXsMTnE3jiIBvWeUs3yV1sw%253D%2526chInfo%253DDingtalk%2526c_stype%253Dsearch_pwd"><img src="./bg.gif" /></a> </div></body><script type="text/javascript">window.onload=function(){ window.location = 'https://ulink.alipay.com/?scheme=alipays%3A%2F%2Fplatformapi%2Fstartapp%3FsaId%3D10000007%26clientVersion%3D3.7.0.0718%26qrcode%3Dhttps%253A%252F%252Frender.alipay.com%252Fp%252Fc%252Falipay-red-qrcode%252Fshared.html%253Fchannel%253Dsearch_pwd%2526shareId%253D2088602294611742%2526token%253D196172230ot5hzl0xl3kzdenRO%2526campStr%253DkPPFvOxaCL3f85TiKss2wsBZgIjulHjG%2526sign%253DqsiVOoa7TuphryWxyBdONXsMTnE3jiIBvWeUs3yV1sw%253D%2526chInfo%253DDingtalk%2526c_stype%253Dsearch_pwd';}</script></html>代码剖析及批改代码中有一个背景是我本人PS做的,这个也是为了仿一个H5页面,做一个a标签去做跳转,另外也是加了一个onload事件去做主动跳转。 咱们只须要批改两个地位,shareId 和 token 即可。 shareId 能够用支付宝扫描下方二维码就能够取得。 token 须要在赚钱红包页面点击分享,而后分享至钉钉,这个时候,二维码就会被保留,而后用微信扫码,进去就是一个token,将这个token的 19 结尾后面的删除,剩下的就是咱们须要的token。 替换进去之后,将html文件上传到本人服务器就能够用了! 体验demo请应用微信扫码体验。 作者TANKING 如需进我的群,能够加:sansure2016

September 23, 2022 · 1 min · jiezi

关于javascript:回归

前段时间 因为一些事件耽搁 的确这个事件苦恼了我很久 我第一次感触到 就是我很想非常致力的去学习 去扭转本人 然而一种力不从心的感觉 一种不给你机会的感觉 如果前面有机会我会专门发一篇随笔来写这几个月我在干嘛 还真是讥刺 后面才说梦开始的中央 后果就戛然而止了 哈哈哈 当初回来了 回来过后先是开始温习我感觉 所以这几天都在温习 两天工夫就把h5 c3 挪动端布局温习完了 的确当初再去看一看以前学的更加得心应手了 可能本人实现一些动态页面动画成果过渡成果等等 挪动端也可能用rem vwvh来实现 然而我感觉这些也没得啥子好展现的 所以我间接给你们看看 根底语法嘛 这才是真正梦开始的中央 这几天在温习根底语法js 这也是 更加得心应手了 很多案例本人不停歇就间接敲下来了 做了很多 我挑几个我做的不是很顺利 就是懂了点脑筋的 js还是判若两人的乏味哈哈 <!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> <script> /* 在控制台一次性打印形态如下:☆ ☆☆ ☆☆☆ ☆☆☆☆ ☆☆☆☆☆ */ var str = '' for (var i = 1; i <= 5; i++) { for (var j = 1; j <= i; j++) { str += '⭐' } str += '\ ' } console.log(str); // 别看这个一串星星 看着简略 还是了解好大半天才给她搞明确 为什么呢 我认为是只有打印进去就能够了 最开始弄得是一个阶梯型的星排列 这个还真要控制台输入久了才想的明确 我就在想不把他弄成阶梯型 那就是要一次性输入进去 那我就在外层循环输入 那不还是这样吗 分了五次才输入结束 最初想明确 间接在循环外来个总输入 先把所有的后果用str存储 </script></body></html><!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> <script> for (var i = 1; i < 10; i++) { var str = '' for (var j = 1; j <= i; j++) { var result = i * j str += j + '*' + i + '=' + result str += '\t' } console.log(str); } // 还是能够 原来99乘法表对我来说是一个难点 当初做出还是蛮快的 但我还是好菜 好久没回来更菜了 </script></body></html><!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> <script> // 接管用户输出的用户名和明码,若用户名为 “admin” ,且明码为 “123456” ,则提醒用户登录胜利! 否则,让用户始终输出。 var userName = prompt('请输出用户名') var passward = prompt('请输出明码') while (userName || passward) { if (userName == 'admin' && passward == '123456') { alert('登录胜利') break } else { userName = prompt('请输出用户名') passward = prompt('请输出明码') } } // 我感觉 我这样有点冗余 但如同又想不出其余方法了 我依稀记得 我原来做的时候 本人想的那个办法很简便 </script></body></html><!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> <button>点击</button> <script> /* 用户在弹出的输入框中抉择要做的运算用户抉择后弹出两个输入框,让用户输出数据依据用户抉择的操作和输出的数据,计算出最初后果并弹出提示框显示后果 */ var btn = document.querySelector('button') console.log(btn); function getCount() { var project = prompt('请输出你要的操作:\n1.加\n2.减\n3.乘\n4.除\n5.退出') var num1 , num2 switch (parseInt(project)) { case 1: num1 = prompt('请输出第一个数') num2 = prompt('请输出第二个数') alert('后果为' + (parseInt(num1) + parseInt(num2))) break; case 2: num1 = prompt('请输出第一个数') num2 = prompt('请输出第二个数') alert('后果为' + (num1 - num2)) break; case 3: num1 = prompt('请输出第一个数') num2 = prompt('请输出第二个数') alert('后果为' + (num1 * num2)) break; case 4: num1 = prompt('请输出第一个数') num2 = prompt('请输出第二个数') alert('后果为' + (num1 / num2)) break; default: break; } } btn.onclick = function() { getCount() } </script></body></html>前端爱好者,望大佬给个内推机会!!! ...

September 23, 2022 · 2 min · jiezi

关于javascript:新人发博第二天-前端商品查询案例

明天的这个案例 应用到的es5的语法 数组的三个遍历的办法 别离是 forEach filter and some 这个案例是让我好好领会了一下 这三个数组 亦或者是es5语法的魅力 还是遇到了一个小难点的 各位能够在代码中找找 哈哈 <!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> <style> table { width: 400px; border: 1px solid #000; border-collapse: collapse; margin: 0 auto; } td, th { border: 1px solid #000; text-align: center; } input { width: 50px; } .search { width: 600px; margin: 20px auto; } </style></head><body> <div class="search"> 依照价格查问: <input type="text" class="start"> - <input type="text" class="end"> <button class="search-price">搜寻</button> 依照商品名称查问: <input type="text" class="product"> <button class="search-pro">查问</button> </div> <table> <thead> <tr> <th>id</th> <th>产品名称</th> <th>价格</th> </tr> </thead> <tbody> </tbody> </table> <script> // 1.动静渲染数据 var data = [ { id : 1, name : 'oppo', price : 3999 }, { id : 2, name : '小米', price : 999 }, { id : 3, name : '光荣', price : 1299 }, { id : 4, name : '华为', price : 6999 } ] var tBody = document.querySelector('tbody') // 2.1 这个函数上面还要执行一次 罗唆封装起来 function loopArr(arr) { // 2.2先清空一下 不然前面重建表格不太好建 tBody.innerHTML = '' arr.forEach(function (value,index) { var tr = document.createElement('tr') // 2.3上面依照价格查问有个小bug 进去的id 还是原来的 所以不应该取数据外面的id 新表格就应该重新排列 新的id程序 var index = index + 1 tr.innerHTML = '<td>'+ index +'</td><td>'+value.name+'</td><td>'+value.price+'</td>' tBody.appendChild(tr) }) } loopArr(data) // 第二个 版块 依照价格查问 var search = document.querySelector('.search') search.children[2].addEventListener('click', function() { var minVal = search.firstElementChild.value var maxVal = search.children[1].value // console.log(minVal, maxVal); var datas = data.filter(function(value) { return value.price >= minVal && value.price <= maxVal }) // console.log(datas); // 能找到返回胜利的数据 数组保留起的 nice 那我就从新对表格来个 调配不就完事了 // 封装好了函数 再次执行 loopArr(datas) }) // 3.依照商品名称查问 search.lastElementChild.addEventListener('click',function() { var str = this.previousElementSibling.value // console.log(str); // 3.1这里咱们就比作每个商品名称就只有一种 意思就是名称不太容易重名 所以用数组的some办法 能够更快一点 var newValue data.some(function(value) { // 本来打算这么做 然而调试看了一下 死活都不给我true 对上了都熟视无睹一样 /* value = value.name return str === value.name */ if (str == value.name) { newValue = value return true } }) // console.log(newValue); // 不倡议采纳原来数组赋值 应该创立一个新数组 这里只是图疾速一点 if (newValue != undefined) { data = [newValue] loopArr(data) } }) </script></body></html>前端爱好者,望大佬给个内推机会!!! ...

September 23, 2022 · 2 min · jiezi

关于javascript:照片添加水印功能

外围代码import EXIF from "exif-js";// 入口const waterMarkToPanel = async (panelFile, waterMarkFile) => { const orientation = await getOrientation(panelFile); const panelBase64Url = await getBase64(panelFile); const waterMarkBase64Url = await getBase64(waterMarkFile); // 获取panel图片的原生宽度、高度、图片元素 const panelNatureData = await getNatureData(panelBase64Url); // 获取水印图片的原生宽度、高度、图片元素 const waterMarkNatureData = await getNatureData(waterMarkBase64Url); // 解决画布旋转/加水印 return startDraw(orientation, panelNatureData, waterMarkNatureData);};// 开始解决画布并加水印const startDraw = (orientation, panelNatureData, waterMarkNatureData) => { const canvas = document.createElement("canvas"); const ctx: any = canvas.getContext("2d"); // panel图片数据 const { naturalWidth, naturalHeight, element: panelEle} = panelNatureData; // waterMark图片数据 const { naturalWidth: wNatureWidth, naturalHeight: wNatureHeight, element: waterMarkEle} = waterMarkNatureData; // 解决画布旋转, 挪动端存在一些兼容性,ios之类 switch (Number(orientation)) { case 6: console.log("照片顺时针旋转了270度"); canvas.width = naturalHeight; // 留神这里,canvas宽度理论取的是图片高度,因为图片的方位是旋转过270度的,以下类试 canvas.height = naturalWidth; ctx.rotate((90 * Math.PI) / 180); // 既然照片方位顺时针转了270度,那再转90度,相当于一共转了360度,相当于没转,这是方位就正确了 ctx.translate(0, -canvas.width); // 转了90度,是不是地位也变了,想想图片在第一象限,绕原点顺时针转了90度,那就转到第二象限了,那就须要超y方向移上去 ctx.drawImage(panelEle, 0, 0, canvas.height, canvas.width); // 画图 // 复原坐标 画完图,须要将canvas复原原位,不解释了,有点绕 ctx.translate(0, canvas.width); ctx.rotate((-90 * Math.PI) / 180); break; case 8: console.log("照片顺时针旋转90度"); canvas.width = naturalHeight; canvas.height = naturalWidth; ctx.rotate((-90 * Math.PI) / 180); ctx.translate(-canvas.height, 0); ctx.drawImage(panelEle, 0, 0, canvas.height, canvas.width); // 复原坐标 ctx.translate(canvas.height, 0); ctx.rotate((90 * Math.PI) / 180); break; case 3: console.log("照片顺时针旋转180度"); canvas.width = naturalWidth; canvas.height = naturalHeight; ctx.rotate((180 * Math.PI) / 180); ctx.translate(-canvas.width, -canvas.height); ctx.drawImage(panelEle, 0, 0, canvas.width, canvas.height); // 复原坐标 ctx.translate(canvas.width, canvas.height); ctx.rotate((-180 * Math.PI) / 180); break; default: canvas.width = naturalWidth; canvas.height = naturalHeight; ctx.drawImage(panelEle, 0, 0, canvas.width, canvas.height); break; } // 在画布上加水印 canvas.drawImage https://www.runoob.com/try/try.php?filename=tryhtml5_canvas_drawimage ctx.drawImage( waterMarkEle, (40 / 750) * canvas.width, canvas.height - ((40+ wNatureHeight) / 750) * canvas.width, (wNatureWidth / 750) * canvas.width, (wNatureHeight / 750) * canvas.width ); const url = canvas.toDataURL("image/jpeg"); // 最终图片url const file = dataURItoBlob(url); // 最终图片file return { url, file }};工具函数// 获取照片方向const getOrientation = (file) => { return new Promise((resolve, reject) => { const currentVersion = getVersion(); // ios 版本号 const support = testVersion(currentVersion, "13.4.1"); // ios版本号大于13.4.1, 无需非凡解决 if (browserInfo.versions.ios && support) { resolve(1); } else { EXIF.getData(file, () => { resolve(EXIF.getTag(file, "Orientation")); }); } });};// 获取base64const getBase64 = (file) => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.addEventListener("load", () => resolve(reader.result)); reader.readAsDataURL(file); });};// 获取图片原生尺寸const getNatureData = (imgUrl) => { return new Promise((resolve, reject) => { const img = new Image(); img.setAttribute("crossOrigin", "Anonymous"); img.onload = (e: any) => { resolve({ element: img naturalWidth: e.target.naturalWidth, naturalHeight: e.target.naturalHeight, }); }; img.src = imgUrl; });};// 判断ios版本 preVersion是否大于lastVersionexport const testVersion = ( preVersion: string = "", lastVersion: string = "") => { const sources = preVersion.split("."); const dests = lastVersion.split("."); const maxL = Math.max(sources.length, dests.length); let result = true; for (let i = 0; i < maxL; i++) { let preValue = sources.length > i ? sources[i] : "0"; let preNum = isNaN(Number(preValue)) ? preValue.charCodeAt(0) : Number(preValue); let lastValue = dests.length > i ? dests[i] : "0"; let lastNum = isNaN(Number(lastValue)) ? lastValue.charCodeAt(0) : Number(lastValue); if (preNum < lastNum) { result = false; break; } else if (preNum > lastNum) { result = true; break; } } return result;};export const getVersion = () => { const str = navigator.userAgent.toLowerCase(); const version = str.match(/cpu iphone os (.*?) like mac os/); let currentVersion = "0.0.0"; // ios 版本号 if (version && version[1]) { currentVersion = version[1].replace(/_/g, "."); } return currentVersion;};// 转换为 blob 间接传输 临时无用export const dataURItoBlob = (dataURI: string) => { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs var byteString = atob(dataURI.split(",")[1]); // separate out the mime component var mimeString = dataURI .split(",")[0] .split(":")[1] .split(";")[0]; // write the bytes of the string to an ArrayBuffer var ab = new ArrayBuffer(byteString.length); var ia = new Uint8Array(ab); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } try { // 新版本浏览器 return new window.Blob([ia], { type: mimeString }); } catch (e) { // TypeError old chrome and FF // Android 中该形式有效 window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; if (e.name === "TypeError" && window.BlobBuilder) { var bb = new window.BlobBuilder(); bb.append(ab); return bb.getBlob(mimeString); } else { return null; } }};demo尝试https://codesandbox.io/s/canv... ...

September 23, 2022 · 3 min · jiezi

关于javascript:图扑数字孪生军事营区实现主动防御

前言20 世纪 50 年代初中国人民解放军开始自建营区。传统营区管理系统以独立的“点状”零碎为主,不足集控平台,全局治理复杂度高。70 年代末提出建设智能化营区,并向“数字化、智能化、网络化、互动化、交融化”的方向聚拢。通过建设集光电、雷达、红外、电磁频谱监测、北斗定位、物联网和虚构仿真等技术于一体的场区监控零碎,对外围训练场区实现广域笼罩、多维感知、全景展示,进一步撑持态势掌控,丰盛沙盘推演、复盘检讨及丰盛场区管理手段。 成果展现图扑软件数字孪生的智能化营区集指挥办公、军事训练、政治文化、营连生存、后装保障、交融服务六大区域于一体。将可视化技术与物联网、大数据、云计算、边缘计算、AI 等技术联合,促成物的智能与官兵智慧在军事治理畛域的最优汇聚,实现人员治理、风格治理、平安治理、能耗治理、设施治理、预警治理等性能中的海量数据分析,达到“信息备战、信息施训、信息促管、信息共享、数据可视、智能利用”目标。 通过 Hightopo 构建的可视化营区以人工轻量化建模的形式搭建营房修建、给排水设施、供电设施、供暖设施、绿化设施、消防设施、训练场、营区路线等物理环境。成果次要以贴图出现,模型精度高,场景互动性强,可自在进行单体化解决。图扑软件也提供导入 IFC 格局的 BIM 性能,在某些场景下应用 BIM 信息升高开发成本. 将工夫信息接入图扑可视化零碎,离开模仿白天、黑夜,提供贴合理论的 24 小时监控场景。通过可视化零碎实现数据的获取、剖析、利用和展现,横向买通各类智能感知设施,实现“一张图”看全部队人员、配备、物资、安防等各类数据,进行全因素、多维度的动态显示和剖析研判。 图扑软件可通过航拍歪斜摄影,以大范畴、高精度、高清晰的形式全面感知简单场景,获取丰盛的建筑物顶面及侧视的高分辨率纹理。实在反映地物信息,通过定位、交融、建模等技术,生成具备天文坐标系信息的三维营区模型。航拍建模能够精确的和 GIS 匹配,能够依据用户浏览时和场景的间隔显示不同精度的 LOD 层级模型。 市面上的 GIS 零碎常见的是基于 Cesium、Mapbox、Leaflet、Openlayers 等进行实现。HT for Web GIS 产品反对对不同地图瓦片服务或数据、航拍歪斜摄影实景的 3DTiles 格局数据以及城市建筑群等不同的 GIS 数据的加载,同时,联合 BIM 数据轻量化、三维视频交融等技术劣势,在 GIS 零碎中对海量的 POI 数据、交通流量数据、布局数据,现状数据等进行多样化的可视化展现。 系统分析军事营区“兵者,战、守、迁,皆施于营垒。”营区作为部队赖以生存的物质基础,地址个别依据军事部署、自然环境、修建技术和经济指标等择优选定,需无利战备、不便生存。个别以城镇为依靠,凑近交通要道。营房智能化程度与军队后勤保障、部队训练、生存、战备非亲非故。智能化营区能适应多型部队:一栋营房满足多种需要;一栋库房匹配多代配备。 通过监督雷达、全景视频监控、可见光红外双光谱摄像机、电磁频谱监测设施、气象监测设施、高精度时空感知设施、物联网基站等传感设施。实现电磁频谱监测、高精度时空感知、全景视频监控、气象环境监测、雷达戒备察看等全维态势的感知。 鸟瞰漫游 采纳图扑轻量化三维建模技术,依据营区现场的 CAD 图、鸟瞰图、设施三视图等材料进行还原外观建模展示科技会议楼、办公楼、宿舍、行政楼、车库、军械库等营区修建。也可通过 BIM 可视化解决方案构建修建的三维场景,通过 BIM 转 OBJ 性能和加载后通过 API 扭转色彩、更换贴图性能,实现 BIM 模型的外观优化。采纳第一人称视角漫游模仿在营区内的巡视过程,并进行禁区或者危险区域的查看。通过无人机视角漫游鸟瞰整个园区设施、设施,展现营区的地理环境,周边地形,提前进行自然灾害预警。 库区信息 利用图扑多样化的图表模式展示人员在位数量、车辆可用信息、占地状况、洞库数量、高空库数量。机关战备车库可与机关楼相邻建设,与战备器材库相通,实现疾速装载、疾速出动。不同库存区漫游时自动弹出面板查看温度和湿度,可点击相干图标间接跳转不同库区。 智能监控 图扑软件基于 HTML5 规范的组件库,可无缝对接 HTML5 各项多媒体性能。将营区内重点区域的监控画面接入图扑可视化零碎,对异样指标的静止状态及指标类型精确预计,依据行为或本身状态的变动,实现口头航迹自适应优化调整、高精度跟踪管制,晋升整个网络信息系统的联结监控能力。对各种突发事件及时告警,可联动调取事件周边摄像头查看现场状况,并记录处理过程。当监控拍到营区四周有可疑人员流动或产生火灾等,可视化大屏及时显示,同时响起报警,揭示相干人员解决问题。 ...

September 22, 2022 · 1 min · jiezi

关于javascript:前端我的第一篇博客-梦开始的地方面向对象版tab栏

这是我的第一篇博客 博客生涯才开始 然而人生曾经过来了二十个年头了 才开始弄这个 也没搞得太懂 我本来的想法是想搞个源代码上来 然而看了半天如同就只能传html源代码 那我还有css js的局部呢 我还想给大伙看看性能呢 其实我老早就想开个博客了 始终没找到在哪里来弄 学倒是始终在学 就这么学下来了 从html css h5c3 挪动端适配 js根本语法 jQuery 到当初的js高级语法 es6 只不过后面如同也没什么须要讲的 当初才刚刚 开始 明天搞了个 面向对象版的tab栏 整点图片 上来把 我的话和教训也都在图片里 老手老手 HTML <!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>面向对象 Tab</title> <link rel="stylesheet" href="./styles/tab.css"> <link rel="stylesheet" href="./styles/style.css"></head><body> <main> <h4> Js 面向对象 动静增加标签页 </h4> <div class="tabsbox" id="tab"> <!-- tab 标签 --> <nav class="fisrstnav"> <ul> <li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li> <li><span>测试2</span><span class="iconfont icon-guanbi"></span></li> <li><span>测试3</span><span class="iconfont icon-guanbi"></span></li> </ul> <div class="tabadd"> <span>+</span> </div> </nav> <!-- tab 内容 --> <div class="tabscon"> <section class="conactive">测试1</section> <section>测试2</section> <section>测试3</section> </div> </div> </main> <script src="./js/index.js"></script></body></html>JS ...

September 22, 2022 · 3 min · jiezi

关于javascript:js中识别html标签外的空格-并替换为nbsp-主要用于富文本

let content = row.content; row.content = content.replace(/[^<>]+(?=<)/g, function (match) { return match.replace(/\s/g, '&nbsp;'); });

September 22, 2022 · 1 min · jiezi

关于javascript:从script标签引入AESjs进行加密

<!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></body><script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/aes-js/3.1.2/index.js"></script><script> const aeskeyLocal = '' // 本人写 const aesUtils = aesjs.utils; const key = aesUtils.utf8.toBytes(aeskeyLocal); var AES = new aesjs.ModeOfOperation.ecb(key) function encrypt (word) { var pad = aesUtils.utf8.toBytes(word) var result = AES.encrypt(aesjs.padding.pkcs7.pad(pad)) return aesUtils.hex.fromBytes(result) } function decrypt(text) { var str = AES.decrypt(aesUtils.hex.toBytes(text)) var res = aesjs.padding.pkcs7.strip(str) return aesUtils.utf8.fromBytes(res) } // 加密 const word = '' // 本人写 console.log(encrypt(word)) // 解密 const text = '' // 本人写 console.log(decrypt(text))</script>

September 22, 2022 · 1 min · jiezi

关于javascript:JavaScript2常用内置函数

数组罕用办法栈办法 push pop队列办法 unshift shiftsplice(开始index, 删除length, 插入新增)join 转换成字符串(连接符连接成一字符串) --split("""")slice(start,end)concat(array) 连贯数组reverse() 数组逆序sort() 排序 降序 -- arr.sort(function(a, b){return b-a})lastIndexOf()、indexOf() -- 查找的项, 查找终点地位的索引(可选的) filter()、map()、some()、every()、forEach() -- 数组项, 对应数组索引, 数组自身filter() -- “过滤”性能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。map() -- 指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的后果组成的数组。some() -- 判断数组中是否存在满足条件的项,只有有一项满足条件,就会返回true。every() -- 判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。forEach() --遍历循环、对数组中的每一项运行给定函数, 这个办法没有返回值.arr.forEach(function(item,index,array){}) 字符串罕用办法.slice(start[,end]) --如果为负,将它作为length+[start, end]解决 end>=start 返回空字符串.substring(start,end) -- 如果start或end为NaN或者为正数,那么将其替换为0.substr(start[,length]) .indexOf(substr[,startIndex]) 第一次呈现子字符串地位。如果没有找到子字符串,则返回-1。.lastIndexOf(substr[,startIndex]) 前面查问.split([separator[,limit]]) 将一个字符串宰割为子字符串,而后将后果作为字符串数组返回 limit该值用来限度返回数组中的元素个数.toLowerCase 返回一个字符串,该字符串中的字母被转换成小写.toUpperCase 返回大写字符串.search(reExp)返回与正则表达式查找内容匹配的第一个字符串的地位.concat(str[,str2,str3]) 字符串连贯.replace 用来查找匹配一个正则表达式的字符串,而后应用新字符串代替匹配 日期办法var myDate = new Date();//创立工夫;myDate.getYear();(2位)//获取以后年份;myDate.getFullYear();(4位)//获取残缺年份;myDate.getMonth();(0-11月,0是1月)//获取月份;myDate.getDate();(1-31日)//获取以后日期;myDate.getTime();//(从1970.1.1开始的毫秒数) //获取以后工夫戳Date.now();myDate.getDay();//(0-6,0是星期天) 获取以后星期myDate.toLocaleDateString(); //获取以后日期 年月日myDate.toLocaleTimeString();//获取以后工夫 时分秒myDate.getHours();(0-23) //获取以后小时数myDate.getMinutes();(0-59) //获取以后分钟数myDate.getSeconds();(0-59) //获取以后秒Date.parse();剖析一个蕴含日期的字符串,并返回从1970.1.1开始的毫秒数new Date(year,month,0).getDate();传入年月零,返回以后月份有多少天 数学方法Math.abs() 取绝对值 .ceil() 向上取整 .floor() 向下取整 .round() 四舍五入 .random() 随机数function getRan(n,m,nums){ return Math.floor((Math.random()m+n)nums); }1-10 -- Math.floor(Math.random()*(10)+1)6位随机数[1-9]-- Math.floor((Math.random()9+1)100000) ...

September 22, 2022 · 1 min · jiezi

关于javascript:JavaScript1

JS是一门什么样的语言及特点? 客户端脚本语言,不须要预编译就能够由解释器间接运行;变量涣散定义,属于弱类型语言,对数据类型未做出严格的要求;基于对象,能够应用new创建对象,也能应用现有对象,比方 Object Array Math Date;JS的数据类型 根本数据类型 String Number Boolean undefined null -- 指的是简略的数据段,按值拜访。 援用数据类型 Object(Array Date Regxp Function) -- 可能有多个值形成的对象 按援用拜访。JS如何查找元素? document. getElementById() getElementsByClassName() getElementsByName() getElementsByTagName() querySelector() querySelectorAll() 节点指针 父节点.firstChild -- firstElementChild 父节点.lastChild -- lastElementChild 父节点.childNodes 兄弟节点.previousSibling -- previousElementSibling 兄弟节点.nextSibling -- nextElementSibling 子节点.parentNodeJS如何创立节点? docuement. createElement(元素标签) 创立元素节点 createAttribute(元素属性) createTextNode(文本内容) 创立文本节点JS如何操作节点(插入、替换、复制、删除)? appendChild(增加的新子节点) 向子节点列表开端增加新的子节点 insertBefore(插入以后节点的新节点,已知子节点) 在已知的子节点之前插入新的子节点 son.parentNode.insertBefore 替换节点 replaceChild(要插入的新元素, 将被替换的老元素) 删除节点 removeChild(要删除的节点) 复制节点.cloneNode(true/false) true -- 复制以后节点及其所有子节点 false -- 仅复制以后节点JS属性操作? 获取元素属性.getAttribute(元素属性名) 设置属性.setAttribute(元素属性名, 属性值) 删除属性removeAttribute(元素属性名)7、什么是伪数组? ...

September 22, 2022 · 3 min · jiezi

关于javascript:前端面试题JavaScript篇20220922

每日3题1 以下代码执行后,控制台中的输入内容为?console.log(+true, !'hello')2 点击p标签时,会输入什么const numbers=[1,2,3,4,5]const [y] = numbersconsole.log(y)3 以下代码执行后,控制台中的输入内容为?const fn = (x) => (y) => (z) => { console.log(x, y, z);};fn(1)(2)(3);公众号【明天也要写bug】更多前端面试题答案及解析1// 答案:1 false// 考查运算符和类型转换// 相加运算符:如果+两边有字符串,则将两者拼接为字符串,否则进行相加运算// +true,会将 true 转换成数字 1,最终输入 1console.log(+true, !"hello");// 在 JS 中,假值有:null;NaN;0;空字符串 ("" or '' or ``);undefined.// 除此之外都是真值// !真值 => 假值,!假值 => 真值// 所以 !"hello" 为 false2// 答案:1// 考查 ES6 数组的解构赋值// ES6 容许写成这样:// let [a, b, c] = [1, 2, 3]// 这种写法能够从数组中提取值,依照对应地位,对变量赋值const numbers = [1, 2, 3, 4, 5];const [y] = numbers; // y 对应 1console.log(y); // 故输入 13// 答案:1 2 3// 考查箭头函数的闭包和函数调用的联合性const fn = (x) => (y) => (z) => { console.log(x, y, z);};// fn 相当于:const fn = (x) => { return (y) => { return (z) => { console.log(x, y, z); }; };};fn(1)(2)(3); // 函数调用的联合性是从左到右,等价于const f1 = fn(1); // (y) => {...}const f2 = f1(2); // (z) => { console.log(x, y, z); }f2(3); // 输入 1 2 3

September 22, 2022 · 1 min · jiezi

关于javascript:技术探索借助-CI-CD-实现前端应用的快速回滚

背景在 上一轮优化 里, 咱们通过优化一些构建工具和流程, 把构建耗时优化到了 4min 左右,整体公布耗时从 15min 优化到了 8 min 左右, 有较大晋升, 然而仍旧存在晋升空间。 通过一些思考与测试,给出技术计划,并落地到了 WMS 业务中, 成果如下: 与原流程相比之, 公布耗时由 8 min 升高到了 1 ~2 min 左右。 上面我次要介绍一下计划细节,总结革新过程中遇到的问题, 心愿对大家有所帮忙。 注释整体方案设计1. 现有架构 现有架构有余: 每次执行 jenkins 都要从新开始执行构建、打包操作,十分的耗时。Jenkins 没有留存打包后果,导致无奈做回滚等操作。 以后构建流程中存在大量有效且耗时的构建能够去掉,如应用 docker 打包了镜像,但对于该我的项目而言是无用的。 架构改良 CI/CD 前置打包MR 之后, 会触发 CI, 执行构建工作,构建过程在 2 min 左右, 构建胜利之后, 会把对应的后果推送到对应的分支保存起来。 Jenkins 构建阶段, 间接从对应的分支取回打包后果, 推送到动态资源服务器,这个过程十分快, 1 分钟之内即可实现公布。 须要留神的是: 因为是在 gitlab 中构建的, 这时候会短少一些环境信息, 比方 CID。 WMS业务中并没有用这个参数做一些非凡的逻辑, 所以没有影响。 如果我的项目须要用到 CID, 则须要额定解决。 ...

September 22, 2022 · 2 min · jiezi

关于javascript:拿来吧你图片主色调

原文参考我的公众号文章入门级!提取图片主色调 ImageColor 可提取一张图片的主题色、亮堂色、柔和色以及暗淡色四种色彩!体验地址Features 简略粗犷高效 Promise调用 返回数据丰盛 反对返回色彩散布图谱GC,并生成GC图片保留到本地Usageimport ImageColor from "./index.js";let IC = new ImageColor();IC.analizeImage({ id: "mycanvas", url: './img.png', frequency: 20,}).then((res) => { const { primary, colors, pixels, imageInfo } = res; console.log("主题色:", primary); console.log("三种不同亮度的色彩:", colors); console.log("所有像素", pixels); console.log("图片信息:", imageInfo); // 执行该工作的话-如果响应速度会比较慢的话,能够提早渲染,保障以后页面渲染晦涩 setTimeout(() => { // IC.showGC({ gcid: "graphy_canvas" }); // IC.saveGCImage('色谱.png'); //须要先调用 showGC }, 0);});DetailsIC.analizeImage 为次要办法,承受一个{对象}作为参数,并以 Promise 的形式返回主题色和三阶亮度色彩@params { id: "mycanvas", url: './img.png', frequency: 20,}/*** @param {Object} params* @param params.id String 指定惟一标识,* @param params.url String 要剖析的图片地址* @param params.frequency Number 采样率,值越大,程序执行速度越快,然而会失落大部分像素色彩导致精度会降落,默认 20 */@returns Promise ...

September 22, 2022 · 1 min · jiezi

关于javascript:模板语法-格式化

模板语法中应用 filter中申明函数 残缺代码如下 <li class="news_li" v-for="(item,index) in noticeList" :key="item.id" v-on:click="newsClick(item.id)"> <span>{{ item.publishTime | formatTimer }}</span> <a href="#">{{ item.title }}</a> </li><script> export default { data(){ }, filters: { formatTimer: function (value) { let date = new Date(value); let y = date.getFullYear(); let MM = date.getMonth() + 1; MM = MM < 10 ? "0" + MM : MM; let d = date.getDate(); d = d < 10 ? "0" + d : d; return y + "-" + MM + "-" + d; } }, };</script>

September 22, 2022 · 1 min · jiezi

关于javascript:猿人学十六题

第一步先抓包,发现m加密参数 第二步跟栈,找加密地位 发现是改写了btoa 将这个加密办法扣下来 接下来就是在本地运行补环境,缺什么补什么就好,这里就不一一细说了留神点:当环境补完后,发现加密参数并不能获取到后果在js中搜寻try 发现这里有个判断,在浏览器关上 控制台输出后发现n.g是个window对象 本地打印为undefined 检测了n.g是不是winodw环境,这个js指纹比较简单,间接把n.g换成window就行或者间接给n.g增加环境 function nn(r) { if (t[r]) return t[r].exports; var i = t[r] = { exports: {} }; return e[r].call(i.exports, i, i.exports, n), i.exports } n.g = function () { if ("object" == typeof globalThis) return globalThis; try { return this || new Function("return this")() } catch (e) { if ("object" == typeof window) return window } }();

September 22, 2022 · 1 min · jiezi

关于javascript:js滚动浏览器滚动条js滚动元素滚动条

该代码能够实现滚动浏览器、任意dom元素程度方向、垂直方向的滚动条至指定地位。常见场景有:置顶、置底滚动成果:程度方向滚动 垂直方向滚动 代码: /** * 设置浏览器或元素滚动条滚动间隔 * @param ele dom元素或window对象 * @param direction 滚动条方向,默认为y,可选值有:x、y * @param to 滚动条行将滚动到到地位 * @param duration 时长(可选) * @param onDone 实现后的回调(可选) * @param onScroll 正在滚动中的回调(可选) * @returns {boolean} */function scrollTo (ele, direction, to, duration, onDone, onScroll) { if (!ele) { return false; } if (!window.requestAnimationFrame) { window.requestAnimationFrame = ( window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { return window.setTimeout(callback, 1000/60); } ); } if (!direction) { direction = 'y'; } direction = direction == 'x' ? 'x' : 'y'; var doDone = function () { if (typeof onDone == 'function') { onDone(); } } var callOnScroll = function () { if (typeof onScroll == 'function') { onScroll(); } } var attr = direction == 'x' ? 'scrollLeft' : 'scrollTop'; var scrollLeft = function (ele) { if (ele && ele.nodeType == 1) { return ele.scrollLeft; } return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; } var scrollTop = function (ele) { if (ele && ele.nodeType == 1) { return ele.scrollTop; } return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } if (!duration || duration <= 0) { if (ele === window) { window.scrollTo(direction === 'x' ? to : scrollLeft(), direction === 'y' ? to : scrollTop()); } else { ele[attr] = to; } callOnScroll(); doDone(); return true; } var diff = to - ele[attr]; if (ele === window) { diff = to - (direction == 'x' ? scrollLeft() : scrollTop()); } var perTick = (diff / duration) * 10; window.requestAnimationFrame(function () { // 实现缓动成果 if (ele === window) { let x = scrollLeft(); let y = scrollTop(); window.scrollTo(direction === 'x' ? (x + perTick) : x, direction === 'y' ? (y + perTick) : y); callOnScroll(); if (direction == 'x' ? scrollLeft() : scrollTop() !== to) { scrollTo(ele, direction, to, duration - 10, onDone, onScroll); } else { callOnScroll(); doDone(); } return; } ele[attr] += perTick; if (ele[attr] !== to) { callOnScroll(); tool.scrollTo(ele, direction, to, duration - 10, onDone, onScroll); } else { callOnScroll(); doDone(); } }); return true; }调用: ...

September 21, 2022 · 2 min · jiezi

关于javascript:前端面试题JavaScript篇20220920

每日3题1 以下代码执行后,控制台中的输入内容为?// index.jsconsole.log(1);import { sum } from "./sum.js";console.log(sum(1, 2)); //sum.jsconsole.log(2);export const sum = (a, b) => a + b;2 以下代码执行后,控制台中的输入内容为?const value = { number: 10 };const multiply = (x = { ...value }) => { console.log((x.number *= 2));};multiply();multiply();multiply(value);multiply(value);3 以下代码在浏览器的控制台中执行后,页面会产生什么变动[].forEach.call($$("*"), function (a) { a.style.outline = "1px solid red"});公众号【明天也要写bug】更多前端面试题答案及解析1// 答案:2 1 3// 考查 es6 模块化// import 命令是在编译阶段执行的// 并且 import 具备晋升成果,会晋升到整个模块的头部// 所以模块合并后相当于:console.log(2);export const sum = (a, b) => a + b;console.log(1);console.log(sum(1, 2));// 因而最终输入 2 1 3// 源代码// index.jsconsole.log(1);import { sum } from "./sum.js";console.log(sum(1, 2));//sum.jsconsole.log(2);export const sum = (a, b) => a + b;2// 答案:20 20 20 40// ES6 能够为函数参数指定默认值const value = { number: 10 };const multiply = (x = { ...value }) => { console.log((x.number *= 2));};multiply(); // 未传参,应用默认值,x={ number: 10 },此对象不是 value,而是一个新对象,输入 20multiply(); // 同上,x={ number: 10 },也是一个新对象,输入 20multiply(value); // 传了参数,x=value,输入 20,并且扭转了 value.numbermultiply(value); // x=value,输入 40,并且扭转了 value.number3// 答案:页面中的所有元素会被增加红色轮廓// $$() 函数是浏览器提供的命令行 API,相当于 document.querySelectorAll()// $$('*') 会抉择页面中的所有元素,失去一个数组[].forEach.call($$("*"), function (a) { a.style.outline = "1px solid red";});// call() 办法应用一个指定的 this 值和独自给出的一个或多个参数来调用一个函数。// 这里 this 是元素数组,参数是一个函数 function(a){...}// 数组的 forEach 办法接管一个回调函数即此处的 function(a) {...}// 等价于:[所有元素].forEach(function (a) { a.style.outline = "1px solid red";});

September 20, 2022 · 1 min · jiezi

关于javascript:14个你必须知道的JavaScript函数

1、确定任意对象的具体类型家喻户晓,JavaScript 中有六种原始数据类型(Boolean、Number、String、Null、Undefined、Symbol)和一个对象数据类型。然而你晓得对象数据类型能够细分为很多种子类型吗?一个对象可能是数组、函数、map等,如果咱们要获取对象的具体类型,应该怎么做呢?代码:function toRawType (value) {  let _toString = Object.prototype.toString;  let str = _toString.call(value)  return str.slice(8, -1)}解释ECMAScript 有以下规定:对于不同的对象,调用 Object.prototype.toString() 时会返回不同的后果。而且,Object.prototype.toString() 的返回值总是‘[object’+‘tag’+‘]’的格局。如果咱们只想要两头的标签,咱们能够通过正则表达式或者String.prototype.slice()删除两边的字符。例子:toRawType(null) // "Null"toRawType(/sdfsd/) //"RegExp"2、缓存函数计算结果如果有这样的性能:function computed(str) {    // Suppose the calculation in the funtion is very time consuming    console.log('2000s have passed')    return 'a result'}咱们要缓存函数操作的后果, 稍后调用时,如果参数雷同,则不再执行该函数,而是间接返回缓存中的后果。咱们能做什么?代码:function cached(fn){  // Create an object to store the results returned after each function execution.  const cache = Object.create(null);  // Returns the wrapped function  return function cachedFn (str) {    // If the cache is not hit, the function will be executed    if ( !cache[str] ) {        let result = fn(str);        // Store the result of the function execution in the cache        cache[str] = result;    }    return cache[str]  }}例子:3、实现Array.prototype.map这是 JavaScript 中一个有用的内置办法,你应该可能本人实现此性能。代码:const selfMap = function (fn, context) {    let arr = Array.prototype.slice.call(this)    let mappedArr = Array()    for (let i = 0; i < arr.length; i++) {        if (!arr.hasOwnProperty(i)) continue;        mappedArr[i] = fn.call(context, arr[i], i, this)    }    return mappedArr}Array.prototype.selfMap = selfMap;例子:4、实现Array.prototype.filter这是 JavaScript 中一个有用的内置办法,你应该可能本人实现此性能。代码:const selfFilter = function (fn, context) {    let arr = Array.prototype.slice.call(this)    let filteredArr = []    for (let i = 0; i < arr.length; i++) {        if(!arr.hasOwnProperty(i)) continue;         fn.call(context, arr[i], i, this) && filteredArr.push(arr[i])    }    return filteredArr}Array.prototype.selfFilter = selfFilter;例子:5、实现 Array.prototype.some这是 JavaScript 中一个有用的内置办法,你应该可能本人实现此性能。代码:const selfSome = function (fn, context) {    let arr = Array.prototype.slice.call(this)    if(!arr.length) return false    for (let i = 0; i < arr.length; i++) {        if(!arr.hasOwnProperty(i)) continue;        let res = fn.call(context,arr[i],i,this)        if(res)return true    }    return false}Array.prototype.selfSome = selfSome;例子:6、实现 Array.prototype.reduce这是 JavaScript 中一个有用的内置办法,你应该可能本人实现此性能。代码:const selfReduce = function (fn, initialValue) {    let arr = Array.prototype.slice.call(this)    let res    let startIndex    if (initialValue === undefined) {        for (let i = 0; i < arr.length; i++) {            if (!arr.hasOwnProperty(i)) continue            startIndex = i            res = arr[i]            break        }    } else {        res = initialValue    }    for (let i = ++startIndex || 0; i < arr.length; i++) {        if (!arr.hasOwnProperty(i)) continue        res = fn.call(null, res, arr[i], i, this)    }    return res}Array.prototype.selfReduce = selfReduce;例子:7、实现 Array.prototype.flat代码:const selfFlat = function (depth = 1) {    let arr = Array.prototype.slice.call(this)    if (depth === 0) return arr    return arr.reduce((pre, cur) => {        if (Array.isArray(cur)) {            return [...pre, ...selfFlat.call(cur, depth - 1)]        } else {            return [...pre, cur]        }    }, [])}Array.prototype.selfFlat = selfFlat;例子:8、柯里化柯里化是一种将具备多个参数的函数评估为具备单个参数的函数序列的技术。换句话说,当一个函数不是一次承受所有参数时,而是承受第一个参数并返回一个新函数,该函数承受第二个参数并返回一个新函数,该函数承受第三个参数,依此类推,直到所有参数都已履行。那就是咱们将函数调用 add(1,2,3) 转换为 add(1)(2)(3) 。通过应用这种技术,能够轻松地配置和重用小块。为什么有用?柯里化能够帮忙您防止一次又一次地传递雷同的变量。它有助于创立高阶函数,它对事件处理十分有帮忙。小部件能够轻松配置和重用。让咱们看一个简略的增加函数。它承受三个操作数作为参数,并返回所有三个操作数的总和作为后果。function add(a,b,c){ return a + b + c;}你能够用太少(后果奇怪)或太多(多余的参数被疏忽)来调用它。add(1,2,3) --> 6 add(1,2) --> NaNadd(1,2,3,4) --> 6 //Extra parameters will be ignored.如何将现有函数转换为 curried 版本?代码:function curry(fn) {    if (fn.length <= 1) return fn;    const generator = (...args) => {        if (fn.length === args.length) {            return fn(...args)        } else {            return (...args2) => {                return generator(...args, ...args2)            }        }    }    return generator}例子:9、去抖动去抖动只不过是缩小不必要的耗时计算,以进步浏览器性能。在某些状况下,某些性能须要更多工夫来执行某个操作。例如,以电子商务网站上的搜寻栏为例。假如用户想要取得“Tutorix 学习套件”。他在搜寻栏中键入产品的每个字符。输出每个字符后,从浏览器到服务器都会进行一次 Api 调用,以获取所需的产品。因为他想要“Tutorix 学习套件”,用户必须从浏览器到服务器进行 17 次 Api 调用。设想一个场景,当数百万人进行雷同的搜寻从而调用数十亿个 Api 时。所以一次调用数十亿个 Api 必定会导致浏览器性能变慢。为了缩小这个毛病,去抖动呈现了。在这种状况下,去抖动将在两次击键之间设置一个工夫距离,假如为 2 秒。如果两次击键之间的工夫超过 2 秒,则只会进行 Api 调用。在这 2 秒内,用户能够输出至多一些字符,从而缩小 Api 调用的这些字符。因为 Api 调用缩小,浏览器性能将进步。必须留神,每次击键都会更新 Debouncing 性能。代码:const debounce = (func, time = 17, options = {    leading: true,    context: null}) => {    let timer;    const _debounce = function (...args) {        if (timer) {            clearTimeout(timer)        }        if (options.leading && !timer) {            timer = setTimeout(null, time)            func.apply(options.context, args)        }else{            timer = setTimeout(() => {                func.apply(options.context, args)                timer = null            }, time)        }    };    _debounce.cancel = function () {        clearTimeout(timer)        timer = null    };    return _debounce};10、 节流节流将以这样一种形式更改函数,即它能够在一个工夫距离内最多触发一次。例如,无论用户单击按钮多少次,限度将在 1000 毫秒内仅执行一次该性能。代码:const throttle = (func, time = 17, options = {    leading: true,    trailing: false,    context: null}) => {    let previous = new Date(0).getTime()    let timer;    const _throttle = function (...args) {        let now = new Date().getTime();        if (!options.leading) {            if (timer) return            timer = setTimeout(() => {                timer = null                func.apply(options.context, args)            }, time)        } else if (now - previous > time) {            func.apply(options.context, args)            previous = now        } else if (options.trailing) {            clearTimeout(timer)            timer = setTimeout(() => {                func.apply(options.context, args)            }, time)        }    };    _throttle.cancel = () => {        previous = 0;        clearTimeout(timer);        timer = null    };    return _throttle};11、 提早加载图片提早加载图片意味着在网站上异步加载图片——也就是说,在首屏内容齐全加载之后,甚至有条件地,只有当它们呈现在浏览器的视口中时。这意味着如果用户不始终向下滚动,则搁置在页面底部的图像甚至不会被加载。代码:// getBoundingClientRectlet imgList1 = [...document.querySelectorAll(".get_bounding_rect")]let num = imgList1.lengthlet lazyLoad1 = (function () {    let count = 0    return function () {        let deleteIndexList = []        imgList1.forEach((img,index) => {            let rect = img.getBoundingClientRect()            if (rect.top < window.innerHeight) {                img.src = img.dataset.src                // Add picture to delete list after loading successfully                deleteIndexList.push(index)                count++                if (count === num) {                    //When all pictures are loaded, unbind scroll event                    document.removeEventListener('scroll',lazyLoad1)                }            }        })        // Delete loaded pictures        imgList1 = imgList1.filter((_,index)=>!deleteIndexList.includes(index))    }})()12、数组随机无序咱们常常须要打乱一个数组。代码:// Randomly select one of all elements after the current element to exchange with the current elementfunction shuffle(arr) {    for (let i = 0; i < arr.length; i++) {        let randomIndex = i + Math.floor(Math.random()  (arr.length - i));        [arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]]    }    return arr}// Generate a new array, randomly take an element from the original array and put it into the new arrayfunction shuffle2(arr) {    let _arr = []    while (arr.length) {        let randomIndex = Math.floor(Math.random()  (arr.length))        _arr.push(arr.splice(randomIndex, 1)[0])    }    return _arr}例子:13、单例模式单例模式将特定对象的实例数限度为一个,这个繁多实例称为单例模式。单例在须要从单个核心地位协调系统范畴的操作的状况下很有用。一个例子是数据库连接池。池治理整个应用程序的所有数据库连贯的创立、销毁和生命周期,确保没有连贯“失落”。单例缩小了对全局变量的需要,这在 JavaScript 中尤为重要,因为它限度了命名空间净化和相干的名称抵触危险。代码:function proxy(func) {    let instance;    let handler = {        construct(target, args) {            if (!instance) {                // Create an instance if there is not exist                instance = Reflect.construct(func,args)            }            return instance        }    }    return new Proxy(func, handler)}// examplefunction Person(name, age) {    this.name = name    this.age = age}const SingletonPerson = proxy(Person)let person1 = new SingletonPerson('zhl', 22)let person2 = new SingletonPerson('cyw', 22)console.log(person1 === person2) // true例子:14、实现 JSON.stringify这是 JavaScript 中一个有用的内置办法,你应该可能本人实现此性能。代码:const isString = value => typeof value === 'string';const isSymbol = value => typeof value === 'symbol'const isUndefined = value => typeof value === 'undefined'const isDate = obj => Object.prototype.toString.call(obj) === '[object Date]'const isFunction = obj => Object.prototype.toString.call(obj) === '[object Function]';const isComplexDataType = value => (typeof value === 'object' || typeof value === 'function') && value !== null;const isValidBasicDataType = value => value !== undefined && !isSymbol(value); const isValidObj = obj => Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Object]';const isInfinity = value => value === Infinity || value === -Infinity// Symbol,undefined,function in array will become null// Infinity,NaN will also become nullconst processSpecialValueInArray = value =>    isSymbol(value) || isFunction(value) || isUndefined(value) || isInfinity(value) || isNaN(value) ? null : value;// Handling property values according to JSON specificationconst processValue = value => {    if (isInfinity(value) || isNaN(value)) {        return null    }    if (isString(value)) {        return "${value}"    }    return value};// obj.loop = objconst jsonStringify = (function () {    // Closure + WeakMap prevent circular references    let wp = new WeakMap();    //It is the function in the closure that recursively calls jsonstrify, not the jsonstrify function declared by const    return function jsonStringify(obj) {        if (wp.get(obj)) throw new TypeError('Converting circular structure to JSON');        let res = "";        if (isComplexDataType(obj)) {            if (obj.toJSON) return obj.toJSON;             if (!isValidObj(obj)) {                 return            }            wp.set(obj, obj);            if (Array.isArray(obj)) {                res += "[";                let temp = [];                obj.forEach((value) => {                    temp.push(                        isComplexDataType(value) && !isFunction(value) ?                            jsonStringify(value) :                            ${processSpecialValueInArray(value, true)}                    )                });                res += ${temp.join(',')}]            } else {                res += "{";                let temp = [];                Object.keys(obj).forEach((key) => {                    if (isComplexDataType(obj[key])) {                        if (isValidObj(obj[key])) {                            temp.push("${key}":${jsonStringify(obj[key])})                        } else if (isDate(obj[key])) {                             temp.push("${key}":"${obj[key].toISOString()}")                        } else if (!isFunction(obj[key])) {                             temp.push("${key}":{})                        }                    } else if (isValidBasicDataType(obj[key])) {                        temp.push("${key}":${processValue(obj[key])})                    }                });                res += ${temp.join(',')}}            }        } else if (isSymbol(obj)) {             return        } else {            return obj        }        return res    }})();// examplelet s = Symbol('s')let obj = {    str: "123",    arr: [1, {e: 1}, s, () => {    }, undefined,Infinity,NaN],    obj: {a: 1},    Infinity: -Infinity,    nan: NaN,    undef: undefined,    symbol: s,    date: new Date(),    reg: /123/g,    func: () => {    },    dom: document.querySelector('body'),};console.log(jsonStringify(obj));console.log(JSON.stringify(obj));例子:总结以上就是我与你分享的14个JavaScript的函数,这些函数也是咱们作为一名web前端开发人员必须要晓得的,心愿对你有用,如果感觉对你有帮忙的话,请记得点赞我,关注我,并将它分享给你身边做开发的敌人,兴许可能帮忙到他。

September 20, 2022 · 1 min · jiezi

关于javascript:面试官请使用JS实现一个优先队列

首先吐槽先最近面试真的好难!前端面试源码局部和算法局部问的越来越多。 在上个月的四次面试中对于优先队列这种数据结构被问到了两回;还好之前看过局部React源码的scheduler局部对小顶堆有一些了解,不置可否的说出一部分,当初简略讲讲堆这种数据结构,以及用JS如何实现; 前端与优先队列如果你看过React源码的Scheduler局部,你应该会对timerQueue延时队列与taskQueue可执行队列有所印象,他们均是采纳小顶堆这种优先队列数据结构来实现的具体可看 《重学React之为什么须要Scheduler》,在Scheduler局部这两个队列次要是做到了调度后的工作优先级排序(工夫维度); 优先队列与堆优先队列顾名思义就是一个队列,队列有一个准则就是从头部出队从尾部入队;而优先队列每次出队入队都是最大(大顶堆)或者最小值(小顶堆),因而优先队列实际上也是一个堆。而堆是一种近似齐全二叉树的数据结构,堆能够看作是一个数组,堆其实就是利用齐全二叉树的构造来保护的一维数组,依据排序形式不同能够分为大顶堆与小顶堆, 大顶堆:每个节点的值大于或等于其左右孩子节点的值小顶堆:每个节点的值小于或等于其左右孩子节点的值 如果将上图堆中数组数据映射到数组中则是这样子的 //大顶堆[50,45,40,20,25,35,30,10,15]//小顶堆[10,20,15,25,50,30,40,35,45]因而咱们依据以上堆的节点值与数组中的下标咱们能够得出以下两个公式 大顶堆: arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]  小顶堆: arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] 如何创立一个堆?如果当初咱们有一个无序的纯数字的数组,咱们将如何对它进行堆排序呢?假如咱们当初有一个无序数组`[3, 7, 16, 10, 21, 23]`咱们须要对他进行堆排序(大顶堆)那么咱们须要怎么做呢? 咱们须要从最初一个分叶子节点开始从下往上进行调整; Q:如何查找最初一个分叶子节点? A:因为咱们用一维数组来存储堆里的数据,所以咱们能够取数组的长度+1/2取整数-1,假如咱们的数组名为array,则能够套用公式 最初一个分页子节点 = (array.length+1)%2 - 1 **比拟以后节点的值和左子树节点的值,如果以后节点小于左子树的值,就替换以后节点和左子树;替换完后要查看左子树是否满足大顶堆的性质,不满足则从新调整子树结构;** **再比拟以后节点的值和右子树节点的值,如果以后节点小于右子树的值,就替换以后节点和右子树;替换完后要查看右子树是否满足大顶堆的性质,不满足则从新调整子树结构;** 无需替换调整的时候,则大顶堆构建实现 图片与内容摘自图解大顶堆的构建、排序过程  如何用JS创立一个堆?const createHeap = (arr,)=>{ const length = arr.length //如果数组长度为0或者1则不扭转数组间接返回(无需比拟) if (length <= 1) return arr //通过数组下标遍历 for (let i = 1; i < length; i++) { while (i) { // 通过传入的数组下标获取父级节点数组下标并进行比对替换 const parentIndex = Math.floor ((i - 1) / 2) //若以后数组下标对应的索引值大于父级节点索引值对应的值则替换 //如果须要创立的是一个小顶堆则arr[i]<arr[parentIndex] if (arr[i]>arr[parentIndex]) { //利用解构赋值进行值替换 [arr[i], arr[parentIndex]] = [arr[parentIndex], arr[i]] //替换实现将以后i替换成父级下标,缩小比对 i = parentIndex } else { //所有替换实现间接退出以后循环 break } } }}如何向堆中插入数据?以上是JS实现一个堆的过程,那么当初假如如果此时咱们须要向堆中插入一条数据咱们该如何操作? ...

September 20, 2022 · 2 min · jiezi

关于javascript:羊了个羊-客户端暴露后台密钥-可以直接修改后台数据

最近两天羊了个羊忽然大火,我在前晚还是第一次听到这个名词,第二天就看到身边人都在玩这个了。还看到羊了个羊日入几百万,日活千万,赚广告费都赚到手软了之类的微博音讯。 随着羊了个羊的爆火,不晓得有多少人因为过不去第二关而暗自上火,通宵熬夜玩的人预计是不可胜数。作者自己就是,原本是打算睡觉之前打一把助眠游戏而后开开心心睡觉的。后果不小心点开了羊了个羊,卡在第二关怎么都过不去,大动肝火,天都亮了还没过来。 随后我就打算去剖析羊了个羊的关卡机制,通过抓包发现,羊了个羊的代码竟然是裸奔的,齐全没有任何js加密等平安解决。我通过网络资源的搜寻,还发现其余作者发现了羊了个羊某些要害接口和参数的裸露 而后到当初为止,羊了个羊的省排行爆出了惊人的问题,从最开始大家都只有几千只羊,到当初所有榜单都是99999只羊。技术人员各展神通,通过各种办法通过舞弊伎俩去刷出厉害的问题。 像呈现羊了个羊这种状况的次要起因是。1.首先官网可能没有想到游戏会这么火,并没有设计反作弊程序。 2.代码在前端开源透明化,只有有一点技术根底的人就能够通过抓包等伎俩去获取js代码。 3.接口加密形式太简略 那么解决办法是什么呢?在游戏整体框架曾经设计好的前提下,如果不不便再退出反作弊程序,那么只能从2、3下手。 应用sojson.v6或者jsjiami对源代码进行一键js加密,让他人即便反编译了你的小程序或小游戏,拿到的js也是一键加密后的js代码,这样他人拿到你的js代码也是无奈剖析的。 当然了,光靠jsjiami是不够的,还要将接口的参数加密一下,双重加密的状况下,他人即便抓包拿到了你的接口也是无奈应用的。

September 20, 2022 · 1 min · jiezi

关于javascript:从useEffect看ReactVue设计理念的不同

大家好,我卡颂。 咱们晓得,React公布Hooks后,带来了业界一波Hooks热。很多框架(比方Vue Composition API、Solid.js)都借鉴了Hooks的模式。 然而,即便这些框架都借鉴了Hooks,但因为框架作者的理念不同,倒退方向也逐步不同。 比方,在Vue Composition API中,对标React useEffect API的是watchEffect,在Vue文档中,有一小段内容介绍他的用法: 而在React beta文档中,介绍useEffect的,则有整整6节内容: 为什么会有这样的区别?让咱们从useEffect看看React、Vue设计理念的不同。 欢送退出人类高质量前端框架群,带飞 Vue与React的差别当Hooks刚问世时,他被看作是类组件的代替计划。文档中介绍Hooks时也是将他与类组件比照。 其中useEffect的执行机会囊括了如下3个生命周期函数: componentDidMountcomponentDidUpdatecomponentWillUnmount 反观借鉴了Hooks的Vue Composition API,则同时提供了watchEffect API与不同场景的生命周期函数。 这里曾经体现出两者设计理念的不同了: React作为Facebook为摸索UI开发最佳实际而生的框架,一贯的做法是 —— 放弃API稳固(比方this.setState从React诞生伊始就始终存在)。 而Vue则借鉴了各种框架中的最佳实际(比方虚构DOM、响应式更新...)。 所以,从易用性上来说,Vue Composition API是肯定优于React Hooks的,比方: Hooks不能在条件语句中申明Hooks必须显式指明依赖并且,这种易用性的差别会随着框架迭代,愈发显著。 useEffect会越来越简单本着放弃API稳固的准则,以后useEffect次要与上述三个生命周期函数相干。 然而,将来会有更多触发机会与useEffect挂钩。 所以,React团队在致力做一件事 —— 淡化useEffect与生命周期的关系,甚至淡化useEffect与组件的关系(因为当谈到组件时,很天然的会想到组件生命周期)。 怎么淡化呢?答案是 —— 在严格模式下,DEV环境会触发屡次useEffect回调。 如果你将useEffect当作componentDidMount/WillUnmount来用,这个个性很可能让你的代码出bug。 React团队之所以这么做,就是想教育开发者 —— useEffect和生命周期没有关系。开发者应该将useEffect看作针对某个数据源的同步过程。 比方,下述聊天室组件,其中的useEffect能够看作是针对聊天室连贯的同步过程: const serverUrl = 'https://localhost:1234';function ChatRoom({ roomId }) { useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => { connection.disconnect(); }; }, [roomId]); // ...}当聊天室组件mount、update、unmount时,对应的同步过程应该进行。 ...

September 20, 2022 · 1 min · jiezi

关于javascript:羊了个羊-客户端暴露后台密钥-可以直接修改后台数据

最近两天羊了个羊忽然大火,我在前晚还是第一次听到这个名词,第二天就看到身边人都在玩这个了。还看到羊了个羊日入几百万,日活千万,赚广告费都赚到手软了之类的微博音讯。 随着羊了个羊的爆火,不晓得有多少人因为过不去第二关而暗自上火,通宵熬夜玩的人预计是不可胜数。作者自己就是,原本是打算睡觉之前打一把助眠游戏而后开开心心睡觉的。后果不小心点开了羊了个羊,卡在第二关怎么都过不去,大动肝火,天都亮了还没过来。 随后我就打算去剖析羊了个羊的关卡机制,通过抓包发现,羊了个羊的代码竟然是裸奔的,齐全没有任何js加密等平安解决。我通过网络资源的搜寻,还发现其余作者发现了羊了个羊某些要害接口和参数的裸露 而后到当初为止,羊了个羊的省排行爆出了惊人的问题,从最开始大家都只有几千只羊,到当初所有榜单都是99999只羊。技术人员各展神通,通过各种办法通过舞弊伎俩去刷出厉害的问题。 像呈现羊了个羊这种状况的次要起因是。1.首先官网可能没有想到游戏会这么火,并没有设计反作弊程序。 2.代码在前端开源透明化,只有有一点技术根底的人就能够通过抓包等伎俩去获取js代码。 3.接口加密形式太简略 那么解决办法是什么呢?在游戏整体框架曾经设计好的前提下,如果不不便再退出反作弊程序,那么只能从2、3下手。 应用sojson.v6或者jsjiami对源代码进行一键js加密,让他人即便反编译了你的小程序或小游戏,拿到的js也是一键加密后的js代码,这样他人拿到你的js代码也是无奈剖析的。 当然了,光靠jsjiami是不够的,还要将接口的参数加密一下,双重加密的状况下,他人即便抓包拿到了你的接口也是无奈应用的。

September 20, 2022 · 1 min · jiezi

关于javascript:webrtc-websocket-完成简单的-1-V1-文字视频通话

先奉上目前实现的成果演示 客户端技术reactantdesign 组件库socket.iopeer.js webrtc 库实现性能登录搜寻用户增加好友承受好友增加回绝好友增加删除好友1 对 1 文字聊天1 对 1 视频聊天客户端代码地址https://github.com/Onedayago/... 服务端代码地址https://github.com/Onedayago/...

September 20, 2022 · 1 min · jiezi

关于javascript:Day-93100-如何判断某个对象是否包含某个属性

(一)需要想判断某个对象,是否蕴含属性值。 (二)思路1、能够遍历对象的所有属性,循环判断 2、能够间接写obj[key] 3、应用Object.hasOwn办法 (三)Democonst object1 = { prop: 'exists'};console.log(Object.hasOwn(object1, 'prop'));// expected output: trueconsole.log(Object.hasOwn(object1, 'toString'));// expected output: falseconsole.log(Object.hasOwn(object1, 'undeclaredPropertyValue'));// expected output: false

September 19, 2022 · 1 min · jiezi

关于javascript:50天用vue3完成了50个web项目我学到了什么

通过本文的50个web示例你将学到: Vue3外围根底语法和进阶语法less外围根底语法和进阶语法scss外围根底语法和进阶语法1.Expanding Cards成果如图所示: 源码在线示例学到了什么?JavascriptVue ref办法定义根本响应式变量。如:const currentIndex = ref(0);ref办法当然也能够定义一个对象,然而通常定义对象应该应用reactive办法。 Vue v-for指令渲染列表。如:v-for="(item,index) in imageItems" v-for指令渲染时最好指定key属性,不便虚构DOM Diff算法比对。 Vue 动静绑定class与style。如::class="index === currentIndex ? 'active' : ''":style="{ backgroundImage:`url(${ imageURL + item })`}":class和:style代表设置动静类名和动静行内款式,其中:为v-bind的简写,值能够是一个javascript表达式,如三元表达式,或者是对象,又或者是数组。 Vue 事件绑定。如:@click="currentIndex = index"vue事件能够简写为@ + 事件名,值为一个javascript表达式或者是一个函数。 less定义公共款式.base-flex { display: flex; justify-content: center; align-items: center;}//应用形式.app { .base-flex;}嵌套语法.app { //...这里写外围款式 .ec-panel { //...这里写外围款式 }}less定义变量是@ + 变量名,如: @width: 100px;&该符号示意对父选择器的一个援用,例如: .ec-panel { //...外围款式 &.active { //...外围款式 }}其中&.active其实就是.ec-panel.active的写法。 2. Progress Steps成果如图所示: 源码在线示例学到了什么?Javascript通过defineProps定义props,如: const props = defineProps({ width:{ type:Number, default:350 }, progressWidth:{ type:Number, default:0 }})通过computed办法定义计算属性: ...

September 19, 2022 · 9 min · jiezi

关于javascript:web3-DApp-开发指南

前置常识对以太坊的基本概念有初步意识把握 react 相干常识理解 typescript 语法理解 ethers.js 库理解 web3js 库理解 web3-react 库为什么是 React 不是 Vue ?区块链畛域在 react 外面有一个很优良的库叫 web3-react,还有一个很酷的连贯钱包的react连贯UI的库叫 web3modal,连贯的过程不须要咱们操作。这个两个库都曾经在最大的交易网站下面应用了,除了这些优良的库,因为 react 的生态在国外自身就是就倒退得比其余框架更加蓬勃,所以导致所有出名的区块链行业代码都是应用 react web3js ehthers web3-react 区别与分割基本概念web3jsWeb3 是一个用于与以太坊区块链以及运行以太坊虚拟机的其余区块链进行通信的库,包含Avalanche,Binance Smart chain和Solana。 web3.js 有一个主类,称为 web3。在该类中能够找到该库的大多数性能。组成 web3js 的另外 5 个模块别离是: web3-eth : 使 web3.js 的用户能够与以太坊区块链进行交互,比方: web3.eth.getBalance 的作用是取得指定区块的某个地址的以太坊余额web3.eth.signTransaction 的作用是对交易签名web3.eth.sendSignedTransaction 的作用是将签名的交易发送到以太坊区块链。web3-shh : 使你能够与 Whisper 协定进行交互。Whisper 是一个音讯传输协定,其目标是轻松播送音讯以及进行低层异步通信。web3-bzz : 使你能够与 Swarm 交互。Swarm 是一个去中心化存储平台和内容散发服务,它能够用来为去中心化利用存储图片或视频等文件。web3-net : 使你能够与以太坊节点的网络属性进行交互。 web3.*.net.getID 返回网络 IDweb3.*.net.getPeerCount 返回连贯到节点的对等点数web3-utils :提供实用程序函数,这些函数可在以太坊去中心化利用以及其余 web3.js 模块中应用。实用程序函数能够重复使用,使代码编写更轻松,在 JavaScript 和其余编程语言中很常见。Web3-utils 蕴含实用程序函数,这些函数用于转换数字、验证值是否满足特定条件以及搜寻数据集。 web3.utils.toWei 将以太转换为 Weiweb3.utils.hexToNumberString 将十六进制值转换为字符串web3.utils.isAddress 校验特定字符串是否为无效的以太坊地址web3-reactweb3-react 是风行的库 Web3 的一个很好的 React 实现 ...

September 18, 2022 · 6 min · jiezi

关于javascript:SAP-UI5-SimpleForm-在-size-XL-下的布局开发

如果表单蕴含单个表单组,请应用标签字段比例为 3:5:4 的单列布局(标签应用 3 个网格列,字段应用 5 个网格列,以及 空列)。 如果将表单放入全屏应用程序中,您还能够应用属性 singleContainerFullSize 将 columnsXL 设置为 3,以 12:12:0 的标签字段比例用单个表单组填充一列(12 个网格列由 标签、字段应用的 12 个网格列和空列应用的 0 个网格列),并将第二列和第三列留空。 例子:Form with single group in a column layout - Size XL - (12:12:0) 如果表单蕴含多个表单组,还能够应用标签字段比例为 4:8:0 的两列布局(标签应用 4 个网格列,字段应用 8 个网格列,0 个网格列 由空列应用)。 如果将表单放入全屏利用中并且蕴含多个表单组,您还能够应用标签字段比例为 12:12:0 的三列布局(标签应用 12 个网格列,12 个网格 字段应用的列,空列应用的 0 个网格列)。 如果您对 XL 屏幕应用三列布局,请不要对 L 和 M 屏幕应用两列布局,因为它会产生大量空白。 在这种状况下,请改用单列布局。 上面是 2 列布局下,造成很多空白区域节约的例子: ...

September 18, 2022 · 1 min · jiezi

关于javascript:SAP-UI5-SimpleForm-M-和-L-型表单的-label-和-input-分配讲解

本文介绍 SAP UI5 Responsive Grid Layout 布局原理。 默认状况下,表单和简略表单的大小 M 在响应式网格布局中也具备单列布局。 然而,在大小为 M 的状况下,标签与相应的输出字段或值位于同一行,并且表单组位于彼此下方。 默认状况下,标签字段比例为 2:10:0: 标签应用响应式网格布局的 2 个网格列。字段应用响应式网格布局的 10 个网格列。响应式网格布局的 0 列被空列应用。请依据您的利用须要更改默认的 2:10:0。 留神,不要把上述的网格列同 columns 的概念混同起来。 看个具体的例子:Form in size M (2:10:0) 上图的例子,label 和 Input 独特占据 form layout 整个 column. 而如前所述,M 类型是 single-column layout. size L默认状况下,大小 L 的表单和简略表单在响应式网格布局中应用两列布局。 这意味着表单组彼此相邻搁置,以便在一个屏幕上显示所有信息并防止滚动。 在这些列中,标签与相应的输出字段或值位于同一行。 因而表单组采纳 Z 布局(按行而不是按列读取方向)。 标签字段比例默认为 4:8:0: 标签应用响应式网格布局的 4 个网格列。字段应用响应式网格布局的 8 个网格列。响应式网格布局的 0 个网格列被空列应用。例子:Form in size L (4:8:0) sap.ui.core.CSSSize:示意 CSS 大小值的字符串类型。 ...

September 18, 2022 · 1 min · jiezi

关于javascript:SAP-UI5-Form-和-Simple-Form-的设计规范

SAP UI5 Form 表单用于向用户出现数据,并容许用户以结构化的形式输出数据。 表单充当其余 UI 元素(例如标签、输出字段、复选框和滑块)的容器,同时将这些元素构建为特定的布局。 在 SAPUI5 中,能够应用两种不同的控件来构建表单: 表单 – sap.ui.layout.form.Form简略表单 – sap.ui.layout.form.SimpleForm应用表单,开发人员能够轻松地安排属性列表和输出字段。 表单被结构成表单容器(Form Containers)。 每个表单容器都由表单元素(Form elements)组成。 每个表单元素由一个标签(Label)和一个输出字段(Input)组成,配对。 简略的表单控件使开发人员能够实现与表单控件雷同的后果,但形式更简略。 在一个简略的表单中,一个表单控件连同它的表单容器和表单元素一起被创立: 布局和构造由输出的内容定义。 表单容器和表单元素是依据内容类型主动创立的。一个题目(sap.ui.core.Title)主动开始一个新的表单组(也就是表单容器),一个标签(sap.m.Label)主动开始一个新行(也就是表单元素)。此标签前面的所有其余控件都将调配给它的行(也就是表单元素)。 有三种类型的 Form 编辑形式: 仅显示:数据仅显示为标签值字段对,没有可编辑字段。例子: 可编辑:数据以标签输出字段对的模式出现,因而用户能够输出数据。例子: 混合:有些字段是可编辑的,有些则不是。表单和简略表单的可编辑属性仅更改垂直对齐到字段(可编辑=真)或文本(可编辑=假)的标签高度。 应用表单和简略表单,它不会在可编辑和只读模式之间切换整个表单,从而将字段更改为文本,反之亦然。

September 17, 2022 · 1 min · jiezi

关于javascript:SAP-UI5-Simple-Form-控件的使用方法介绍试读版

一套适宜 SAP UI5 初学者循序渐进的学习教程本专栏打算的文章数在 300 篇左右,到 2022年9月16日为止,目前曾经更新了 131 篇,专栏完成度为 43.6%作者简介Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后退出 SAP 成都研究院工作至今。Jerry 是 SAP 社区导师,SAP 中国技术大使。在长达 15 年的 SAP 规范产品开发生涯里,Jerry 已经先后参加 SAP Business ByDesign, SAP CRM, SAP Cloud for Customer, SAP S/4HANA, SAP Commerce Cloud(电商云)等规范产品的研发工作。 Jerry 工作中应用 ABAP, Java, JavaScript 和 TypeScript 进行开发, 对包含 SAP UI5 在内的多款 SAP 自研框架有深刻的钻研。 教程目录SAP UI5 本地开发环境的搭建SAP UI5 利用开发教程之一:Hello WorldSAP UI5 利用开发教程之二:SAP UI5 的疏导过程 BootstrapSAP UI5 利用开发教程之三:开始接触第一个 SAP UI5 控件SAP UI5 利用开发教程之四:XML 视图初探SAP UI5 利用开发教程之五:视图控制器初探SAP UI5 利用开发教程之六 - 理解 SAP UI5 的模块(Module)概念SAP UI5 利用开发教程之七 - JSON 模型初探SAP UI5 利用开发教程之八 - 多语言的反对SAP UI5 利用开发教程之九 - 创立第一个 ComponentSAP UI5 利用开发教程之十 - 什么是 SAP UI5 利用的描述符 DescriptorSAP UI5 利用开发教程之十一 :SAP UI5 容器类控件 Page 和 PanelSAP UI5 利用开发教程之十二 - 应用 CSS 类对 UI 进行进一步丑化SAP UI5 利用开发教程之十三 - 如何增加自定义 CSS 类SAP UI5 利用开发教程之十四 - 嵌入视图的应用形式SAP UI5 利用开发教程之十五 - 对话框和 Fragments 的应用形式SAP UI5 利用开发教程之十六 - 图标 icon 的应用SAP UI5 利用开发教程之十七 - 聚合绑定在 UI5 复合控件中的应用SAP UI5 利用开发教程之十八 - SAP UI5 数据绑定语法里的特殊符号,以及相对绑定和绝对绑定概念详解SAP UI5 利用开发教程之十九 - SAP UI5 数据类型和简单的数据绑定SAP UI5 利用开发教程之二十 - SAP UI5 的表达式绑定用法解说SAP UI5 利用开发教程之二十一 - SAP UI5 的自定义格局器 Custom FormatterSAP UI5 利用开发教程之二十二 - 过滤器 filter 的开发和应用SAP UI5 利用开发教程之二十三 - 列表控件的排序 Sort 和分组 GroupSAP UI5 利用开发教程之二十四 - 如何应用 OData 数据模型SAP UI5 利用开发教程之二十五 - 应用自开发的代理服务器解决 SAP UI5 利用拜访远端 OData 服务的跨域问题SAP UI5 利用开发教程之二十六 - OData 服务配合 Mock 服务器的应用步骤详解SAP UI5 利用开发教程之二十七 - SAP UI5 利用的单元测试工具 QUnit 介绍SAP UI5 利用开发教程之二十八 - SAP UI5 利用的集成测试工具 OPA 介绍SAP UI5 利用开发教程之二十九 - SAP UI5 的路由和导航性能介绍SAP UI5 利用开发教程之三十 - SAP UI5 的路由过程中进行参数传递SAP UI5 利用开发教程之三十一 - SAP UI5 的路由历史和路由回退(Routing back and history)SAP UI5 利用开发教程之三十二 - 如何创立一个自定义 SAP UI5 控件SAP UI5 利用开发教程之三十三 - SAP UI5 利用的响应式布局个性(Responsiveness)SAP UI5 利用开发教程之三十四 - SAP UI5 利用基于设施类型的页面适配性能(Device Adaptation)SAP UI5 利用开发教程之三十五 - 如何把本地开发的 SAP UI5 利用部署到 ABAP 服务器上SAP UI5 利用开发教程之三十六 - 应用 Chrome 开发者工具 Elements 标签动静批改 CSS 类SAP UI5 利用开发教程之三十七 - 应用 Chrome 开发者工具 Console 面板进行元素审查SAP UI5 利用开发教程之三十八 - 应用 Chrome 开发者工具查看程序执行出错时的上下文信息SAP UI5 利用开发教程之三十九 - SAP UI5 利用呈现白屏的一些常见谬误和分析方法分享SAP UI5 利用开发教程之四十 - 如何制作蕴含了 component-preload.js 在内的 SAP UI5 公布版本SAP UI5 利用开发教程之四十一 - Chrome 扩大 UI5 Inspector 的离线装置和应用办法SAP UI5 利用开发教程之四十二 - SAP UI5 自带的 Diagnostics 诊断工具应用办法介绍SAP UI5 利用开发教程之四十三 - SAP UI5 自带的 Support Assistant 工具应用办法介绍SAP UI5 利用开发教程之四十四 - Label 和 Input 控件文本没有程度对齐的起因剖析和解决方案SAP UI5 利用开发教程之四十五 - 如何在 SAP UI5 利用里应用 jQuery 和原生的 DOM APISAP UI5 利用开发教程之四十六 - 应用 Message Manager 实现开箱即用的验证(Validation)信息抛出SAP UI5 利用开发教程之四十七 - 如何自定义 SAP UI5 字符串类型输出字段的校验逻辑SAP UI5 利用开发教程之四十八 - 如何在 SAP UI5 利用里开发条形码扫描性能SAP UI5 利用开发教程之四十九 - 如何在桌面电脑端调试运行在手机上的 SAP UI5 利用SAP UI5 利用开发教程之五十 - 如何应用 Cordova 将 SAP UI5 利用生成一个能在 Android 手机上安装的混合利用SAP UI5 利用开发教程之五十一 - 如何应用 Chrome 调试运行在手机上的 SAP UI5 Cordova 混合利用SAP UI5 利用开发教程之五十二 - 如何应用 SAP UI5 的规范控件联合 Cordova 插件调用手机摄像头进行条形码扫描SAP UI5 利用开发教程之五十三 - 如何自定义 SAP UI5 数据类型(Data Type)SAP UI5 利用开发教程之五十四 - 如何将本地 SAP UI5 利用配置到本地 Fiori Launchpad 中SAP UI5 利用开发教程之五十五 - 如何将本地 SAP UI5 利用通过 Node.js Express 部署到公网上SAP UI5 利用开发教程之五十六 - SAP UI5 树控件(tree)的开发SAP UI5 利用开发教程之五十七 - 基于 OData 注解的 Smart Field 应用办法学习SAP UI5 利用开发教程之五十八 - 应用工厂办法在运行时动态创建不同类型的列表行我的项目控件SAP UI5 利用开发教程之五十九 - 如何在 SAP UI5 利用里显示世界地图SAP UI5 利用开发教程之六十 - SAP UI5 地图控件的一些高级用法SAP UI5 利用开发教程之六十一 - 在 SAP UI5 利用里绘制甘特图 Gantt ChartSAP UI5 利用开发教程之六十二 - 基于 OData V4 的 SAP UI5 表格控件应用办法介绍SAP UI5 利用开发教程之六十三 - 基于 OData V4 的本地 Mock Server 实现的深刻介绍SAP UI5 利用开发教程之六十四 - 基于 OData V4 的 SAP UI5 表格控件如何实现 filter(过滤) 和 sort(排序)性能SAP UI5 利用开发教程之六十五 - 基于 OData V4 的 SAP UI5 表格控件如何实现创立,编辑和保留性能SAP UI5 利用开发教程之六十六 - 基于 OData V4 的 SAP UI5 表格控件如何实现删除性能SAP UI5 利用开发教程之六十七 - 基于 OData V4 的 SAP UI5 List-Detail(列表-明细)布局的实现形式SAP UI5 利用开发教程之六十八 - 如何实现 SAP UI5 路由失败时显示自定义的 NOT Found 页面SAP UI5 利用开发教程之六十九 - 如何从 SAP UI5 Not Found 页面跳转回到失常的利用页面SAP UI5 利用开发教程之七十 - 如何应用按钮控件触发页面路由跳转SAP UI5 利用开发教程之七十一 - SAP UI5 页面的嵌套路由SAP UI5 利用开发教程之七十二 - SAP UI5 页面路由的动画成果设置SAP UI5 利用开发教程之七十三 - 应用自定义 Query 实现 SAP UI5 页面路由的书签性能SAP UI5 利用开发教程之七十四 - SAP UI5 利用应用 OData V4 显示 Table 表格数据的一个陷阱SAP UI5 利用开发教程之七十五 - 如何采纳SAP UI5 主从表格的联动技术显示简单表格内容SAP UI5 利用开发教程之七十六 - 如何实现 SAP UI5 的 Lazy Loading(提早加载,懒加载)SAP UI5 利用开发教程之七十七 - SAP UI5 动静页面路由的高级用法:路由记录 routes 和 target 的一对多关系SAP UI5 利用开发教程之七十八 - 如何通过 url 放弃 SAP UI5 搜寻的状态,让其反对书签性能SAP UI5 利用开发教程之七十九 - 采纳测试驱动开发理念(Test Driven Development)进行 SAP UI5 利用的性能开发(一)SAP UI5 利用开发教程之八十 - 采纳测试驱动开发理念(Test Driven Development)进行 SAP UI5 利用的性能开发(二)SAP UI5 利用开发教程之八十一 - 采纳 OPA5 进行 SAP UI5 集成测试(Integration Test)的一个例子SAP UI5 利用开发教程之八十二 - 采纳 OPA5 开发反对页面跳转的 SAP UI5 集成测试用例SAP UI5 利用开发教程之八十三 - SAP UI5 的自动化测试套件页面的开发步骤介绍SAP UI5 利用开发教程之八十四 - 如何指定 SAP UI5 应用程序基于某个特定的版本运行SAP UI5 利用开发教程之八十五 - 如何用 OPA5 编写测试用例来测试用户输出文本的性能SAP UI5 利用开发教程之八十六 - 入手开发一个最简略的本地 Mock 数据服务器SAP UI5 利用开发教程之八十七 - 如何让 SAP UI5 Mock 服务器反对自定义 url 参数SAP UI5 利用开发教程之八十八 - SAP UI5 Mock 服务器如何实现自定义 Function ImportSAP UI5 利用开发教程之八十九 - 如何给 SAP UI5 列表控件削减多个图形界面的过滤器SAP UI5 利用开发教程之九十 - 基于 OData V2 的 SAP UI5 List-Detail(列表-明细)布局的实现形式SAP UI5 利用开发教程之九十一 - 如何应用客户端 JSON 模型构建一个 Master-Detail-Detail 布局中的列表页面SAP UI5 利用开发教程之九十二 - 基于 SAP UI5 JSONModel 客户端模型的列表分页显示(Table Pagination)前提SAP UI5 利用开发教程之九十三 - 基于 JSONModel 数据模型的列表控件显示数据的深刻探讨SAP UI5 利用开发教程之九十四 - 基于 JSONModel 数据模型的 SAP UI5 列表控件分页显示数据的残缺解决方案SAP UI5 利用开发教程之九十五 - SAP UI5 下拉菜单(Select) 控件的应用形式SAP UI5 利用开发教程之九十六 - SAP UI5 列表控件分页显示数据时,如何自定义分页大小SAP UI5 利用开发教程之九十七 - 如何应用客户端 JSON 模型构建一个 Master-Detail-Detail 布局中的明细页面SAP UI5 利用开发教程之九十八 - 从 viewId 这个属性谈起,聊聊 SAP UI5 的 HTML 源代码生成机制SAP UI5 利用开发教程之九十九 - 深入探讨 SAP UI5 本地开发环境里的 package.json 和 ui5.yamlSAP UI5 利用开发教程之一百 - 如何批改 SAP UI5 框架的源代码实现,以及应用本地部署的 SAP UI5 SDKSAP UI5 利用开发教程之一百零一 - SAP UI5 利用的 Locale 决定机制SAP UI5 利用开发教程之一百零二 - SAP UI5 利用的打印(Print)性能实现详解SAP UI5 利用开发教程之一百零三 - 如何在 SAP UI5 利用中生产第三方库SAP UI5 利用开发教程之一百零四 - SAP UI5 表格控件的反对复选(Multi-Select)以及如何用代码一次选中多个表格行我的项目SAP UI5 利用开发教程之一百零五 - SAP UI5 Master-Detail 布局模式的联动成果实现明细介绍SAP UI5 利用开发教程之一百零六 - 如何进步 SAP UI5 利用路由 url 的可读性SAP UI5 利用开发教程之一百零七 - SAP UI5 OverflowToolbar 容器控件以及 resize 事件处理的一些细节介绍SAP UI5 利用开发教程之一百零八 - SAP UI5 图片显示控件 Avatar 的应用形式介绍SAP UI5 利用开发教程之一百零九 - 应用 SAP UI5 FileUploader 控件上传本地文件SAP UI5 利用开发教程之一百一十 - SAP UI5 FileUploader 控件深刻介绍 - 为什么须要一个暗藏的 iframeSAP UI5 利用开发教程之一百一十一 - SAP UI5 FileUploader 控件实现本地文件上传,接管服务器端的响应时遇到跨域拜访谬误SAP UI5 利用开发教程之一百一十二 - 应用自开发的代理服务器解决 SAP UI5 FileUploader 上传文件时遇到的跨域拜访谬误SAP UI5 利用开发教程之一百一十三 - 授人以渔 - 如何自行查问任意 SAP UI5 控件属性的文档和技术实现细节SAP UI5 利用开发教程之一百一十四 - 如何通过单步调试的形式找到引起 Fiori Launchpad 路由谬误的起因SAP UI5 利用开发教程之一百一十五 - 对于将本地 SAP UI5 利用配置到本地 Fiori Launchpad 的技术实现深刻解说SAP UI5 利用开发教程之一百一十六 - 在 SAPGUI 里应用 ABAP 报表上传 SAP UI5 利用到 ABAP 服务器SAP UI5 利用开发教程之一百一十七 - 本地开发好的 SAP UI5 利用部署到 ABAP 服务器时,中文字符变成乱码的起因剖析和解决方案SAP UI5 利用开发教程之一百一十八 - 如何剖析因为 SAP UI5 版本差别带来的问题SAP UI5 利用开发教程之一百一十九 - 对于 SAP UI5 Container 控件 aggregation 的深入分析SAP UI5 利用开发教程之一百二十 - 如何依据 SAP UI5 框架代码抛出的谬误音讯,反查出是哪一行代码引起的谬误音讯SAP UI5 利用开发教程之一百二十一 - 一键部署开箱即用的代理服务器,解决 SAP UI5 利用开发过程中拜访远端 OData 服务的跨域问题SAP UI5 利用开发教程之一百二十二 - 在 SAP UI5 利用中应用浏览器原生的 Fetch API 发动网络申请SAP UI5 利用开发教程之一百二十三 - 应用 Busy Dialog 动画阻止 SAP UI5 利用按钮短时间内疾速被点击SAP UI5 利用开发教程之一百二十四 - 应用函数节流思维防止 SAP UI5 利用里按钮短时间内被高频反复点击SAP UI5 利用开发教程之一百二十五 - SAP UI5 进阶 - XML 视图里定义的 UI 控件,运行时实例化的技术细节分析SAP UI5 利用开发教程之一百二十六 - SAP UI5 进阶 - JSON 模型字段里的值,显示在最终 UI5 界面上的神秘剖析SAP UI5 利用开发教程之一百二十七 - SAP UI5 利用的全局配置(Global Configuration) 的设计和应用SAP UI5 利用开发教程之一百二十八 - SAP UI5 智能控件 Smart Controls 的初步意识SAP UI5 利用开发教程之一百二十九 - 如何给 SAP UI5 SmartField 增加 Value Help 性能SAP UI5 利用开发教程之一百三十 - 如何使 SAP UI5 SmartField 在运行时渲染成超链接的模式并反对跳转SAP UI5 利用开发教程之一百三十一 - SAP UI5 Cross Application Navigation (跨利用间跳转)的本地模仿实现SAP UI5 利用开发教程之一百三十二 - 正在写作中......阐明Jerry 从 2014 年退出 SAP成都研究院 CRM Fiori 开发团队之后开始接触 SAP UI5,已经在 SAP 社区和“汪子熙”微信公众号上发表过多篇对于 SAP UI5 工作原理和源码解析的文章。 ...

September 17, 2022 · 6 min · jiezi

关于javascript:浅谈-SAP-UI5-OData-模型构造函数的输入参数

咱们能够在 SAP UI5 利用里应用如下的代码来创立一个 OData 模型实例: this.oVocabularyModel = new ODataModel("/sap/opu/odata/SAP/vocabulary_srv/");这里传入一个 OData 服务的 url 作为 ODataModel 构造函数的输出参数。 ODataModel 的依赖,通过如下代码引入:sap/ui/model/odata/v2/ODataModel 这个构造函数的参数如下: new sap.ui.model.odata.v2.ODataModel(vServiceUrl, mParameters?)vServiceUrl:用于申请数据的服务的根本 URI; 此处附加的其余 URL 参数将附加到每个申请中。 如果传递一个对象,它将被解释为参数对象(第二个参数)。 那么 mParameters.serviceUrl 就变成了强制参数。mParameters:可选参数,是一个键值对。能够蕴含下列属性:(1) annotation:应从中加载正文元数据的 URL(或 URL 数组) (2) bindableResponseHeaders:设置此数组以通过实体的 __metadata/headers 属性使自定义响应标头可绑定 (3) canonicalRequests: 模型是否尝试计算标准 URL 以申请数据。 例如: 应用程序以具备相对绑定门路 /SalesOrderSet("1") 的表单显示销售订单的详细信息。该表单为具备绝对绑定门路 ToLineItems 的销售订单行我的项目嵌入了一个表。如果用户抉择了一个销售订单行我的项目(例如我的项目“10”),则该销售订单行我的项目的详细信息以另一种模式显示,该表单还蕴含一个销售订单行我的项目计划表,其中蕴含绝对绑定门路 ToSchedules。 如果 canonicalRequests 参数的默认值为 false,则 OData 模型将通过以下申请申请销售订单行我的项目的详细信息表单的数据: GET /<serviceUrl>/SalesOrderSet("1")/ToLineItems(SalesOrderID="1",ItemPosition="10")GET /<serviceUrl>/SalesOrderSet("1")/ToLineItems(SalesOrderID="1",ItemPosition="10")/ToSchedules一些后端实现不反对资源 URL 中的多个导航属性。在这种状况下,请将 canonicalRequests 参数设置为 true。而后,OData 模型将长资源 URL 转换为标准 URL,并应用以下申请申请销售订单行我的项目的详细信息表单的数据: ...

September 17, 2022 · 1 min · jiezi

关于javascript:如何在-Spartacus-使用-UserAccountFacade-在语言设置更改后重新读取用户数据

问题1:如何在 Spartacus 应用 UserAccountFacade 在语言设置更改后从新读取用户数据 能够扩大上图这个 Observable. 而后应用 combineLatest 和其余的 Observable 进行组合。 问题2:应用 outlet 时遇到谬误音讯:Type before is not assignable to type OutletPosition 解决方案: add outletPosition = OutletPosition; to the component, HTML 里增加代码: [cxOutletPos]="outletPosition.BEFORE"还须要查看: did you add the outlets to the app component html?例如增加如下代码到 Component HTML: <outlets></outlets>问题2:HTTP 400 和 404对于 product 明细页面来说,轻易输出一个不存在的 url,返回值为 HTTP 400: https://cloudapp.azure.com:9002/occ/v2/electronics-spa/cms/pages?pageType=CategoryPage&code=5781122&lang=en&curr=USD 谬误音讯: { "errors" : [ { "message" : "The value provided is not allowed.", "reason" : "invalid", "subject" : "code", "subjectType" : "parameter", "type" : "ValidationError" } ]}如果是 content page 申请不存在: ...

September 17, 2022 · 1 min · jiezi

关于javascript:SAP-Spartacus-和-CDC-集成的-HTTP-请求明细

首先一个 account login 申请: url:https://accounts.eu1.gigya.co... 间接拜访的话,会报谬误音讯:短少 API Key: 每刷新一次浏览器,callId 会变动一次。 response: token 申请的负载: 胜利获得 Access Token: HTTP post: 申请的 payload: 胜利返回的数据: Spartacus 和 CDC 的集成配置步骤通过在店面应用程序的根目录中运行以下命令来装置 SAP Customer Data Cloud 集成库: ng add @spartacus/cdc 当您运行此命令时,Angular Schematics 会为 CDC 集成创立一个模块,其中包含所有必须的导入和配置。 留神:要应用原理图装置 CDC 集成库,您的应用程序构造须要匹配 Spartacus 参考应用程序构造。 或者,您能够手动创立模块并将其导入您的应用程序,如以下示例所示: import { NgModule } from '@angular/core';import { CdcConfig, CdcRootModule, CDC_FEATURE } from '@spartacus/cdc/root';import { provideConfig } from '@spartacus/core';@NgModule({ declarations: [], imports: [CdcRootModule], providers: [ provideConfig({ featureModules: { [CDC_FEATURE]: { module: () => import('@spartacus/cdc').then((m) => m.CdcModule), }, }, }), provideConfig(<CdcConfig>{ cdc: [ { baseSite: 'electronics-spa', javascriptUrl: '<paste-link-to-cdc-script>', sessionExpiration: 3600, }, ], }), ],})export class CdcFeatureModule {}调整新建模块中的CDC配置,如下例所示: ...

September 17, 2022 · 1 min · jiezi

关于javascript:关于用户-email-邮件地址是否允许有加号的问题

在电子邮件地址中应用加号 (+) 十分有用。Gmail 以及两个常见的邮件服务器零碎 sendmail 和 CommuniGate Pro 将发送地址为“user+tag@mumble.dom”的邮件,就如同它的地址是“user@mumble.dom”一样。 而后,电子邮件地址的“+标签”局部可用于归档邮件和筛选邮件。 许多须要电子邮件地址能力注册的网站都存在一个独特的设计缺点,比方最近笔者在 CNet 的 download.com 网站上遇到了这个谬误:因为某种原因,当我尝试注册蕴含 + 的电子邮件地址时,这个网站不承受我的注册申请。 + 是电子邮件地址中齐全无效的字符; 正如 1982 年公布的互联网消息传递规范所定义的 RFC 822(第 8 页和第 9 页). 我通常应用用户名+站点名称+yyyy-mm-dd@domain.com 模式的电子邮件地址在网站上注册,如果我收到未经请求的电子邮件到此地址,不仅能够轻松 跟踪垃圾邮件发送者从哪里取得我的地址,同时也阻止该地址以供未来发送电子邮件。 一个更理论的例子: 一位数学传授 Xavier Yates Zanzibar 博士(又名 xyz123)传授数学,专业课 id 为 20 和数学 497D. 在他的数学 20 网页上,他的电子邮件地址为 xyz123+math20@psu.edu,在他的数学 497D 教学大纲中,他的电子邮件地址为 xyz123+math497d@psu.edu. 当他与共事就 Journal of Cool Math 进行交换时,他的地址是 xyz123+coolmath@psu.edu. 最初,他的家人晓得给他发送电子邮件至 xyz123+personal@psu.edu. 所有这些都会发送到他的 xyz123 电子邮件收件箱,但它们的地址都不同。 Spartacus 应用邮件地址作为用户名登录的办法: loginWithCredentials, userId 为用户邮件地址。 登录 Commerce Cloud Backoffice 后盾,能够查看到胜利创立的用户: ...

September 17, 2022 · 1 min · jiezi

关于javascript:30秒无脑速通羊了个羊

最近几天羊了个羊小游戏大火,纷纷登上热搜,让不明所以的吃瓜大众也都参加起来了。 卷福昨天刚玩,第一关乱点都过了,玩到第二关的时候,看到难度飙升,玩了半天也没过,明天搞搞事件换种形式过关。 1.筹备工作Windows电脑上装置微信桌面版2.开搞第一步:微信桌面版上关上 羊了个羊 小程序,登录,失常玩过第一关,到第二关不必玩间接退出即可; 第二步:关上微信的设置,找到文件治理,而后点击 关上文件夹 第三步:关上文件夹后,顺次关上门路为 Applet -> a9结尾的文件夹 -> usr -> gaomecaches -> resources,找到一个大小为 2KB的json文件,用记事本关上这个文件 第四步:把文件里原先的内容删除,替换为一段神秘的代码,代码能够在公号卷福同学内回复羊了个羊获取 第五步:微信电脑端上从新关上羊了个羊小程序,关上后第一关没什么变动,等到第二关的时候就会发现怎么和第一关一样简略,无脑点点点,过了四关后,游戏胜利通关了,你也能获取羊皮肤了 留神:如果从新关上小程序有问题或者没有失效,能够把Applet文件夹删掉,或者微信上把小程序移除后,再从新操作一遍 小伙伴们,赶快去试试~~

September 17, 2022 · 1 min · jiezi

关于javascript:如何在JavaScript中使用高阶函数

将另一个函数作为参数的函数,或者定义一个函数作为返回值的函数,被称为高阶函数。JavaScript能够承受高阶函数。这种解决高阶函数的能力以及其余特点,使JavaScript成为非常适合函数式编程的编程语言之一。 JavaScript将函数视为一等公民你兴许据说过,JavaScript函数是一等公民。这意味着,在JavaScript中函数是对象。 它们的类型是Object,它们能够作为一个变量的值被调配,而且它们能够像其余援用变量一样被传递和返回。 一等函数赋予了JavaScript非凡的能力,使咱们可能从高阶函数中获益。 因为函数是对象,且JavaScript是风行的编程语言之一,因而其反对函数式编程的原生办法。 事实上,一等函数是JavaScript的原生办法。我敢打赌你在应用他们的时候甚至都没有想过正在应用函数。 高阶函数接管函数作为参数如果你做过很多JavaScript开发,你可能遇到过应用回调函数的状况。 回调函数是一个在操作完结时执行的函数,一旦所有其余操作实现后便会执行。 通常状况下,咱们把这个函数作为最初的参数传递,在其余参数之后。它通常被定义为内联的匿名函数。回调函数依附的是JavaScript解决高阶函数的能力。 JavaScript是一个单线程语言。这意味着同一时间只有一个操作会被执行。 为了防止操作或零碎的主线程相互阻塞(这将导致死锁),引擎会确保所有操作按程序执行。它们沿着这个单线程排队,直到平安产生另一个代码事务。 将一个函数作为参数传入,并在父函数的其余操作实现后运行该函数的能力,对于反对高阶函数的语言来说是至关重要的。 JavaScript中的回调函数容许异步行为,因而脚本能够在期待后果的同时继续执行其余函数或操作。 在解决可能在不确定的时间段后返回后果的资源时,传递回调函数的能力至关重要。 这种高阶函数模式在网络开发中十分有用。一个脚本能够向服务器发送一个申请,而后须要在响应到来时进行解决,而不须要理解服务器的网络提早或解决工夫。 Node.js常常应用回调函数来无效地利用服务器资源。这种异步办法对于期待用户输出后再执行函数的应用程序来说也很有用。 考虑一下这个简略的JavaScript片段,它为一个按钮增加了一个事件监听器。 document.getElementById("clicker").addEventListener("click", function() {alert("you triggered " + this.id);});这段脚本应用内联匿名函数来显示一个alert。 但它也能够很容易地应用一个独自定义的函数,并将这个命名函数传递给addEventListener办法。 var proveIt = function() {alert("you triggered " + this.id);};document.getElementById("clicker").addEventListener("click", proveIt);咱们这样做不仅仅是展现了高阶函数。咱们使代码更可读,更有弹性,并为不同的工作拆散了性能(监听点击事件与揭示用户)。 代码可重用性咱们的proveIt()函数在结构上独立于它四周的代码,总是返回被触发的元素的id。这种函数设计的办法是函数式编程的外围。 这段代码能够存在于任何你用元素的id显示alert的上下文中,并且能够被任何事件监听器调用。 用一个独自定义和命名的函数取代内联函数的能力为咱们提供了有限可能。 在函数式编程中,咱们试图开发不扭转内部数据的纯函数,并且每次对雷同的输出返回雷同的后果。 当初咱们有了一个根本的工具,能够帮忙咱们开发一个小型的、有针对性的高阶函数库,你能够在任何应用程序中应用。 请留神,咱们把 proveIt 而不是 proveIt() 传递给咱们的 addEventListener 函数。 当你不带括号传递一个函数的名字时,你传递的是函数对象自身。当你用圆括号传递函数时,你是在传递执行该函数的后果。返回函数除了将函数作为参数之外,JavaScript还容许函数将其余函数作为后果返回。 这是说得通的,因为函数是简略的对象。对象(包含函数)能够被定义为一个函数的返回值,就像字符串、数组或其余值。 然而函数作为后果返回是什么意思呢? 函数是合成问题和创立可重用代码片断的一种弱小形式。当咱们将一个函数定义为一个高阶函数的返回值时,它能够作为新函数的模板。 如果你读了太多对于"千禧一代"的文章,感到腻烦。你决定每当呈现"千禧一代"这个词时,你都要用 "蛇人"这个短语来代替它。 你可能是简略地写一个函数,在你传递给它的任何文本上执行该文本替换。 var snakify = function(text) {return text.replace(/millenials/ig, "Snake People");};console.log(snakify("The Millenials are always up to something."));// The Snake People are always up to something.这种写法是无效的,但不够通用。你可能想为其余状况写一个替换函数: ...

September 17, 2022 · 1 min · jiezi

关于javascript:ajax和fetch封装网络请求

fetch 默认不带cookie谬误不会rejectHTTP谬误(例如404 Page Not Found 或 500 Internal Server Error)不会导致Fetch返回的Promise标记为reject;.catch()也不会被执行。想要准确的判断 fetch是否胜利,须要蕴含 promise resolved 的状况,此时再判断 response.ok是不是为 true// 不反对间接设置超时, 能够用promisefunction fetchTimeout(url, init, timeout = 3000) { return new Promise((resolve, reject) => { fetch(url, init) .then(resolve) .catch(reject); setTimeout(reject, timeout);})}// 停止fetchconst controller = new AbortController(); fetch( 'http://domain/service', { method: 'GET', signal: controller.signal }).then(response => response.json()).then(json => console.log(json)).catch(error => console.error('Error:', error));controller.abort(); interface IOptions { url: string; type?: string; data: any; timeout?: number;}function formatUrl(json) { let dataArr = []; json.t = Math.random(); for (let key in json) { dataArr.push(`${key}=${encodeURIComponent(json[key])}`) } return dataArr.join('&');}export function ajax(options: IOptions) { return new Promise((resolve, reject) => { if (!options.url) return; options.type = options.type || 'GET'; options.data = options.data || {}; options.timeout = options.timeout || 10000; let dataToUrlstr = formatUrl(options.data); let timer; // 1.创立 let xhr; if ((window as any).XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } if (options.type.toUpperCase() === 'GET') { // 2.连贯 xhr.open('get', `${options.url}?${dataToUrlstr}`, true); // 3.发送 xhr.send(); } else if (options.type.toUpperCase() === 'POST') { // 2.连贯 xhr.open('post', options.url, true); xhr.setRequestHeader('ContentType', 'application/x-www-form-urlencoded'); // 3.发送 xhr.send(options.data); } // 4.接管 xhr.onreadystatechange = () => { if (xhr.readyState === 4) { clearTimeout(timer); if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) { resolve(xhr.responseText); } else { reject(xhr.status); } } } if (options.timeout) { timer = setTimeout(() => { xhr.abort(); reject('超时'); }, options.timeout) } // xhr.timeout = options.timeout; // xhr.ontimeout = () => { // reject('超时'); // } });}

September 16, 2022 · 2 min · jiezi

关于javascript:实现羊了个羊的小游戏

实现《羊了个羊-动物版》的小游戏这两天火爆全场的《羊了个羊》游戏,置信大家都玩过了,那么在玩这个游戏的同时,我想大家都会好奇这个游戏的实现,本文就带大家应用css,html,js来实现一个动物版的游戏。 首先我用到了2个插件,第一个插件就是flexible.js,这个插件就是对不同设施设置根元素字体大小,也就是一个挪动端的适配计划。 因为这里应用了rem布局,针对挪动端做了自适应,所以这里抉择采纳rem布局计划。 还有一个弹框插件,我很早自行实现的,就是popbox.js,对于这个插件,本文不打算解说实现原理,只解说一下应用原理: ewConfirm({ title: "舒适提醒", //弹框题目 content: "游戏完结,别灰心,你能行的!", //弹框内容 sureText: "从新开始", //确认按钮文本 isClickModal:false, //点击遮罩层是否敞开弹框 sure(context) { context.close(); //点击确认按钮执行的逻辑 },//点击确认的事件回调})引入了这个js之后,会在window对象上绑定一个ewConfirm办法,这个办法传入一个自定义对象,对象的属性有title,content,sureText,cancelText,cancel,sure,isClickModal这几个属性,当然这里没有用到cancel按钮,所以不细讲。 正如正文所说,每个属性代表的意思,这里不做赘述。 而后html代码是这样的: <!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>羊了个羊《动物版》</title> <link rel="stylesheet" href="./style.css"></head><body></body><script src="https://www.eveningwater.com/static/plugin/popbox.min.js"></script><script src="https://www.eveningwater.com/test/demo/flexible.js"></script><script src="./script.js"></script></html>能够看到html代码是什么都没有的,因为外面的DOM元素,咱们都放在js代码外面动静生成了,所以script.js这里的代码是外围,这个后续会讲到,接下来看款式代码,也比较简单。 * { margin: 0; padding: 0; box-sizing: border-box;}body,html { height: 100%; width: 100%; overflow: hidden;}body { background: url('https://www.eveningwater.com/my-web-projects/js/21/img/2.gif') no-repeat center / cover; display: flex; justify-content: center; align-items: center;}.ew-box { position: absolute; width: 8rem; height: 8rem;}.ew-box-item { width: 1.6rem; height: 1.6rem; border-radius: 4px; border: 1px solid #535455; background-position: center; background-size: cover; background-repeat: no-repeat; cursor: pointer; transition: all .4s cubic-bezier(0.075, 0.82, 0.165, 1);}.ew-collection { width: 8rem; height: 2.4rem; display: flex; align-items: center; justify-content: center; padding: 0 1rem; background: url('https://www.eveningwater.com/static/dist/20d6c430c2496590f224.jpg') no-repeat center/cover; position: fixed; margin: auto; overflow: auto; bottom: 10px;}.ew-collection > .ew-box-item { margin-right: 0.3rem;}.ew-left-source,.ew-right-source { width: 2.6rem; height: 1.2rem; position: absolute; top: 0;}.ew-left-source { left: 0;}.ew-right-source { right: 0;}.ew-shadow { box-shadow: 0 0 50px 10px #535455 inset;}首先是通配选择器'*'代表匹配所有的元素,并且设置款式初始化,而后是html和body元素设置宽高为100%,并且暗藏溢出的内容,而后给body元素设置了一个背景图,并且body元素采纳弹性盒子布局,程度垂直居中。 ...

September 16, 2022 · 6 min · jiezi

关于javascript:华为云快成长直播间云会议专场华为员工都在用的高效办公神器

千行百业数字化转型的趋势下,企业线上办公、视频会议的需要逐步增多,企业须要一个高效智慧的云会议平台,为实现数字化办公降本增效。9月5日,在华为云快成长直播间的云会议专场,华为云会议产品经理宁哥向大家举荐了一款“19万+华为员工都在用的高效办公神器”——华为云会议,并现场分享了华为云会议+华为IdeaHubS2系列的弱小之处。华为云会议,用高效链接提供业余服务华为员工及上下游合作伙伴近40万用户,笼罩寰球170个国家,1023个办公点,靠智能会议零碎撑持。现在迈入云会议时代,华为每个月视频会议80万+场,会议晦涩率高达99%,用户满意度从两年前的88%晋升至以后的98%。当初,这种高效的工作形式走出华为,让每一个组织、每一个人都能享有。华为云会议,基于华为近30年的音视频技术,联合华为云会议宝等全系列智能合作终端,为客户提供全场景端云协同视频会议解决方案,满足跨地区、跨企业、跨终端的智能沟通合作需要。协同办公,华为云会议打造智慧全场景在此次华为云会议专场直播上,华为云会议产品经理宁哥重点介绍了华为云会议搭载全新上市的华为IdeaHubS2系列终端后,可助力企业实现多端会议无缝流转、高浊音视频会议、智能高效合作的性能亮点,为企业带来高效的线上会议办公体验。多端会议无缝流转——基于华为鸿蒙技术,手机、电脑上的视频会议能够无缝流转到大屏上;同时,手机变身遥控器,实现对会议大屏的操控,坐在远处就能够遥控大屏。高浊音视频会议——在会议晦涩与清晰度上,华为云会议+IdeaHubS2系列以高清低码、专业级的4K摄像机,让会议画面更实在、天然、长久清晰,并且还反对48K音频和AI降噪,为企业提供沉迷式的会议体验。智能高效合作——在办公合作上,华为云会议+IdeaHubS2系列可实现一步无线投屏和多人近程合作,让企业的会议探讨与近程协同变得更高效。智能优选,华为云会议助力企业数字化落地华为云会议+IdeaHubS2系列,更弱小,更智“会”,为企业提供了更便捷、高效的办公体验,减速了企业倒退的数字化转型。

September 16, 2022 · 1 min · jiezi

关于javascript:分片上传方案

一、index.tsimport Embitter from "../tools/emmitter";import Slice from "./sliceUpload";// 上传状态const statusMap = { fail: 0, // 失败 success: 1, // 胜利 inProcessing: 2, // 进行中 paused: 3, // 暂停 canceled: 4, // 已勾销 wait: 5 // 未开始};interface IConfig { file: File; parallel: number; partSize: number;}class Client extends Embitter { private file: File; private parallel: number; // 分片并行数量 private partSize: number; // 分片大小 private status: number; // 0 失败 1胜利 2进行中 3暂停 4勾销 5未开始 6报错 private partInfo: IPartInfo; private partsArray: Slice[]; // 保护所有分片 private sliceUploadSuccess: Set<number>; // 上传胜利的分片partIndex private sliceUploadRunning: Set<number>; // 上传中的分片partIndex private sliceEvent: Embitter; constructor(config: IConfig) { super(); this.file = config.file; this.parallel = config.parallel || defaultParallel; this.partInfo = { partSize: config.partSize, partNum: Math.ceil(config.file.size / config.partSize), }; this.status = statusMap.wait; // 默认未开始 this.partsArray = []; // 记录胜利的分片上传 this.sliceUploadSuccess = new Set([]); // 记录上传中的分片 this.sliceUploadRunning = new Set([]); // 监听分片上传 this.sliceEvent = new Embitter(); } getConfig() { return { file: this.file, partInfo: this.partInfo, sliceEvent: this.sliceEvent, status: this.status, }; } private startUploadAllSlice() { this.sliceEvent.on("success", (partIndex: number) => { if (!this.sliceUploadSuccess.has(partIndex)) { this.sliceUploadSuccess.add(partIndex); this.sliceUploadRunning.delete(partIndex); const progress = this.sliceUploadSuccess.size / this.partInfo.partNum; this.emmit("progress", progress); if (progress >= 1) { this.endSliceUpload(); } else { this._resumeUpload(); } } }); this.sliceEvent.on("error", (partIndex: number, err: any) => { this.emmit("error", err); this.sliceUploadRunning.delete(partIndex); this.status = statusMap.paused; // 上传出现异常就先暂停上传 this.emmit("pause"); }); const that = this; // 创立分片上传实例 this.partsArray = Array.from( new Array(this.partInfo.partNum), (x, i) => new Slice({ client: that, partIndex: i + 1, }) ); // 开始分片上传 this._resumeUpload(); } /** * 上传文件:开始上传或者复原上传 * @param file * @returns {Promise<void>} */ private async uploadFile(): Promise<void> { if (this.status !== statusMap.inProcessing) { this.status = statusMap.inProcessing; this.emmit("start"); } // 开始上传 this.startUploadAllSlice(); } /** * 开始上传 * @param file * @returns {Promise<void>} */ public async startUpload(): Promise<void> { if (this.status !== statusMap.wait) { console.log("startUpload status error", this.status); this.emmit("error", errorMap.hasStarted); return; } this.uploadFile(); } // 完结分片上传事务 private async endSliceUpload() { if (statusMap.canceled === this.status) { return; } const tagList = []; for (const val of this.partsArray) { tagList.push({ partIndex: val.partIndex, partTag: val.partTag, }); } // 完结分片上传事务 const res = await action.endMultipartUpload({tagList}); if (!res.hasOwnProperty("err")) { this.status = statusMap.success; this.emmit("success", { resourceId: res.resourceId, preResourceId: res.preResourceId, url: res.path, }); } } /** * 暂停上传 * @returns {Promise<void>} */ public async pauseUpload() { // 只有文件正在上传中,才能够暂停 if (this.status !== statusMap.inProcessing) { this.emmit("error", errorMap.noInProcess); return; } this.status = statusMap.paused; this.emmit("pause"); } /** * 分片上传开始 * @returns */ private _resumeUpload() { const todoParts = this.partsArray.filter( (part) => !this.sliceUploadSuccess.has(part.partIndex) && !this.sliceUploadRunning.has(part.partIndex) ); let job; while ( this.sliceUploadRunning.size < this.parallel && ![statusMap.paused, statusMap.canceled].includes(this.status) && (job = todoParts.shift()) ) { this.sliceUploadRunning.add(job.partIndex); job.startUpload(); } } /** * 复原上传 * @returns {Promise<void>} */ public async resumeUpload() { if (this.status !== statusMap.paused) { this.emmit("error", errorMap.noCanResume); return; } this.status = statusMap.inProcessing; this.emmit("start"); this._resumeUpload(); } /** * 破除上传 * @returns {Promise<void>} */ public async abortUpload(): Promise<void> { // 只有文件正在上传中或者上传曾经暂停,才能够勾销上传 if ( this.status !== statusMap.inProcessing && this.status !== statusMap.paused ) { this.emmit("error", errorMap.noCanCancel); return; } const result = await action.abortUpload(); // 勾销上传胜利 if (!result.err) { this.status = statusMap.canceled; this.emmit("abort"); this.emmit("progress", 0); return; } this.emmit("error", result.err); }}export default Client;二、sliceUpload.tsimport { generateMD5 } from "../tools/utils";import action from "../action";import Client from "./index";class Slice { // 以下是独有属性 private sliceFile: Blob; private md5Content: string; private signatureUrl: string; private _status: number; // 0 失败 1胜利 2进行中 3暂停 4勾销 5未开始 6报错 private _partTag: string; // 上传胜利会有标签 private _partIndex: number; private client: Client; // 上传实例 constructor(config: ISliceConfig) { this.client = config.client; this._partIndex = config.partIndex; this._status = statusMap.wait; this._partTag = ""; } get partTag() { return this._partTag; } get status() { return this._status; } get partIndex() { return this._partIndex; } /** * 获取分片签名上传url */ private async getSignatureUrl() { const { file, sliceEvent } = this.client.getConfig(); const res = await action.getMultipartUrl(this._partIndex, { headers: { "FileContent-MD5": this.md5Content, "FileContent-Type": file.type || "application/octet-stream", }, }); if (!res.err) { this.signatureUrl = res.signatureUrl; } else { if (this.getCurrentStatus() === statusMap.canceled) { return; } this._status = statusMap.fail; sliceEvent.emmit("error", this.partIndex, res.err); } } private generateSliceFile() { const { partInfo, file } = this.client.getConfig(); const start = (this._partIndex - 1) * partInfo.partSize; let end = start + partInfo.partSize; if (this._partIndex === partInfo.partNum) { end = file.size; } this.sliceFile = file.slice(start, end); } private isContinueUpload() { const status = this.getCurrentStatus(); return ![statusMap.canceled, statusMap.paused].includes(status); } private getCurrentStatus() { const { status } = this.client.getConfig(); return status; } private async uploadSlice() { const { file, sliceEvent } = this.client.getConfig(); const res = await action.startPartUpload( this.signatureUrl, this.sliceFile, { headers: { "Content-MD5": this.md5Content, "Content-Type": file.type || "application/octet-stream", }, } ); if (!res.err) { this._status = statusMap.success; try { this._partTag = JSON.parse(res.headers.etag); } catch (error) { this._partTag = res.headers.etag; } sliceEvent.emmit("success", this._partIndex); } else { if (this.getCurrentStatus() === statusMap.canceled) { return; } this._status = statusMap.fail; sliceEvent.emmit("error", this._partIndex, res.err); } } // 上传分片入口 async startUpload() { if (this.isContinueUpload() && !this.sliceFile) { this.generateSliceFile(); } if (this.isContinueUpload() && !this.md5Content && this.sliceFile) { this.md5Content = await generateMD5(this.sliceFile); } if (this.isContinueUpload() && !this.signatureUrl && this.md5Content) { await this.getSignatureUrl(); } if (this.isContinueUpload() && this.signatureUrl) { await this.uploadSlice(); } return this._status === statusMap.success; }}export default Slice;三、demo 集成import xyUpload from "./index.ts";const client = new xyUpload({ file, parallel: 3, partSize: 2000000,});client.on("progress", (res) => { console.log("progress", res);});client.on("success", (res) => { resolve(res);});client.on("error", (res) => { reject(res);});client.on("start", () => { console.log("开始了");});// 开始上传client.startUpload();// 暂停上传client.pauseUpload();// 持续上传client.resumeUpload();// 破除上传client.abortUpload();

September 16, 2022 · 4 min · jiezi

关于javascript:详细介绍什么是浏览器指纹

咱们在日常生活中,指纹往往说的都是咱们手指上举世无双的纹路。在古代日常生活中常用于手机、大门、打卡机等设施。 那么什么是浏览器指纹呢?他的作用又是什么?他是为了什么而存在的? 咱们一一道来 背景 最开始浏览器指纹是为了标记每个用户的身份,不便电商企业对用户进行精细化的数据举荐。起初慢慢演化成抓取浏览器的各种信息通过计算失去一个惟一值。 什么是浏览器指纹 浏览器指纹是指js通过获取浏览器的各种信息,例如零碎字体、分辨率、ck、浏览器模式、语言、时区、UA、计算机硬件,一些计算机的综合信息来计算出一个惟一值,这个惟一值就是指纹。浏览器指纹的使用范畴非常宽泛,罕用于危险控制系统,加重公司业务压力与损失。 它的作用又是什么 做跨境电商、经营媒体账号的来说,都须要大量的账号去推广经营,最早的时候社交站风控系统都不太欠缺,大批量的账号在同一台电脑上登录,发文,开店铺做批量操作。后边为了社交站的数据品质等起因,开始利用浏览器指纹来判断账号是否在同一台电脑等,检测到了就将违规批量操作的账号封停。后边绝对应的,为了反抗浏览器指纹,有些公司就退出了指纹浏览器产品,来避免用户电脑的浏览器参数被检测到,从而达到一机多号的目标,升高经营老本。这个是题外话了,后边有机会能够独自写一个文章来讲这个指纹浏览器。 他是为了什么而存在的 浏览器指纹是为了避免那些跨境电商、媒体账号的经营,用一台电脑登录大批量的账号发低质量的文章和店铺。利用浏览器指纹能够判断出哪些账号在同一台电脑登录的,将这些影响平台数据品质的账号一网打尽。 还能够避免爬虫作者抓取网站接口,大批量自动化的去获取平台数据,影响平台稳定性。浏览器指纹在防爬虫作者这方面起到的作用是什么呢?后面有提到,浏览器指纹会获取浏览器的各种环境参数信息,而爬虫作者个别获取到接口后,会利用代码模仿http主动大批量的去申请这个接口。而浏览器指纹会检测浏览器环境,如果爬虫作者将你的加密的js代码一起丢到代码环境中运行的话,浏览器指纹检测到环境不对,就不会去执行正确的代码逻辑,无效的爱护了后端接口数据的平安。 最初举荐一下 加密就用 jsjiami.v6

September 16, 2022 · 1 min · jiezi

关于javascript:详细介绍什么是浏览器指纹

咱们在日常生活中,指纹往往说的都是咱们手指上举世无双的纹路。在古代日常生活中常用于手机、大门、打卡机等设施。 那么什么是浏览器指纹呢?他的作用又是什么?他是为了什么而存在的? 咱们一一道来 背景 最开始浏览器指纹是为了标记每个用户的身份,不便电商企业对用户进行精细化的数据举荐。起初慢慢演化成抓取浏览器的各种信息通过计算失去一个惟一值。 什么是浏览器指纹 浏览器指纹是指js通过获取浏览器的各种信息,例如零碎字体、分辨率、ck、浏览器模式、语言、时区、UA、计算机硬件,一些计算机的综合信息来计算出一个惟一值,这个惟一值就是指纹。浏览器指纹的使用范畴非常宽泛,罕用于危险控制系统,加重公司业务压力与损失。 它的作用又是什么 做跨境电商、经营媒体账号的来说,都须要大量的账号去推广经营,最早的时候社交站风控系统都不太欠缺,大批量的账号在同一台电脑上登录,发文,开店铺做批量操作。后边为了社交站的数据品质等起因,开始利用浏览器指纹来判断账号是否在同一台电脑等,检测到了就将违规批量操作的账号封停。后边绝对应的,为了反抗浏览器指纹,有些公司就退出了指纹浏览器产品,来避免用户电脑的浏览器参数被检测到,从而达到一机多号的目标,升高经营老本。这个是题外话了,后边有机会能够独自写一个文章来讲这个指纹浏览器。 他是为了什么而存在的 浏览器指纹是为了避免那些跨境电商、媒体账号的经营,用一台电脑登录大批量的账号发低质量的文章和店铺。利用浏览器指纹能够判断出哪些账号在同一台电脑登录的,将这些影响平台数据品质的账号一网打尽。 还能够避免爬虫作者抓取网站接口,大批量自动化的去获取平台数据,影响平台稳定性。浏览器指纹在防爬虫作者这方面起到的作用是什么呢?后面有提到,浏览器指纹会获取浏览器的各种环境参数信息,而爬虫作者个别获取到接口后,会利用代码模仿http主动大批量的去申请这个接口。而浏览器指纹会检测浏览器环境,如果爬虫作者将你的加密的js代码一起丢到代码环境中运行的话,浏览器指纹检测到环境不对,就不会去执行正确的代码逻辑,无效的爱护了后端接口数据的平安。 最初举荐一下 js解密就用,简略的间接在线一键解密就行了 jsjiami

September 16, 2022 · 1 min · jiezi

关于javascript:前端面试题JavaScript篇20220916

每日3题1 以下代码执行后,控制台中的输入内容为?// 以下代码执行后,浏览器的控制台中输入的内容是什么var arr = [0, 1, 2];arr[10] = 10;var newArr = arr.filter((x) => x === undefined);console.log(newArr);2 以下代码执行后,控制台中的输入内容为?// 以下代码执行后,控制台中输入的内容是什么const obj = { 2: 3, 3: 4, length: 2, push: Array.prototype.push,};obj.push(1);console.log(obj);3 以下代码执行后,控制台中的输入内容为?// 以下代码执行后,控制台中输入的内容是什么let x;try { throw new Error();} catch (x) { x = 1; console.log(x);}console.log(x);公众号【明天也要写bug】更多前端面试题答案及解析1// 答案:[]// 考查 filter 办法var arr = [0, 1, 2];arr[10] = 10;var newArr = arr.filter((x) => x === undefined);// 传入 filter 办法的函数,只会在曾经赋值的索引上被调用,对于那些曾经被删除或者从未被赋值的索引不会被调用。// 所以最终没有值通过测试console.log(newArr);2// 答案:{ '2': 1, '3': 4, length: 3, push: [Function: push] }// 考查 push 办法// push 办法能够利用在相似数组的对象上// push 办法依据 length 属性来决定从哪里开始插入给定的值const obj = { 2: 3, 3: 4, length: 2, push: Array.prototype.push,};obj.push(1); // obj.length=2,所以 push 插入到索引 2 处,即 obj[2]=1console.log(obj);3// 答案:1 undefined// 考查 catch 和作用域// catch块指定一个标识符(在上面为x),该标识符保留由throw语句指定的值。// catch块是惟一的,因为当输出catch块时,JavaScript 会创立此标识符,并将其增加到以后作用域;// 标识符仅在catch块执行时存在;catch块执行实现后,标识符不再可用。let x;try { throw new Error();} catch (x) { // x 仅在 catch 块中可用 x = 1; console.log(x); // 输入 1}console.log(x); // x 从未赋值,输入 undefined

September 16, 2022 · 1 min · jiezi

关于javascript:浅谈-MessageChannel

什么是 MessageChannelMessageChannel 容许两个不同的脚本运行在同一个文档的不同浏览器上下文(例如两个 iframe,文档主体和一个 iframe,应用 SharedWorker 的两个文档,或两个 worker)来间接通信,在每端应用一个端口(port)通过双向频道(channel)向彼此传递音讯。 MessageChannel 是以DOM Event的模式发送音讯,所以它属于异步的宏工作。根本用法应用 MessageChannel() 构造函数来创立通信信道,获取两个端口 MessagePort 对象 port1 port2;一个端口应用 postMessage发送音讯,另一个端口通过 onmessage 接管音讯;另一个端口通过 onmessage 接管音讯;当端口收到无奈反序列化的音讯时,应用 onmessageerror解决;进行发送音讯时,调用 close 敞开端口;形式一const { port1, port2 } = new MessageChannel();port1.onmessage = (event) => { console.log('收到来自port2的音讯:', event.data);};port1.onmessageerror = (event) => {};port2.onmessage = function (event) { console.log('收到来自port1的音讯:', event.data); port2.postMessage('我是port2');};port2.onmessageerror = (event) => {};port1.postMessage('我是port1');形式二const { port1, port2 } = new MessageChannel();port1.addEventListener('message', event => { console.log('收到来自port2的音讯:', event.data);});port1.addEventListener('messageerror', (event) => { });port1.start();port2.addEventListener('message', event => { console.log('收到来自port1的音讯:', event.data); port2.postMessage('我是port2');});port2.addEventListener('messageerror', (event) => { });port2.start();port1.postMessage('我是port1');以上两种形式,输入均为: ...

September 16, 2022 · 1 min · jiezi

关于javascript:Day-92100-原型链的继承属性

1、JS中的继承当谈到继承时,JavaScript 只有一种构造:对象。每个实例对象(object)都有一个公有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。 该原型对象也有一个本人的原型对象(__proto__),层层向上直到一个对象的原型对象为 null。依据定义,null 没有原型,并作为这个原型链中的最初一个环节。2、继承属性JavaScript 对象是动静的属性“包”(指其本人的属性)。JavaScript 对象有一个指向一个原型对象的链。 当试图拜访一个对象的属性时,它不仅仅在该对象上搜查,还会搜查该对象的原型,以及该对象的原型的原型,顺次层层向上搜寻,直到找到一个名字匹配的属性或达到原型链的开端。3、创立原型链的Demo// 让咱们从一个函数里创立一个对象o,它本身领有属性a和b的:let f = function () { this.a = 1; this.b = 2;}/* 这么写也一样function f() { this.a = 1; this.b = 2;}*/let o = new f(); // {a: 1, b: 2}// 在f函数的原型上定义属性f.prototype.b = 3;f.prototype.c = 4;// 不要在 f 函数的原型上间接定义 f.prototype = {b:3,c:4};这样会间接突破原型链// o.[[Prototype]] 有属性 b 和 c// (其实就是 o.__proto__ 或者 o.constructor.prototype)// o.[[Prototype]].[[Prototype]] 是 Object.prototype.// 最初o.[[Prototype]].[[Prototype]].[[Prototype]]是null// 这就是原型链的开端,即 null,// 依据定义,null 就是没有 [[Prototype]]。// 综上,整个原型链如下:// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> nullconsole.log(o.a); // 1// a是o的本身属性吗?是的,该属性的值为 1console.log(o.b); // 2// b是o的本身属性吗?是的,该属性的值为 2// 原型上也有一个'b'属性,然而它不会被拜访到。// 这种状况被称为"属性遮蔽 (property shadowing)"console.log(o.c); // 4// c是o的本身属性吗?不是,那看看它的原型上有没有// c是o.[[Prototype]]的属性吗?是的,该属性的值为 4console.log(o.d); // undefined// d 是 o 的本身属性吗?不是,那看看它的原型上有没有// d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有// o.[[Prototype]].[[Prototype]] 为 null,进行搜寻// 找不到 d 属性,返回 undefined

September 16, 2022 · 1 min · jiezi

关于javascript:译angular中的ngtemplate-ngcontent-ngcontainer

本文会蕴含作者一些了解,为了不和原作者意思混同,会将集体的了解放在【】里。原文地址 那是我忙于为我的办公我的项目创作新性能的日子之一。忽然间,某些事件引起了我的留神。 上图是angular最终渲染进去的DOM 当我审查DOM时候,我看到这个 ngcontent 被Angular利用到了元素上。如果他们蕴含元素在最终的DOM里,那么<ng-container>是用来干什么的? 那是我很困惑在 <ng-container> 和 <ng-content>中。 在探寻问题答案的时候我发现了<ng-template>和 *ngTemplateOutlet的概念。当初咱们有四个听起来简直雷同的概念。我开始了探寻它们的旅程。 你已经也遇到过这种状况吗?如果是,那么你来对中央了。闲话少说,让咱们一个一个来解说他们。 1. < ng-template >顾名思义,<ng-template> 是一个模板元素,用于Angular与构造指令联合应用(*ngIf, *ngFor, [ngSwitch]和自定义指令) <font color='red'>这些模板元素仅工作在构造指令存在的时候</font>。Angular包装了咱们利用指令的元素。 思考下边的一个*ngIf的例子。 【咱们能够看到,在一个一般元素上增加构造指令,angular在解析时候,其实会帮我买创立一个ng-template元素,并将相干的构造指令放到ng-template上进行解决】 下面展现的是Angular对与*ngIf的解释。 最终的DOM与咱们在本文结尾看到的相似。 应用办法咱们曾经看到了Angular应用<ng-template>的形式。然而咱们如何应用它呢?因为它只和构造指令一起工作,所以咱们能够这样应用:【这种是❌形式,后边会讲到】 此处的 home 设置为 true, 上述代码在DOM中的输入为: 什么都没有被渲染进去!这是为什么呢? 其实,这正是预期的后果。正如咱们曾经探讨过的,Angular会用正文代替ng-template【译文应用的Angular版本为6.1.10。 在Angular12版本,曾经用非凡的className代替正文了】,咱们的代码最终会被解释成如下代码。 咱们的<ng-template>在被Angular包装之后,变成了两个。然而无论怎样,Angular都不对<ng-template>的内容进行选中。 以下是两种<font color=green>正确</font>的应用形式: Method 1在第一种办法中,你提供给Angular一种不须要进一步解决的形式。这样Angular将仅仅转换 <ng-template> 到正文里,并不会扭转其内容。(它们不会再像之前的例子一样被放在任何<ng-template>中)。因而,它将正确的渲染内容。 要想理解更多如何应用此构造和更多的构造指令,请参考这篇文章。 Method2这是一种很少应用的形式(应用两个<ng-template>)。这里咱们在then中给出了一个模板援用,通知他当条件为真时候应该渲染什么。 像这样应用多<ng-template>(你能够应用<ng-container>代替)是不被倡议的因为这不是Angular的本意。<ng-template>该当被应用在多处重复使用的场景下。咱们将在文章前面的局部更具体的探讨。 < ng-container >你是否已经写过或看到过相似这样的代码 咱们大部分人写这样代码的起因在于Angular无奈再单个元素上应用多个构造指令。当初这个代码失常工作,然而如果item.id 为false,它就会在dom中引入很多空的<div> 在简略的例子中可能不须要关怀它,但如果在大型简单的利用中时候(会展现成千上万的数据),它可能变得麻烦,因为有可能会有监听器在这些DOM上。 更蹩脚的是你可能必须去嵌套你的CSS。【大略是想表白这些写会在附加款式时候须要额定的选择器】 不要放心!咱们有<ng-container>能够解决。 <ng-container>是一个组元素,它不会烦扰款式或布局,因为Angular不会将它们渲染到DOM中。 以上代码会渲染出这样的DOM构造 看,咱们解脱了那些空的div。咱们应该应用<ng-container>当咱们仅仅想应用多个构造指令而不想引入多的DOM时候。 3、< ng-content >它用于创立可配置的组件。这意味着组件能够依据用户的志愿来配置。这就是家喻户晓的内容投影~ 思考一个简略的应用了<ng-content>的组件 ...

September 16, 2022 · 1 min · jiezi

关于javascript:js设计模式一面向对象封装

前言最近始终在看typescript,次要的一个目标是为vue3.x做筹备。3.x版本尤雨溪大神采纳typescript重写底层,具体内容能够查看[[译] 尤雨溪:Vue 3.0 打算-掘金](https://juejin.im/post/684490...)。在typescript里,简直齐全采纳ES6语法,其中最为重要的还是class类的应用,学到这块就有点懵逼了。什么?继承还能够这样玩?什么共有公有什么派生类???我之前学了个假js吧??? 于是回头来从新梳理学习一下面对对象编程,这一系列文章全副是基于ES5语法规定,别跟我说为啥不间接用ES6,ES6它最终也是编译成ES5运行。小子只是个前端菜鸟,对编程还没有太深刻的理解,只是个代码搬运工。如果文章有什么谬误或者是了解上的谬误,还请指条明路,感激不尽。 这一系列将以面对对象三个个性封装、继承、多态为题进行解说,更好的了解面对对象编程。 面对过程编程和面对对象编程(OOP)面对过程编程面向过程就是剖析出解决问题所须要的步骤,而后用函数把这些步骤一步一步实现,应用的时候一个一个顺次调用就能够了。 面对对象编程面对对象编程就是将你的需要形象成一个对象,针对这个对象剖析其特色和动作,这个对象咱们称之为类 对象基础知识对象了解程序员常常会拿对象来开玩笑:没对象?本人new一个呗,要啥样都能够。那到底什么是对象呢?js中有一个说法是万物皆对象,对象就是能够领有属性和办法的一个汇合。人,是一个对象,他有吃饭睡觉的属性,有下班赚钱的办法。所有的所有都能够形象为一个对象,只不过每个对象都属于本人的属性和办法。 什么叫面对对象编程???在js中,有两种编程格调。面对过程编程和面对对象编程,咱们写轮播图写动画写页面,大部分都是面对过程编程(反正我集体目前是这样)。 对象三大特色封装、继承、多态 一个对象被创立,这两头产生什么 | new 关键字做了什么(面试题) 1、创立一个新的对象,这个对象的类型是 `object` 2、设置这个新的对象的外部、可拜访性和[[prototype]]属性为构造函数(指prototype.construtor所指向的构造函数)中设置的 3、将步骤1新创建的对象作为this的上下文 4、果该函数没有返回对象,则返回this。原型和原型链原型 JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。咱们能够把所有对象实例须要共享的属性和办法间接定义在 prototype 对象上。这个对象的所有属性和办法,都会被构造函数的所领有。prototype作为对象的外部属性,咱们个别通过实例化对象的__proto__这个属性进行拜访。在原型对象中还有一个属性constructor,这个属性对应创立所有指向该原型的实例的构造函数 原型链 当咱们拜访对象的一个属性或办法时,它会先在对象本身中寻找,如果有则间接应用,如果没有则会去原型对象中寻找,如果找到则间接应用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中仍然没有找到,则返回null。 function Person(name, age) { this.name = name this.age= age this.action = function () { alert('hello word') }}var p = new Person('尤雨溪', 18) // 实例化Person这个对象console.log(p.name) // 尤雨溪/*他们之间的关系 构造函数的原型 == 实例化p.__proto__ 构造函数 == 构造函数原型的constructor*/ console.log(Person.prototype === p.__proto__) // true console.log(Person.prototype.constructor === Person) // trueconsole.log(p.constructor === Person) // true面对对象—封装什么是封装封装就是把客观事物封装成形象的类,暗藏属性和办法的实现细节,仅对外公开接口。也就是说,封装就是将属性和办法组成一个类的过程就称之为封装。对象封装的几种模式对象字面量长处:代码简略易懂毛病:创立多个对象会产生大量的代码,编写麻烦,且并没有实例与原型的概念 ...

September 15, 2022 · 2 min · jiezi

关于javascript:测评几大js加密站的加密质量3

1.简介 公司网站的接口常常被爬虫爬,时不时就导致服务器压力过大,白白耗费公司服务器资源。于是开始接触js加密这块的业务。发现了不少反对js在线加密的站,以及各种加密计划,在这做个笔记,一一列举各大加密站的优缺点。看看哪种才是最平安的html代码加密形式。 2.加密摸索 最开始在网络上搜寻js加密,看到了很多解决方案,例如crypto、base64、MD5、sha1、sha256、unicode编码、AES/DES、RSA都是优良的js加密算法,然而最终我发现,这些加密都是在前端实现的,也就是在用户电脑上实现的,齐全透明化的,所以爬虫作者破解难度也很低,他不须要去摸索你这个算法计算的过程,他只有拿到你雷同的加密算法代码,就能够通过同样的伎俩加密进去,继而盗取接口信息。 3.工具介绍 Sojson反对js的不可逆混同加密,和很多高级的加密配置,还减少了小白专用的一键配置惯例配置,和禁控制台调试输入、A级爱护、变量办法全混同等诸多高级配置,很多细节做的不错。查了一下资格,这家站13年创立的,搞了快有十个年头了,是个老品牌。接下来咱们做个demo加密一下试试,以下加密,除了根本配置,我还勾选了办法函数变量全副重命名。 4.js案例代码(function () { String.prototype.searchAB = function (){ return this.match(/[^A|B]/g); } const str = '本工具由 wwBw.jsjiami.cAom 提供接口。\n专一JS平安畛域近10年\n企业化经营\n业余的JS加密研发团队。'.searchAB().toString().replaceAll(',', ''); alert(str); console.log(str);}());5.通过Sojson加密后/* * 加密工具曾经降级了一个版本,目前为 jsjiami.com.v5 ,次要增强了算法,以及防破解【相对不可逆】配置,耶稣也无奈100%还原,我说的。; * 曾经打算把这个工具根底性能始终收费上来。还心愿反对我。 * 另外 jsjiami.com.v5 曾经强制退出校验,正文能够去掉,然而 jsjiami.com.v5 不能去掉(如果你开明了VIP,能够手动去掉),其余都没有任何绑定。 * 誓死不会退出任何后门,jsjiami.com JS 加密的使命就是为了爱护你们的Javascript 。 * 正告:如果您歹意去掉 jsjiami.com.v5 那么咱们将不会爱护您的JavaScript代码。请遵守规则 * 新版本: https://www.jsjiami.com/ 反对批量加密,反对大文件加密,领有更多加密。 */ ;var encode_version = 'jsjiami.com.v5', aoveg = '__0xeb218', __0xeb218=['54mt5p2G5Yye77+5IS3kv5Llr5zmnLjlvYbnqJ7vvYDovI7or6Xml5Pmj4vmiI7kupHnmqXltbDkv50=','BMKReQ==','wpgkecKkdQ==','RhBiw7bCuw==','woFvacOrDQ==','5p6C5bWn5YSE55WXZXjDhSPDpVdHwp3ChhvDnMO/w73CscOZE8O7BsOB5o2+5Lyx5o2h5Y6R44ORb+S7m+azsSJR5a+K5Yaq6aKB5Z2u6Ly4A8OX5bqkw4PkvJPkurvlj6PovITok7LDsuS7oeS4hOeapSjCluWKq+Wtl+ehlOWPmeWagumZnOOAtg==','e8OtNMOWS8KYw4lRwrw=','E8O/Q0LDpQ==','w7gRwol2wrM=','wqoGwpw0wpnChsKZYg==','bgBaw6LCtMOzwqDDk1XDuQ==','woNyf1nChA==','E3NL','w7UQwow=','wrRoQMKJXR3DjsKKWQ==','TxnCg8KcKjPCoWhEEMOkYsKgJw==','wrI9Gg==','wqrDjcK6','5Yiz6ZuD54ml5p2w5Y6y77+8wqPDq+S8leWsoeacseW9seeokw==','M8OpdGfDgw==','BMKBc8KSGA==','JcODH8KswqI=','w5Ibw6kzAQ==','w5F8QMK0w6s=','wqjDlcKPaW8=','OsKBaMKRwoA='];(function(_0x104565,_0x3c3110){var _0xe5012c=function(_0x311857){while(--_0x311857){_0x104565['push'](_0x104565['shift']());}};_0xe5012c(++_0x3c3110);}(__0xeb218,0x6d));var _0x3f28=function(_0x231fd0,_0x4f680a){_0x231fd0=_0x231fd0-0x0;var _0x5b4826=__0xeb218[_0x231fd0];if(_0x3f28['initialized']===undefined){(function(){var _0x550fbc=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0x18d5c9='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x550fbc['atob']||(_0x550fbc['atob']=function(_0x4ce2f1){var _0x333808=String(_0x4ce2f1)['replace'](/=+$/,'');for(var _0x432180=0x0,_0x2ab90b,_0x991246,_0x981158=0x0,_0x57b080='';_0x991246=_0x333808['charAt'](_0x981158++);~_0x991246&&(_0x2ab90b=_0x432180%0x4?_0x2ab90b*0x40+_0x991246:_0x991246,_0x432180++%0x4)?_0x57b080+=String['fromCharCode'](0xff&_0x2ab90b>>(-0x2*_0x432180&0x6)):0x0){_0x991246=_0x18d5c9['indexOf'](_0x991246);}return _0x57b080;});}());var _0x219af0=function(_0x441e3a,_0x2cc193){var _0x5f41ea=[],_0x503809=0x0,_0xe42b77,_0x56465b='',_0x52cace='';_0x441e3a=atob(_0x441e3a);for(var _0x39753a=0x0,_0xf81284=_0x441e3a['length'];_0x39753a<_0xf81284;_0x39753a++){_0x52cace+='%'+('00'+_0x441e3a['charCodeAt'](_0x39753a)['toString'](0x10))['slice'](-0x2);}_0x441e3a=decodeURIComponent(_0x52cace);for(var _0x307b3e=0x0;_0x307b3e<0x100;_0x307b3e++){_0x5f41ea[_0x307b3e]=_0x307b3e;}for(_0x307b3e=0x0;_0x307b3e<0x100;_0x307b3e++){_0x503809=(_0x503809+_0x5f41ea[_0x307b3e]+_0x2cc193['charCodeAt'](_0x307b3e%_0x2cc193['length']))%0x100;_0xe42b77=_0x5f41ea[_0x307b3e];_0x5f41ea[_0x307b3e]=_0x5f41ea[_0x503809];_0x5f41ea[_0x503809]=_0xe42b77;}_0x307b3e=0x0;_0x503809=0x0;for(var _0x3ab53f=0x0;_0x3ab53f<_0x441e3a['length'];_0x3ab53f++){_0x307b3e=(_0x307b3e+0x1)%0x100;_0x503809=(_0x503809+_0x5f41ea[_0x307b3e])%0x100;_0xe42b77=_0x5f41ea[_0x307b3e];_0x5f41ea[_0x307b3e]=_0x5f41ea[_0x503809];_0x5f41ea[_0x503809]=_0xe42b77;_0x56465b+=String['fromCharCode'](_0x441e3a['charCodeAt'](_0x3ab53f)^_0x5f41ea[(_0x5f41ea[_0x307b3e]+_0x5f41ea[_0x503809])%0x100]);}return _0x56465b;};_0x3f28['rc4']=_0x219af0;_0x3f28['data']={};_0x3f28['initialized']=!![];}var _0xfeb75b=_0x3f28['data'][_0x231fd0];if(_0xfeb75b===undefined){if(_0x3f28['once']===undefined){_0x3f28['once']=!![];}_0x5b4826=_0x3f28['rc4'](_0x5b4826,_0x4f680a);_0x3f28['data'][_0x231fd0]=_0x5b4826;}else{_0x5b4826=_0xfeb75b;}return _0x5b4826;};(function(){var _0x51ca65={'zfcaT':_0x3f28('0x0','utdG'),'yIOxN':function _0x5e1682(_0xc8f5a3,_0x3eeb2a){return _0xc8f5a3(_0x3eeb2a);}};String[_0x3f28('0x1','*4dD')]['searchAB']=function(){return this[_0x3f28('0x2','HY[j')](/[^A|B]/g);};const _0x443d66=_0x51ca65[_0x3f28('0x3','UvGD')]['searchAB']()[_0x3f28('0x4','^1Wj')]()[_0x3f28('0x5','b)dh')](',','');_0x51ca65[_0x3f28('0x6','57Mq')](alert,_0x443d66);console[_0x3f28('0x7','L@A#')](_0x443d66);}());;(function(_0x25294e,_0x4b28ed,_0x23e1ad){var _0x306eb6={'cTziY':_0x3f28('0x8','9b2u'),'MwCFN':function _0x3934fb(_0x58f1e0,_0x47a748){return _0x58f1e0!==_0x47a748;},'ZlecP':_0x3f28('0x9','[H2q'),'vnTmH':_0x3f28('0xa','h4hX'),'vubId':function _0x57d6b5(_0x526c42,_0x2f0ce6){return _0x526c42!==_0x2f0ce6;},'ebTrQ':_0x3f28('0xb','Rusa'),'ZuHxn':'版本号,js会定期弹窗,还请反对咱们的工作','hvkTq':function _0x1feda9(_0x123602,_0x126847){return _0x123602!==_0x126847;},'qZugo':function _0x3bfcab(_0x75fc32,_0x5a0410){return _0x75fc32===_0x5a0410;},'mYCQK':function _0x43657f(_0x12ea6b,_0x482a3c){return _0x12ea6b+_0x482a3c;},'Masgs':function _0x5e166e(_0x37744e,_0x464172){return _0x37744e===_0x464172;},'Zkiry':_0x3f28('0xc','kzwQ'),'ZDrsf':function _0x4670c0(_0x437455,_0x41038e){return _0x437455+_0x41038e;},'pYULy':_0x3f28('0xd','7&K@')};_0x23e1ad='al';try{_0x23e1ad+=_0x306eb6['cTziY'];_0x4b28ed=encode_version;if(!(_0x306eb6[_0x3f28('0xe','HY[j')](typeof _0x4b28ed,_0x306eb6[_0x3f28('0xf','oZC$')])&&_0x4b28ed===_0x306eb6['vnTmH'])){if(_0x306eb6['vubId'](_0x306eb6[_0x3f28('0x10','h&*k')],'nuU')){_0x25294e[_0x23e1ad]('删除'+_0x306eb6[_0x3f28('0x11','$0E%')]);}else{_0x23e1ad+=_0x306eb6[_0x3f28('0x12','NVu)')];_0x4b28ed=encode_version;if(!(_0x306eb6['hvkTq'](typeof _0x4b28ed,_0x306eb6[_0x3f28('0x13','kzwQ')])&&_0x306eb6['qZugo'](_0x4b28ed,'jsjiami.com.v5'))){_0x25294e[_0x23e1ad](_0x306eb6[_0x3f28('0x14','cOs@')]('删除',_0x3f28('0x15','h4hX')));}}}}catch(_0x1a8b3c){if(_0x306eb6['Masgs'](_0x306eb6['Zkiry'],_0x3f28('0x16','cOs@'))){_0x25294e[_0x23e1ad](_0x306eb6[_0x3f28('0x17','ht3S')]('删除',_0x306eb6[_0x3f28('0x18','b)dh')]));}else{_0x25294e[_0x23e1ad](_0x306eb6[_0x3f28('0x19','n4i$')]);}}}(window));;encode_version = 'jsjiami.com.v5';6.格式化一下,把正文清理掉。;var encode_version = 'jsjiami.com.v5', aoveg = '__0xeb218', __0xeb218 = ['54mt5p2G5Yye77+5IS3kv5Llr5zmnLjlvYbnqJ7vvYDovI7or6Xml5Pmj4vmiI7kupHnmqXltbDkv50=', 'BMKReQ==', 'wpgkecKkdQ==', 'RhBiw7bCuw==', 'woFvacOrDQ==', '5p6C5bWn5YSE55WXZXjDhSPDpVdHwp3ChhvDnMO/w73CscOZE8O7BsOB5o2+5Lyx5o2h5Y6R44ORb+S7m+azsSJR5a+K5Yaq6aKB5Z2u6Ly4A8OX5bqkw4PkvJPkurvlj6PovITok7LDsuS7oeS4hOeapSjCluWKq+Wtl+ehlOWPmeWagumZnOOAtg==', 'e8OtNMOWS8KYw4lRwrw=', 'E8O/Q0LDpQ==', 'w7gRwol2wrM=', 'wqoGwpw0wpnChsKZYg==', 'bgBaw6LCtMOzwqDDk1XDuQ==', 'woNyf1nChA==', 'E3NL', 'w7UQwow=', 'wrRoQMKJXR3DjsKKWQ==', 'TxnCg8KcKjPCoWhEEMOkYsKgJw==', 'wrI9Gg==', 'wqrDjcK6', '5Yiz6ZuD54ml5p2w5Y6y77+8wqPDq+S8leWsoeacseW9seeokw==', 'M8OpdGfDgw==', 'BMKBc8KSGA==', 'JcODH8KswqI=', 'w5Ibw6kzAQ==', 'w5F8QMK0w6s=', 'wqjDlcKPaW8=', 'OsKBaMKRwoA='];(function (_0x104565, _0x3c3110) { var _0xe5012c = function (_0x311857) { while (--_0x311857) { _0x104565['push'](_0x104565['shift']()); } }; _0xe5012c(++_0x3c3110);}(__0xeb218, 0x6d));var _0x3f28 = function (_0x231fd0, _0x4f680a) { _0x231fd0 = _0x231fd0 - 0x0; var _0x5b4826 = __0xeb218[_0x231fd0]; if (_0x3f28['initialized'] === undefined) { (function () { var _0x550fbc = typeof window !== 'undefined' ? window : typeof process === 'object' && typeof require === 'function' && typeof global === 'object' ? global : this; var _0x18d5c9 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; _0x550fbc['atob'] || (_0x550fbc['atob'] = function (_0x4ce2f1) { var _0x333808 = String(_0x4ce2f1)['replace'](/=+$/, ''); for (var _0x432180 = 0x0, _0x2ab90b, _0x991246, _0x981158 = 0x0, _0x57b080 = ''; _0x991246 = _0x333808['charAt'](_0x981158++); ~_0x991246 && (_0x2ab90b = _0x432180 % 0x4 ? _0x2ab90b * 0x40 + _0x991246 : _0x991246, _0x432180++ % 0x4) ? _0x57b080 += String['fromCharCode'](0xff & _0x2ab90b >> (-0x2 * _0x432180 & 0x6)) : 0x0) { _0x991246 = _0x18d5c9['indexOf'](_0x991246); } return _0x57b080; }); }()); var _0x219af0 = function (_0x441e3a, _0x2cc193) { var _0x5f41ea = [], _0x503809 = 0x0, _0xe42b77, _0x56465b = '', _0x52cace = ''; _0x441e3a = atob(_0x441e3a); for (var _0x39753a = 0x0, _0xf81284 = _0x441e3a['length']; _0x39753a < _0xf81284; _0x39753a++) { _0x52cace += '%' + ('00' + _0x441e3a['charCodeAt'](_0x39753a)['toString'](0x10))['slice'](-0x2); } _0x441e3a = decodeURIComponent(_0x52cace); for (var _0x307b3e = 0x0; _0x307b3e < 0x100; _0x307b3e++) { _0x5f41ea[_0x307b3e] = _0x307b3e; } for (_0x307b3e = 0x0; _0x307b3e < 0x100; _0x307b3e++) { _0x503809 = (_0x503809 + _0x5f41ea[_0x307b3e] + _0x2cc193['charCodeAt'](_0x307b3e % _0x2cc193['length'])) % 0x100; _0xe42b77 = _0x5f41ea[_0x307b3e]; _0x5f41ea[_0x307b3e] = _0x5f41ea[_0x503809]; _0x5f41ea[_0x503809] = _0xe42b77; } _0x307b3e = 0x0; _0x503809 = 0x0; for (var _0x3ab53f = 0x0; _0x3ab53f < _0x441e3a['length']; _0x3ab53f++) { _0x307b3e = (_0x307b3e + 0x1) % 0x100; _0x503809 = (_0x503809 + _0x5f41ea[_0x307b3e]) % 0x100; _0xe42b77 = _0x5f41ea[_0x307b3e]; _0x5f41ea[_0x307b3e] = _0x5f41ea[_0x503809]; _0x5f41ea[_0x503809] = _0xe42b77; _0x56465b += String['fromCharCode'](_0x441e3a['charCodeAt'](_0x3ab53f) ^ _0x5f41ea[(_0x5f41ea[_0x307b3e] + _0x5f41ea[_0x503809]) % 0x100]); } return _0x56465b; }; _0x3f28['rc4'] = _0x219af0; _0x3f28['data'] = {}; _0x3f28['initialized'] = !![]; } var _0xfeb75b = _0x3f28['data'][_0x231fd0]; if (_0xfeb75b === undefined) { if (_0x3f28['once'] === undefined) { _0x3f28['once'] = !![]; } _0x5b4826 = _0x3f28['rc4'](_0x5b4826, _0x4f680a); _0x3f28['data'][_0x231fd0] = _0x5b4826; } else { _0x5b4826 = _0xfeb75b; } return _0x5b4826;};(function () { var _0x51ca65 = { 'zfcaT': _0x3f28('0x0', 'utdG'), 'yIOxN': function _0x5e1682(_0xc8f5a3, _0x3eeb2a) { return _0xc8f5a3(_0x3eeb2a); } }; String[_0x3f28('0x1', '*4dD')]['searchAB'] = function () { return this[_0x3f28('0x2', 'HY[j')](/[^A|B]/g); }; const _0x443d66 = _0x51ca65[_0x3f28('0x3', 'UvGD')]['searchAB']()[_0x3f28('0x4', '^1Wj')]()[_0x3f28('0x5', 'b)dh')](',', ''); _0x51ca65[_0x3f28('0x6', '57Mq')](alert, _0x443d66); console[_0x3f28('0x7', 'L@A#')](_0x443d66);}());;(function (_0x25294e, _0x4b28ed, _0x23e1ad) { var _0x306eb6 = { 'cTziY': _0x3f28('0x8', '9b2u'), 'MwCFN': function _0x3934fb(_0x58f1e0, _0x47a748) { return _0x58f1e0 !== _0x47a748; }, 'ZlecP': _0x3f28('0x9', '[H2q'), 'vnTmH': _0x3f28('0xa', 'h4hX'), 'vubId': function _0x57d6b5(_0x526c42, _0x2f0ce6) { return _0x526c42 !== _0x2f0ce6; }, 'ebTrQ': _0x3f28('0xb', 'Rusa'), 'ZuHxn': '版本号,js会定期弹窗,还请反对咱们的工作', 'hvkTq': function _0x1feda9(_0x123602, _0x126847) { return _0x123602 !== _0x126847; }, 'qZugo': function _0x3bfcab(_0x75fc32, _0x5a0410) { return _0x75fc32 === _0x5a0410; }, 'mYCQK': function _0x43657f(_0x12ea6b, _0x482a3c) { return _0x12ea6b + _0x482a3c; }, 'Masgs': function _0x5e166e(_0x37744e, _0x464172) { return _0x37744e === _0x464172; }, 'Zkiry': _0x3f28('0xc', 'kzwQ'), 'ZDrsf': function _0x4670c0(_0x437455, _0x41038e) { return _0x437455 + _0x41038e; }, 'pYULy': _0x3f28('0xd', '7&K@') }; _0x23e1ad = 'al'; try { _0x23e1ad += _0x306eb6['cTziY']; _0x4b28ed = encode_version; if (!(_0x306eb6[_0x3f28('0xe', 'HY[j')](typeof _0x4b28ed, _0x306eb6[_0x3f28('0xf', 'oZC$')]) && _0x4b28ed === _0x306eb6['vnTmH'])) { if (_0x306eb6['vubId'](_0x306eb6[_0x3f28('0x10', 'h&*k')], 'nuU')) { _0x25294e[_0x23e1ad]('删除' + _0x306eb6[_0x3f28('0x11', '$0E%')]); } else { _0x23e1ad += _0x306eb6[_0x3f28('0x12', 'NVu)')]; _0x4b28ed = encode_version; if (!(_0x306eb6['hvkTq'](typeof _0x4b28ed, _0x306eb6[_0x3f28('0x13', 'kzwQ')]) && _0x306eb6['qZugo'](_0x4b28ed, 'jsjiami.com.v5'))) { _0x25294e[_0x23e1ad](_0x306eb6[_0x3f28('0x14', 'cOs@')]('删除', _0x3f28('0x15', 'h4hX'))); } } } } catch (_0x1a8b3c) { if (_0x306eb6['Masgs'](_0x306eb6['Zkiry'], _0x3f28('0x16', 'cOs@'))) { _0x25294e[_0x23e1ad](_0x306eb6[_0x3f28('0x17', 'ht3S')]('删除', _0x306eb6[_0x3f28('0x18', 'b)dh')])); } else { _0x25294e[_0x23e1ad](_0x306eb6[_0x3f28('0x19', 'n4i$')]); } }}(window));encode_version = 'jsjiami.com.v5'; 7.加密后剖析 说实话,看到加密后的代码,第一眼人是解体的,没看到啥有用的信息。所有办法和变量都混同了。格式化后咱们从头开始看起。首先是变量__0xeb218,存的是一个数组,和上篇讲到的那个加密一样,然而这里把里边的值都加密过了,初步看格局是进行了一个Base64编码。而后下方第二个办法对上边的数组做了元素地位的调换。而后第二个看起来是个加密函数,因为咱们晓得本人的源码是什么,找到了本人的alert和console代码,还有咱们本人写的一个正则,发现有两处截然不同的。 ...

September 15, 2022 · 4 min · jiezi

关于javascript:纯手工解密几大在线js加密网站3

0x0.结尾 续接上章,灵机一动想挨个破解一下各大js加密的网站,理解一下现有的js加密的逻辑。 0x1.介绍Sojson反对js的不可逆混同加密,和很多高级的加密配置,还减少了小白专用的一键配置惯例配置,和禁控制台调试输入、A级爱护、变量办法全混同等诸多高级配置,很多细节做的不错。查了一下资格,这家站13年创立的,搞了快有十个年头了,是个老品牌。接下来咱们做个demo加密一下试试,以下加密,除了根本配置,我还勾选了办法函数变量全副重命名。 0x2.源代码(function () { String.prototype.searchAB = function (){ return this.match(/[^A|B]/g); } const str = '本工具由 wwBw.jsjiami.cAom 提供接口。\n专一JS平安畛域近10年\n企业化经营\n业余的JS加密研发团队。'.searchAB().toString().replaceAll(',', ''); alert(str); console.log(str);}());0x3.加密后/* * 加密工具曾经降级了一个版本,目前为 jsjiami.com.v5 ,次要增强了算法,以及防破解【相对不可逆】配置,耶稣也无奈100%还原,我说的。; * 曾经打算把这个工具根底性能始终收费上来。还心愿反对我。 * 另外 jsjiami.com.v5 曾经强制退出校验,正文能够去掉,然而 jsjiami.com.v5 不能去掉(如果你开明了VIP,能够手动去掉),其余都没有任何绑定。 * 誓死不会退出任何后门,jsjiami.com JS 加密的使命就是为了爱护你们的Javascript 。 * 正告:如果您歹意去掉 jsjiami.com.v5 那么咱们将不会爱护您的JavaScript代码。请遵守规则 * 新版本: https://www.jsjiami.com/ 反对批量加密,反对大文件加密,领有更多加密。 */;var encode_version = 'jsjiami.com.v5', nayxk = '__0xeb23e', __0xeb23e=['IXYRHEI=','CCYiIcOu','GsK8wowTHQ==','54mM5p2X5YyJ77+CaHbkvbzlrJPmnpDlv6XnqrLvv5rovLHorLvmlbbmj7bmi53kuoHnmoLltobkvpo=','woPDvz0=','5p+W5bWs5Ya+55SSw6LCoggiLEM/woXCr8ONwqHCvcKXacK0Y8KDSTPmjazkv7DmjIDljZjjg7TCjeS4lOayhMKawrflr43lh5npobzlnozovIPDrsKE5bqJw6/kv4/ku4Dlj5zovabok4HDieS5muS4kueblxER5Yim5ayS56OQ5Y2U5ZqX6ZmQ44G+','SgBZNxA=','wpHDhhvDumI=','w6vDsy7CusOJ','wqAJw7VaNMOZwpPCmMO1','w48dwrXCtMOQ','K3jDi8ODw5tMwrfChg==','woTDmQ/DjQQ=','wojDqDTDjFDDocOfwpY=','wpIAMiPDvgptwoQ=','KcO/N1tcSEViwqHCrA==','w4nDgMOr','54qC5p+/5Y+Q77y6WsOY5L2N5ayf5p6w5byq56ms77276L226K6i5paq5oya5oin5LuK55qC5bW95Lyh','5Yuz6ZqH54qh5p2Y5Y6d77+QwpRy5L2s5a6n5p+F5byU56qQ','PCjDoDkawr5gcXDDrMKDwq7ChFE=','wrjDtzLDjxE=','w7J+IcOlwok=','RHkTYC4=','LMKlwo0pBw==','LmBfa8Kh','MDAeOMOq','wp/DmyvDmyU=','cFrCvSDCnQ=='];(function(_0x4fe50f,_0x1873df){var _0x13858f=function(_0x5e0bfd){while(--_0x5e0bfd){_0x4fe50f['push'](_0x4fe50f['shift']());}};_0x13858f(++_0x1873df);}(__0xeb23e,0x1a8));var _0x283e=function(_0x27a5bc,_0x101af3){_0x27a5bc=_0x27a5bc-0x0;var _0x10bb4e=__0xeb23e[_0x27a5bc];if(_0x283e['initialized']===undefined){(function(){var _0x3a7cff=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0x132a83='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x3a7cff['atob']||(_0x3a7cff['atob']=function(_0x1eb12d){var _0x106424=String(_0x1eb12d)['replace'](/=+$/,'');for(var _0x4a2000=0x0,_0x4726be,_0x4b15c7,_0x18229a=0x0,_0xb6f8e4='';_0x4b15c7=_0x106424['charAt'](_0x18229a++);~_0x4b15c7&&(_0x4726be=_0x4a2000%0x4?_0x4726be*0x40+_0x4b15c7:_0x4b15c7,_0x4a2000++%0x4)?_0xb6f8e4+=String['fromCharCode'](0xff&_0x4726be>>(-0x2*_0x4a2000&0x6)):0x0){_0x4b15c7=_0x132a83['indexOf'](_0x4b15c7);}return _0xb6f8e4;});}());var _0x5bdc07=function(_0x334a5b,_0x1635b7){var _0x43421f=[],_0x216485=0x0,_0xa7d60d,_0x5b8f1e='',_0x792d05='';_0x334a5b=atob(_0x334a5b);for(var _0xc451ca=0x0,_0xc846a3=_0x334a5b['length'];_0xc451ca<_0xc846a3;_0xc451ca++){_0x792d05+='%'+('00'+_0x334a5b['charCodeAt'](_0xc451ca)['toString'](0x10))['slice'](-0x2);}_0x334a5b=decodeURIComponent(_0x792d05);for(var _0x430013=0x0;_0x430013<0x100;_0x430013++){_0x43421f[_0x430013]=_0x430013;}for(_0x430013=0x0;_0x430013<0x100;_0x430013++){_0x216485=(_0x216485+_0x43421f[_0x430013]+_0x1635b7['charCodeAt'](_0x430013%_0x1635b7['length']))%0x100;_0xa7d60d=_0x43421f[_0x430013];_0x43421f[_0x430013]=_0x43421f[_0x216485];_0x43421f[_0x216485]=_0xa7d60d;}_0x430013=0x0;_0x216485=0x0;for(var _0x5bff45=0x0;_0x5bff45<_0x334a5b['length'];_0x5bff45++){_0x430013=(_0x430013+0x1)%0x100;_0x216485=(_0x216485+_0x43421f[_0x430013])%0x100;_0xa7d60d=_0x43421f[_0x430013];_0x43421f[_0x430013]=_0x43421f[_0x216485];_0x43421f[_0x216485]=_0xa7d60d;_0x5b8f1e+=String['fromCharCode'](_0x334a5b['charCodeAt'](_0x5bff45)^_0x43421f[(_0x43421f[_0x430013]+_0x43421f[_0x216485])%0x100]);}return _0x5b8f1e;};_0x283e['rc4']=_0x5bdc07;_0x283e['data']={};_0x283e['initialized']=!![];}var _0x52f150=_0x283e['data'][_0x27a5bc];if(_0x52f150===undefined){if(_0x283e['once']===undefined){_0x283e['once']=!![];}_0x10bb4e=_0x283e['rc4'](_0x10bb4e,_0x101af3);_0x283e['data'][_0x27a5bc]=_0x10bb4e;}else{_0x10bb4e=_0x52f150;}return _0x10bb4e;};(function(){var _0x555370={'wNKpT':function _0x5d77c1(_0x50f6c6,_0x50079e){return _0x50f6c6(_0x50079e);}};String['prototype']['searchAB']=function(){var _0x433705={'nczMX':function _0x36f6e4(_0x16f977,_0x13c64e){return _0x16f977===_0x13c64e;},'jKNDQ':_0x283e('0x0','ch)&'),'qfYEY':_0x283e('0x1','b6lp'),'Jjmrt':function _0x2094cd(_0x3a122a,_0xbf7144){return _0x3a122a(_0xbf7144);}};if(_0x433705[_0x283e('0x2','Bv8b')](_0x433705[_0x283e('0x3','ch)&')],_0x433705['jKNDQ'])){return this[_0x283e('0x4','2C5f')](/[^A|B]/g);}else{String[_0x283e('0x5','5npl')]['searchAB']=function(){return this[_0x283e('0x6','o@1r')](/[^A|B]/g);};const _0x2afd9f=_0x433705['qfYEY']['searchAB']()[_0x283e('0x7','b10M')]()['replaceAll'](',','');_0x433705[_0x283e('0x8','cuhX')](alert,_0x2afd9f);console['log'](_0x2afd9f);}};const _0x493c6e='本工具由\x20wwBw.jsjiami.cAom\x20提供接口。\x0a专一JS平安畛域近10年\x0a企业化经营\x0a业余的JS加密研发团队。'[_0x283e('0x9','ch)&')]()[_0x283e('0xa','^Rl*')]()[_0x283e('0xb','FEg@')](',','');_0x555370['wNKpT'](alert,_0x493c6e);console['log'](_0x493c6e);}());;(function(_0x26a8bf,_0x1b3d22,_0x57167a){var _0x1ecaea={'vDPpa':function _0x4bbe24(_0x196798,_0x28ae00){return _0x196798===_0x28ae00;},'wVdMw':_0x283e('0xc','299L'),'HXEbb':'jGZ','YTjTR':'ert','Nhlic':function _0x59eb7e(_0x3ce965,_0x6ad683){return _0x3ce965!==_0x6ad683;},'oVWCQ':'undefined','QhIdU':function _0x3e047a(_0x218201,_0x37678c){return _0x218201+_0x37678c;},'WmmUB':_0x283e('0xd','9%A%'),'PfMev':_0x283e('0xe','eU!)'),'EZyiI':function _0x18d526(_0x187205,_0x1c45b1){return _0x187205===_0x1c45b1;},'NRlie':_0x283e('0xf','PVfY'),'xqmSy':function _0x51338a(_0x1ca5e1,_0x4fcbee){return _0x1ca5e1+_0x4fcbee;}};_0x57167a='al';try{if(_0x1ecaea[_0x283e('0x10','cuhX')](_0x1ecaea['wVdMw'],_0x1ecaea[_0x283e('0x11','ns*5')])){_0x57167a='al';try{_0x57167a+=_0x1ecaea[_0x283e('0x12','#xjn')];_0x1b3d22=encode_version;if(!(_0x1ecaea[_0x283e('0x13','AM@r')](typeof _0x1b3d22,_0x1ecaea[_0x283e('0x14','Ak*G')])&&_0x1ecaea[_0x283e('0x15','k4b2')](_0x1b3d22,'jsjiami.com.v5'))){_0x26a8bf[_0x57167a](_0x1ecaea[_0x283e('0x16','cuhX')]('删除',_0x1ecaea['WmmUB']));}}catch(_0x2c780a){_0x26a8bf[_0x57167a](_0x1ecaea[_0x283e('0x17','UwAd')]);}}else{_0x57167a+='ert';_0x1b3d22=encode_version;if(!(typeof _0x1b3d22!=='undefined'&&_0x1ecaea[_0x283e('0x18','jwV3')](_0x1b3d22,_0x1ecaea[_0x283e('0x19','k4b2')]))){_0x26a8bf[_0x57167a](_0x1ecaea[_0x283e('0x1a','AM@r')]('删除',_0x283e('0x1b','ge&n')));}}}catch(_0x46de5d){_0x26a8bf[_0x57167a]('删除版本号,js会定期弹窗');}}(window));;encode_version = 'jsjiami.com.v5';0x4.格式化一下,去除正文。;var encode_version = 'jsjiami.com.v5', nayxk = '__0xeb23e', __0xeb23e = ['IXYRHEI=', 'CCYiIcOu', 'GsK8wowTHQ==', '54mM5p2X5YyJ77+CaHbkvbzlrJPmnpDlv6XnqrLvv5rovLHorLvmlbbmj7bmi53kuoHnmoLltobkvpo=', 'woPDvz0=', '5p+W5bWs5Ya+55SSw6LCoggiLEM/woXCr8ONwqHCvcKXacK0Y8KDSTPmjazkv7DmjIDljZjjg7TCjeS4lOayhMKawrflr43lh5npobzlnozovIPDrsKE5bqJw6/kv4/ku4Dlj5zovabok4HDieS5muS4kueblxER5Yim5ayS56OQ5Y2U5ZqX6ZmQ44G+', 'SgBZNxA=', 'wpHDhhvDumI=', 'w6vDsy7CusOJ', 'wqAJw7VaNMOZwpPCmMO1', 'w48dwrXCtMOQ', 'K3jDi8ODw5tMwrfChg==', 'woTDmQ/DjQQ=', 'wojDqDTDjFDDocOfwpY=', 'wpIAMiPDvgptwoQ=', 'KcO/N1tcSEViwqHCrA==', 'w4nDgMOr', '54qC5p+/5Y+Q77y6WsOY5L2N5ayf5p6w5byq56ms77276L226K6i5paq5oya5oin5LuK55qC5bW95Lyh', '5Yuz6ZqH54qh5p2Y5Y6d77+QwpRy5L2s5a6n5p+F5byU56qQ', 'PCjDoDkawr5gcXDDrMKDwq7ChFE=', 'wrjDtzLDjxE=', 'w7J+IcOlwok=', 'RHkTYC4=', 'LMKlwo0pBw==', 'LmBfa8Kh', 'MDAeOMOq', 'wp/DmyvDmyU=', 'cFrCvSDCnQ=='];(function (_0x4fe50f, _0x1873df) { var _0x13858f = function (_0x5e0bfd) { while (--_0x5e0bfd) { _0x4fe50f['push'](_0x4fe50f['shift']()); } }; _0x13858f(++_0x1873df);}(__0xeb23e, 0x1a8));var _0x283e = function (_0x27a5bc, _0x101af3) { _0x27a5bc = _0x27a5bc - 0x0; var _0x10bb4e = __0xeb23e[_0x27a5bc]; if (_0x283e['initialized'] === undefined) { (function () { var _0x3a7cff = typeof window !== 'undefined' ? window : typeof process === 'object' && typeof require === 'function' && typeof global === 'object' ? global : this; var _0x132a83 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; _0x3a7cff['atob'] || (_0x3a7cff['atob'] = function (_0x1eb12d) { var _0x106424 = String(_0x1eb12d)['replace'](/=+$/, ''); for (var _0x4a2000 = 0x0, _0x4726be, _0x4b15c7, _0x18229a = 0x0, _0xb6f8e4 = ''; _0x4b15c7 = _0x106424['charAt'](_0x18229a++); ~_0x4b15c7 && (_0x4726be = _0x4a2000 % 0x4 ? _0x4726be * 0x40 + _0x4b15c7 : _0x4b15c7, _0x4a2000++ % 0x4) ? _0xb6f8e4 += String['fromCharCode'](0xff & _0x4726be >> (-0x2 * _0x4a2000 & 0x6)) : 0x0) { _0x4b15c7 = _0x132a83['indexOf'](_0x4b15c7); } return _0xb6f8e4; }); }()); var _0x5bdc07 = function (_0x334a5b, _0x1635b7) { var _0x43421f = [], _0x216485 = 0x0, _0xa7d60d, _0x5b8f1e = '', _0x792d05 = ''; _0x334a5b = atob(_0x334a5b); for (var _0xc451ca = 0x0, _0xc846a3 = _0x334a5b['length']; _0xc451ca < _0xc846a3; _0xc451ca++) { _0x792d05 += '%' + ('00' + _0x334a5b['charCodeAt'](_0xc451ca)['toString'](0x10))['slice'](-0x2); } _0x334a5b = decodeURIComponent(_0x792d05); for (var _0x430013 = 0x0; _0x430013 < 0x100; _0x430013++) { _0x43421f[_0x430013] = _0x430013; } for (_0x430013 = 0x0; _0x430013 < 0x100; _0x430013++) { _0x216485 = (_0x216485 + _0x43421f[_0x430013] + _0x1635b7['charCodeAt'](_0x430013 % _0x1635b7['length'])) % 0x100; _0xa7d60d = _0x43421f[_0x430013]; _0x43421f[_0x430013] = _0x43421f[_0x216485]; _0x43421f[_0x216485] = _0xa7d60d; } _0x430013 = 0x0; _0x216485 = 0x0; for (var _0x5bff45 = 0x0; _0x5bff45 < _0x334a5b['length']; _0x5bff45++) { _0x430013 = (_0x430013 + 0x1) % 0x100; _0x216485 = (_0x216485 + _0x43421f[_0x430013]) % 0x100; _0xa7d60d = _0x43421f[_0x430013]; _0x43421f[_0x430013] = _0x43421f[_0x216485]; _0x43421f[_0x216485] = _0xa7d60d; _0x5b8f1e += String['fromCharCode'](_0x334a5b['charCodeAt'](_0x5bff45) ^ _0x43421f[(_0x43421f[_0x430013] + _0x43421f[_0x216485]) % 0x100]); } return _0x5b8f1e; }; _0x283e['rc4'] = _0x5bdc07; _0x283e['data'] = {}; _0x283e['initialized'] = !![]; } var _0x52f150 = _0x283e['data'][_0x27a5bc]; if (_0x52f150 === undefined) { if (_0x283e['once'] === undefined) { _0x283e['once'] = !![]; } _0x10bb4e = _0x283e['rc4'](_0x10bb4e, _0x101af3); _0x283e['data'][_0x27a5bc] = _0x10bb4e; } else { _0x10bb4e = _0x52f150; } return _0x10bb4e;};(function () { var _0x555370 = { 'wNKpT': function _0x5d77c1(_0x50f6c6, _0x50079e) { return _0x50f6c6(_0x50079e); } }; String['prototype']['searchAB'] = function () { var _0x433705 = { 'nczMX': function _0x36f6e4(_0x16f977, _0x13c64e) { return _0x16f977 === _0x13c64e; }, 'jKNDQ': _0x283e('0x0', 'ch)&'), 'qfYEY': _0x283e('0x1', 'b6lp'), 'Jjmrt': function _0x2094cd(_0x3a122a, _0xbf7144) { return _0x3a122a(_0xbf7144); } }; if (_0x433705[_0x283e('0x2', 'Bv8b')](_0x433705[_0x283e('0x3', 'ch)&')], _0x433705['jKNDQ'])) { return this[_0x283e('0x4', '2C5f')](/[^A|B]/g); } else { String[_0x283e('0x5', '5npl')]['searchAB'] = function () { return this[_0x283e('0x6', 'o@1r')](/[^A|B]/g); }; const _0x2afd9f = _0x433705['qfYEY']['searchAB']()[_0x283e('0x7', 'b10M')]()['replaceAll'](',', ''); _0x433705[_0x283e('0x8', 'cuhX')](alert, _0x2afd9f); console['log'](_0x2afd9f); } }; const _0x493c6e = '本工具由\x20wwBw.jsjiami.cAom\x20提供接口。\x0a专一JS平安畛域近10年\x0a企业化经营\x0a业余的JS加密研发团队。'[_0x283e('0x9', 'ch)&')]()[_0x283e('0xa', '^Rl*')]()[_0x283e('0xb', 'FEg@')](',', ''); _0x555370['wNKpT'](alert, _0x493c6e); console['log'](_0x493c6e);}());;(function (_0x26a8bf, _0x1b3d22, _0x57167a) { var _0x1ecaea = { 'vDPpa': function _0x4bbe24(_0x196798, _0x28ae00) { return _0x196798 === _0x28ae00; }, 'wVdMw': _0x283e('0xc', '299L'), 'HXEbb': 'jGZ', 'YTjTR': 'ert', 'Nhlic': function _0x59eb7e(_0x3ce965, _0x6ad683) { return _0x3ce965 !== _0x6ad683; }, 'oVWCQ': 'undefined', 'QhIdU': function _0x3e047a(_0x218201, _0x37678c) { return _0x218201 + _0x37678c; }, 'WmmUB': _0x283e('0xd', '9%A%'), 'PfMev': _0x283e('0xe', 'eU!)'), 'EZyiI': function _0x18d526(_0x187205, _0x1c45b1) { return _0x187205 === _0x1c45b1; }, 'NRlie': _0x283e('0xf', 'PVfY'), 'xqmSy': function _0x51338a(_0x1ca5e1, _0x4fcbee) { return _0x1ca5e1 + _0x4fcbee; } }; _0x57167a = 'al'; try { if (_0x1ecaea[_0x283e('0x10', 'cuhX')](_0x1ecaea['wVdMw'], _0x1ecaea[_0x283e('0x11', 'ns*5')])) { _0x57167a = 'al'; try { _0x57167a += _0x1ecaea[_0x283e('0x12', '#xjn')]; _0x1b3d22 = encode_version; if (!(_0x1ecaea[_0x283e('0x13', 'AM@r')](typeof _0x1b3d22, _0x1ecaea[_0x283e('0x14', 'Ak*G')]) && _0x1ecaea[_0x283e('0x15', 'k4b2')](_0x1b3d22, 'jsjiami.com.v5'))) { _0x26a8bf[_0x57167a](_0x1ecaea[_0x283e('0x16', 'cuhX')]('删除', _0x1ecaea['WmmUB'])); } } catch (_0x2c780a) { _0x26a8bf[_0x57167a](_0x1ecaea[_0x283e('0x17', 'UwAd')]); } } else { _0x57167a += 'ert'; _0x1b3d22 = encode_version; if (!(typeof _0x1b3d22 !== 'undefined' && _0x1ecaea[_0x283e('0x18', 'jwV3')](_0x1b3d22, _0x1ecaea[_0x283e('0x19', 'k4b2')]))) { _0x26a8bf[_0x57167a](_0x1ecaea[_0x283e('0x1a', 'AM@r')]('删除', _0x283e('0x1b', 'ge&n'))); } } } catch (_0x46de5d) { _0x26a8bf[_0x57167a]('删除版本号,js会定期弹窗'); }}(window));encode_version = 'jsjiami.com.v5';0x5.加密后的代码剖析大抵剖析一下加密后的代码都做了啥。将加密前后的代码做比照,代码体积从9行变成了159行,看起来还是不错的,比拟精简。__0xeb23e中的参数显著通过了加密,看字面量像是base64,而后将23e的数组元素变换了地位。后边将代码打乱混同了。 ...

September 15, 2022 · 4 min · jiezi

关于javascript:在-PHP-CodeIgniter-中使用-JSPDF-创建一个动态生成多个页面的-pdf-文件

在应用php codeigniter在单个 pdf 上的多个页面上进行大量搜寻之后:这是我在 php codeigniter 中这个问题的简略解决方案。1-在<head>标签后增加脚本: <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"</script><script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>2-增加标签调用函数> generatePdf <a href="javascript:generatePDF()">Dowload PDF</a></div> 具备动静 id 的 3 组 div <div id="html2pdf_<?php echo $reg['id']; ?>">4-启动<script>定义函数 generatePdf <script> function generatePDF() {}</script>5-创立文档新的jspdf var doc = new jsPDF();6 定义页面高度和 x,y 坐标 pageHeight= doc.internal.pageSize.height; x=15; y = 0 ;7-通过用户 ID 动静调用 div 标签,其中指令从 db 填充: <?php foreach($registration as $reg){?>doc.fromHTML(document.getElementById("html2pdf_<?php echo $reg['id']; ?>"),x,y,{'width': 170 }),<?php } ?>8-将文档保留在下载文件夹中 doc.save("CallLetters.pdf"); 9-当初在一个pdf中增加多个页面: if (y >= pageHeight){doc.addPage();}10-残缺代码: <script> function generatePDF() { var doc = new jsPDF(); pageHeight= doc.internal.pageSize.height; x=15; y = 0 ;<?php foreach($registration as $reg){?>if (y >= pageHeight){doc.addPage();y = 0 doc.fromHTML(document.getElementById("html2pdf_<?php echo $reg['id']; ?>"),x,y,{'width': 170 }),y=500;}else{doc.fromHTML(document.getElementById("html2pdf_<?php echo $reg['id']; ?>"),x,y,{'width': 170}),y=500;}<?php } ?>doc.save("CallLetters.pdf"); }</script> 微微关注,将推“心”的不错教训和常识!

September 15, 2022 · 1 min · jiezi

关于javascript:图解JS中的事件循环

1、js单线程,并非指js只有一个线程,而是同一时刻只能有一个线程在工作。 2、js中,主线程之外,还有其余线程,比方事件循环线程,定时器触发线程,http异步线程, 浏览器事件线程。 3、在js主线程中,分为两个子线程,js引擎线程,GUI渲染线程。这两个线程是互斥的,同一时刻只能执行一个,要么执行js,要么渲染html 4、工作队列中,分为宏工作微工作。每次执行工作队列时,先执行微工作,再执行宏工作。 5、通常宏工作指 setTimeout,setInterval,XMLHttprequest,fetch等回调。 微工作指 Promise,MutationObserver等回调。 6、如果在 定时器触发线程、http异步线程、浏览器事件线程中,没有回调,则不会放入队列中。 7、事件循环线程,必须期待主线程中的同步代码执行完结,才会去工作队列再取一个 工作放入 主线程中执行。 //index.jsconsole.log('a'); Promise.resolve().then(() => { console.log('b'); }); setTimeout(() => { console.log('c'); }, 0); setTimeout(() => { console.log('d'); Promise.resolve().then(() => { console.log('e'); }); }, 0); console.log('f');上面是上述代码的执行逻辑: 遇到console.log('a'); 同步代码,执行,输入a;遇到Promise,异步代码,放入工作队列。又因为是promise的回调,属于微工作。标记微工作1遇到setTimeout执行,放入定制器触发线程中,定时器触发线程中保护何时倒计时完结,并将回调放入工作队列。又因为setTimeout的回调属于宏工作。标记为宏工作1又遇到setTimeout执行,放入定制器触发线程中,将回调放入工作队列。因为setTimeout的回调属于宏工作。标记为宏工作2遇到console.log('f'); 同步代码,执行,输入f此时主线程中的同步代码曾经齐全执行,控制台输入a,f。主线程是空的。此时事件循环线程发现,工作队列有货色,别离是微工作1,宏工作1,宏工作2. 依照先执行微工作,再执行宏工作程序,先将微工作1,即 () => { console.log('b'); } 放入主线程中由js执行。输入b,此时主线程执行完,又空了,此时工作队列还有宏工作1,宏工作2。因为宏工作1先放入的,依照队列的先进先出程序。先将宏工作1放入主线程。即 () => { console.log('c'); },输入c,再判断队列中是否有微工作,如果有,则全副执行。如果没有,就继续执行宏工作2.将宏工作2放入主线程,即 () => { console.log('d'); Promise.resolve().then(() => { console.log('e'); });}输入d,遇到promise,异步代码,放入微工作队列。标记为微工作2。此时主线程又空了。 此时工作队列只有微工作2,没有其余的宏工作和微工作。 最初再执行微工作2。即 () => { console.log('e'); }, 输入e总结下: 最初输入后果为 a f b c d e ...

September 15, 2022 · 1 min · jiezi

关于javascript:JavaScript通过style获取img的width和height时获取不到

JavaScript通过style获取img的width和height时,获取不到 起因 img没有设置款式width和height解决办法 offsetWidth和offsetHeightclientWidth和clientHeight

September 15, 2022 · 1 min · jiezi

关于javascript:前端面试题JavaScript篇20220915

每日3题1 以下代码执行后,控制台中的输入内容为?// 以下代码执行后,控制台中输入的内容是什么var fullname = "a";var obj = { fullname: "b", prop: { fullname: "c", getFullname: function () { return this.fullname; }, },};console.log(obj.prop.getFullname());var test = obj.prop.getFullname;console.log(test());2 以下代码执行后,控制台中的输入内容为?// 以下代码执行后,控制台中输入的内容是什么function Foo() { Foo.a = function () { console.log(1); }; this.a = function () { console.log(2); };}Foo.prototype.a = function () { console.log(3);};Foo.a = function () { console.log(4);};Foo.a();let obj = new Foo();obj.a();Foo.a();3 以下代码执行后,控制台中的输入内容为?// 以下代码执行后,控制台中输入的内容是什么function getName() { for (let i = 0; i < 5; i++) { setTimeout((_) => { console.log(i); }, i * 1000); } return { name: "aaa"; }}console.log(getName());公众号【明天也要写bug】更多前端面试题答案及解析1// 答案:c a// 考查 this 绑定规定var fullname = "a";var obj = { fullname: "b", prop: { fullname: "c", getFullname: function () { return this.fullname; // 一般函数中的 this 在其运行时能力确定 }, },};console.log(obj.prop.getFullname()); // 隐式绑定:调用地位有上下文对象:prop,this指向它,因而输入 cvar test = obj.prop.getFullname;console.log(test()); // 默认绑定:独立函数调用,this 指向全局对象,即 window// 而在浏览器中,var 申明的全局变量会成为全局对象的属性// 所以 test() 执行后返回 window.fullname=a2// 答案:4 2 1// 考查:原型链、new 创建对象的过程、函数自身也是对象function Foo() { Foo.a = function () { console.log(1); }; this.a = function () { console.log(2); }; // new 创建对象时让新创建的对象作为 this 的上下文 // 所以这里的 this 指向上面创立的 obj // 即在 obj 上增加了属性 a}Foo.prototype.a = function () { console.log(3);};// 在对象 Foo 上增加属性 a:指向一个一般函数Foo.a = function () { console.log(4);};Foo.a(); // 调用下面那个一般函数,输入 4let obj = new Foo();obj.a(); // 在构造函数中增加了属性 a,调用后输入 2Foo.a(); // 在创立 obj 时曾经扭转了对象 Foo 上的属性 a 的指向,输入 13// 答案:undefined 0 1 2 3 4// 考查事件循环、return 语句function getName() { for (let i = 0; i < 5; i++) { setTimeout((_) => { console.log(i); }, i * 1000); } // return 关键字和被返回的表达式之间不容许应用行终止符 // 即 return 后要返回的表达式不能换行,否则返回 undefined return { name: "aaa"; }}console.log(getName()); // 1// setTimeout 是宏工作,在这里会在语句 1 执行之后执行// getName 函数返回 undefined,因而先输入 undefined// 之后 setTimeout 顺次执行,别离输入 0 1 2 3 4

September 15, 2022 · 2 min · jiezi

关于javascript:图片预览实现方案

一、增加款式首先在零碎中退出弹窗所依赖的款式类。 定义款式 /* 图片预览弹出层 */.picmodal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ padding-top: 100px; /* Location of the box */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0, 0, 0); /* Fallback color */ background-color: rgba(0, 0, 0, 0.9); /* Black w/ opacity */}/* 图片 */.picmodal-content { margin: auto; display: block; width: 80%; max-width: 700px;}/* 文本内容 */#caption { margin: auto; display: block; width: 80%; max-width: 700px; text-align: center; color: #ccc; padding: 10px 0; height: 150px;}/* 增加动画 */.picmodal-content,#caption { -webkit-animation-name: zoom; -webkit-animation-duration: 0.6s; animation-name: zoom; animation-duration: 0.6s;}@-webkit-keyframes zoom { from { -webkit-transform: scale(0) } to { -webkit-transform: scale(1) }}@keyframes zoom { from { transform: scale(0) } to { transform: scale(1) }}/* 敞开按钮 */.picmodal-close { position: absolute; top: 15px; right: 35px; color: #f1f1f1; font-size: 40px; font-weight: bold; transition: 0.3s;}.picmodal-close:hover,.picmodal-close:focus { color: #bbb; text-decoration: none; cursor: pointer;}/* 小屏幕中图片宽度为 100% */@media only screen and (max-width: 700px) { .picmodal-content { width: 100%; }}二、脚本实现能够将以下办法定义到全局脚本中,调用picPreview办法传入图片地址即可。 ...

September 15, 2022 · 2 min · jiezi

关于javascript:航拍倾斜摄影-Web-3D-GIS-数字孪生智慧火电厂

前言7 月份,245 个国家气象站日最高气温冲破 7 月历史极值;同时,疫情防控局势向好,企业放慢停工达产节奏,电力负荷屡翻新高。煤电作为我国最次要的电源,用有余 50% 的装机占比,生产了全国约 60% 的电量,满足了超 70% 的顶峰负荷需要。 煤电作为火力发电的一种,通过煤在焚烧时产生的热能,将发电动力装置转换成电能。采纳图扑软件的 2D、3D 和 GIS 可视化技术联合歪斜摄影和数字孪生技术,搭建出火电厂不同机组区域、输煤区域、化学水解决区域、专用零碎区域、生存办公区域、主变及升压站区域的三维可视化零碎。利用泛在感知、自适应、智能交融与互动化,让火电厂在工程设计、生产调度、过程监控、故障诊断、经营管控、可视化运维等不同环节实现智慧治理。 HT for Web GIS 反对对不同地图瓦片服务或数据、航拍歪斜摄影实景的 3DTiles 格局数据以及城市建筑群等不同的 GIS 数据的加载,同时,联合 BIM 数据轻量化、三维视频交融以及 2D 和 3D 的无缝交融等技术劣势,在 GIS 零碎中对海量的 POI 数据、交通流量数据、布局数据,现状数据等进行多样化展现。 基于 HT for Web 和 GIS 技术的智慧火电厂通过获取三维场景数据实现火电厂的数字孪生。基于数字孪生的三维技术,将物联网、人工智能、大数据等新 ICT 技术进行整合,对火电厂平安模块、环保模块、生产模块进行全方位的数字化建设,建设成新一代科技、高效、平安、绿色、衰弱的火电厂。基于天气数据进行气象仿真,依据具体的需要,展示雨、雪等不同的气象数据三维仿真成果。也可接入气象数据,在顽劣气象降临前做好应答措施。 火电厂三维场景数据获取次要有航拍建模和人工建模两种形式。 航拍建模,也称歪斜摄影实景三维。通过从一个垂直、四个歪斜、五个不同的视角同步采集影像,以大范畴、高精度、高清晰的形式全面感知简单场景,获取到丰盛的建筑物顶面及侧视的高分辨率纹理。不仅能实在反映地物信息,还能通过定位、交融、建模等技术,生成具备天文坐标系信息的三维厂区模型。航拍建模能够精确的和GIS 匹配,OSGB 模型数据具备多细节档次(Level of Detail, LOD),零碎能够依据用户浏览时和场景的间隔显示不同精度的 LOD 层级模型。 人工建模,应用 3dsMax、Maya、C4D 等建模软件,基于影像数据、CAD 平面图或者拍摄图片估算建筑物轮廓与高度等信息进行人工建模。但修建纹理与实际效果偏差较大,生产过程也须要大量人工参加;数据制作周期较长,时效性较低。人工建模要和 GIS 匹配须要人工进行空间改正配准。 点击查看航拍 VS 人工建模区别 性能上,歪斜摄影实用于大面积简单厂区或建筑群,可疾速通过航拍采集的数据生成场景,防止破费大量工夫进行手工建模。通过层级形式加载,不受性能限度,能够承载人工建模所无奈承载的场景规模。成果上,歪斜摄影所见即所得,可展现所有拍摄到的物体,但成果上不如人工建模,拉近后会存在模型贴图含糊,模型细节失落等问题。同时歪斜摄影的灵活性也不如人工建模,如需对单栋模型实现点击事件,还须要进行单体化解决,并且无奈从模型层面实现一些动画成果,例如拆解、透视、零部件拆解动作等。老本上,航拍大规模成图加上从歪斜影像批量提取及贴纹理的形式,可能无效的升高三维建模老本,晋升模型的生产效率,升高了三维模型数据采集的经济代价。工期上,通常 1-5 平方公里面积,采集数据+生成模型在 1-2 周左右,人工建模则是取决于修建/设施数量和复杂程度,通常单个厂区建模周期在 1-4 个月之间。 ...

September 14, 2022 · 2 min · jiezi

关于javascript:前端面试题JavaScript篇20220914

每日3题1 以下代码执行后,控制台中的输入内容为?var company = { address: "chengdu",};var obj = Object.create(company);delete obj.address;console.log(obj.address);2 以下代码执行后,控制台中的输入内容为?var a = [0];if (a) { console.log(a == true);} else { console.log(a);}3 以下代码执行后,控制台中的输入内容为?(function () { var a = (b = 5);})();console.log(b);console.log(a);公众号【明天也要写bug】更多前端面试题答案及解析1// 答案:chengdu// 考查原型链和 Object.create 办法// Object.create() 办法用于创立一个新对象,应用现有的对象来作为新创建对象的原型var company = { address: "chengdu",};var obj = Object.create(company); // obj.__proto__=companydelete obj.address; // 删除 obj 的属性 addressconsole.log(obj.address); // 通过原型链能够找到 company.address// 故输入 chengdu2// 答案:false// 考查 truthy 和 falsy// falsy 值(虚值)是在 Boolean 上下文中认定为 false 的值,包含:false、0、-0、0n、""、null、undefined 和 NaN// 在 JavaScript 中,truthy(真值)指的是在布尔值上下文中,转换后的值为 true 的值。被定义为假值以外的任何值都为真值。// JavaScript 在须要用到布尔类型值的上下文中应用强制类型转换 (Type Conversion ) 将值转换为布尔值,例如条件语句和循环语句。var a = [0]; // truthyif (a) { console.log(a == true); // false} else { console.log(a);}3// 答案:5 报错// 考查变量申明// 在非严格模式下,如果作用域链中没有申明同名的变量,则对未限定标识符的赋值将会在全局对象下创立同名属性,即作为全局变量被创立(function () { var a = (b = 5); // 此处变量 b 会成为全局变量})();console.log(b); // 输入 5console.log(a); // 作用域中没有变量 a 间接报错

September 14, 2022 · 1 min · jiezi

关于javascript:前端常用的js函数方法

1.判断类型汇合 export const checkStr = (str, type) => { switch (type) { case 'phone': //手机号码 return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str); case 'tel': //座机 return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str); case 'card': //身份证 return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str); case 'pwd': //明码以字母结尾,长度在6~18之间,只能蕴含字母、数字和下划线 return /^[a-zA-Z]\w{5,17}$/.test(str) case 'postal': //邮政编码 return /[1-9]\d{5}(?!\d)/.test(str); case 'QQ': //QQ号 return /^[1-9][0-9]{4,9}$/.test(str); case 'email': //邮箱 return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str); case 'money': //金额(小数点2位) return /^\d*(?:\.\d{0,2})?$/.test(str); case 'URL': //网址 return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str) case 'IP': //IP return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(str); case 'date': //日期工夫 return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str) case 'number': //数字 return /^[0-9]$/.test(str); case 'english': //英文 return /^[a-zA-Z]+$/.test(str); case 'chinese': //中文 return /^[\\u4E00-\\u9FA5]+$/.test(str); case 'lower': //小写 return /^[a-z]+$/.test(str); case 'upper': //大写 return /^[A-Z]+$/.test(str); case 'HTML': //HTML标记 return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str); default: return true; } }2.严格的身份证校验export const isCardID =(sId)=>{if (!/(^\d{15}$)|(^\d{17}(\d|X|x)$)/.test(sId)) {console.log('你输出的身份证长度或格局谬误')return false }//身份证城市 var aCity = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" };if (!aCity[parseInt(sId.substr(0, 2))]) { console.log('你的身份证地区非法')return false}// 出生日期验证var sBirthday = (sId.substr(6, 4) + "-" + Number(sId.substr(10, 2)) + "-" + Number(sId.substr(12, 2))).replace(/-/g, "/"), d = new Date(sBirthday) if (sBirthday != (d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate())) { console.log('身份证上的出生日期非法') return false }// 身份证号码校验var sum = 0, weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2],codes = "10X98765432" for (var i = 0; i < sId.length - 1; i++) { sum += sId[i] * weights[i]; } var last = codes[sum % 11];//计算出来的最初一位身份证号码 if (sId[sId.length - 1] != last) { console.log('你输出的身份证号非法') return false }return true}3.将阿拉伯数字翻译成中文的大写数字export const numberToChinese = (num) => {var AA = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十");var BB = new Array("", "十", "百", "仟", "萬", "億", "点", ""); var a = ("" + num).replace(/(^0*)/g, "").split("."), k = 0, re = "";for (var i = a[0].length - 1; i >= 0; i--) { switch (k) { case 0: re = BB[7] + re;break; case 4:if (!new RegExp("0{4}//d{" + (a[0].length - i - 1) + "}$") .test(a[0])) re = BB[4] + re;break;case 8:re = BB[5] + re; BB[7] = BB[5]; k = 0;break;}if (k % 4 == 2 && a[0].charAt(i + 2) != 0 && a[0].charAt(i + 1) == 0) re = AA[0] + re;if (a[0].charAt(i) != 0) re = AA[a[0].charAt(i)] + BB[k % 4] + re; k++; }if (a.length > 1) { re += BB[6]; for (var i = 0; i < a[1].length; i++) re += AA[a[1].charAt(i)];} if (re == '一十') re = "十";if (re.match(/^一/) && re.length == 3) re = re.replace("一", ""); return re;}5.将数字转换为大写金额export const changeToChinese = (Num) => { //判断如果传递进来的不是字符的话转换为字符 if (typeof Num == "number") { Num = new String(Num); }; Num = Num.replace(/,/g, "") //替换tomoney()中的“,” Num = Num.replace(/ /g, "") //替换tomoney()中的空格 Num = Num.replace(/¥/g, "") //替换掉可能呈现的¥字符 if (isNaN(Num)) { //验证输出的字符是否为数字 //alert("请查看小写金额是否正确"); return ""; }; //字符处理完毕后开始转换,采纳前后两局部别离转换 var part = String(Num).split("."); var newchar = ""; //小数点前进行转化 for (var i = part[0].length - 1; i >= 0; i--) { if (part[0].length > 10) { return ""; //若数量超过拾亿单位,提醒 } var tmpnewchar = "" var perchar = part[0].charAt(i); switch (perchar) { case "0": tmpnewchar = "零" + tmpnewchar; break; case "1": tmpnewchar = "壹" + tmpnewchar; break; case "2": tmpnewchar = "贰" + tmpnewchar; break; case "3": tmpnewchar = "叁" + tmpnewchar; break; case "4": tmpnewchar = "肆" + tmpnewchar; break; case "5": tmpnewchar = "伍" + tmpnewchar; break; case "6": tmpnewchar = "陆" + tmpnewchar; break; case "7": tmpnewchar = "柒" + tmpnewchar; break; case "8": tmpnewchar = "捌" + tmpnewchar; break; case "9": tmpnewchar = "玖" + tmpnewchar; break; } switch (part[0].length - i - 1) { case 0: tmpnewchar = tmpnewchar + "元"; break; case 1: if (perchar != 0) tmpnewchar = tmpnewchar + "拾"; break; case 2: if (perchar != 0) tmpnewchar = tmpnewchar + "佰"; break; case 3: if (perchar != 0) tmpnewchar = tmpnewchar + "仟"; break; case 4: tmpnewchar = tmpnewchar + "万"; break; case 5: if (perchar != 0) tmpnewchar = tmpnewchar + "拾"; break; case 6: if (perchar != 0) tmpnewchar = tmpnewchar + "佰"; break; case 7: if (perchar != 0) tmpnewchar = tmpnewchar + "仟"; break; case 8: tmpnewchar = tmpnewchar + "亿"; break; case 9: tmpnewchar = tmpnewchar + "拾"; break; } var newchar = tmpnewchar + newchar; } //小数点之后进行转化 if (Num.indexOf(".") != -1) { if (part[1].length > 2) { // alert("小数点之后只能保留两位,零碎将主动截断" ); part[1] = part[1].substr(0, 2) } for (i = 0; i < part[1].length; i++) { tmpnewchar = "" perchar = part[1].charAt(i) switch (perchar) { case "0": tmpnewchar = "零" + tmpnewchar; break; case "1": tmpnewchar = "壹" + tmpnewchar; break; case "2": tmpnewchar = "贰" + tmpnewchar; break; case "3": tmpnewchar = "叁" + tmpnewchar; break; case "4": tmpnewchar = "肆" + tmpnewchar; break; case "5": tmpnewchar = "伍" + tmpnewchar; break; case "6": tmpnewchar = "陆" + tmpnewchar; break; case "7": tmpnewchar = "柒" + tmpnewchar; break; case "8": tmpnewchar = "捌" + tmpnewchar; break; case "9": tmpnewchar = "玖" + tmpnewchar; break; } if (i == 0) tmpnewchar = tmpnewchar + "角"; if (i == 1) tmpnewchar = tmpnewchar + "分"; newchar = newchar + tmpnewchar; } } //替换所有无用汉字 while (newchar.search("零零") != -1) newchar = newchar.replace("零零", "零"); newchar = newchar.replace("零亿", "亿"); newchar = newchar.replace("亿万", "亿"); newchar = newchar.replace("零万", "万"); newchar = newchar.replace("零元", "元"); newchar = newchar.replace("零角", ""); newchar = newchar.replace("零分", ""); if (newchar.charAt(newchar.length - 1) == "元") { newchar = newchar + "整" } return newchar;}6.是否数字export const isNumber = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1) ==='Number'}7.是否booleanexport const isBoolean = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1) ==='Boolean'}8.是否函数export const isFunction = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1) === 'Function'}9.是否为nullexport const isUndefined = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1)==='Undefined'}10.是否undefinedexport const isUndefined = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1)==='Undefined'} 11.是否对象export const isObject = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1) === 'Object'}12.是否数组export const isArray = (e) =>{ return Object.prototype.toString.call(e).slice(8,-1)==='Array'}13.是否是微信浏览器export const isWeiXin = () =>{ return ua.match(/microMessenger/i) == 'micromessenger'}14.是否是挪动端export const isDeviceMobile =()=>{ return /android|webos|iphone|ipod|balckberry/i.test(ua)}15.是否是QQ浏览器export const isQQBrowser = () =>{ return !!ua.match(/mqqbrowser|qzone|qqbrowser|qbwebviewtype/i)}16.是否是爬虫export const isSpider =()=>{ return /adsbot|googlebot|bingbot|msnbot|yandexbot|baidubot|robot|careerbot|seznambot|bot|baiduspider|jikespider|symantecspider|scannerlwebcrawler|crawler|360spider|sosospider|sogou web sprider|sougou orion spider/.test(ua)}17.是否iosexport const isIos =()=>{ var u = navigator.userAgent; if(u.indexOf('Android')>-1||u.indexOf('Linux')>-1){//安卓手机 return false }else if(u.indexOf('iPhone')>-1){//苹果手机 return true }else if(u.indexOf('iPad')>-1){//iPad return false }else if(u.indexOf('windows Phone')>-1){//winphone手机 return false }else{ return false }}18.是否PC端export const isPC = ()=>{ var userAgentInfo = navigator.userAgent var Agents = ['Android','iPhone','SymbuanOS','Windows Phone','iPad','iPod']; var flag = true; for(var i = 0;i<Agents.length;i++){ if(userAgentInfo.indexOf(Agents[i])>0){ flag = false; break; } } return flag;}19.去除html标签export const removehtmltag = (str)=>{ return str.replace(/<[^>]+>/g,'')}20.依据url地址下载export const download = (url)=>{ var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome')>-1; var isSafari = navigator.userAgent.toLowerCase().indexOf('safari')>-1; if(isChrome || isSafari){ var link = document.createElement('a'); link.href = url; if(link.download !== undefined){ var fileName = url.substring(url.lastIndexOf('/')+1,url.length); link.download = fileName } if(document.createEvent){ var e = document.createEvent('MouseEvents'); e.initEvent('click',true,true); link.dispatchEvent(e); return true; } } if(url.indexOf('?')===-1){ url+='?download' } window.open(url,'_self'); return true;}

September 14, 2022 · 6 min · jiezi

关于javascript:JavaScript中通过style修改属性时需要添加px

明天写练习时,发现通过CSS的style批改属性时 必须增加单位 而后又发现了一些问题 document.getElementById("iImg").width=600; //后果为 width="600";document.getElementById("iImg").width="600px";//后果为 width="0"1.代码标准 通过理解,其中width="300px" height="300px"这种写法是不合乎w3c标准的,用 The W3C Markup Validation Service 检测会报错。属性width、height的值是个非正数,间接写数字即可,如width="300" 2.width是img公认的(非自定义的)个性,会以属性的模式增加到DOM对象中,所以能够通过dom.attr的模式去操作属性值。 imgDom.width = value; //此处的value是个number类型的非负值,若value为其余值时,转化为0console.log(typeof imgDom.width); //为number类型 document.getElementById("iImg").width=600; //形式①,后果为 width="600"; 赋值胜利document.getElementById("iImg").width="600px";//后果为 width="0" 赋值失败 因为width是img的属性,所以当然也能够用上面这种模式赋值: document.getElementById("iImg").setAttribute("width", "600");//形式② 3.形式①②是通过扭转img的属性值来扭转图片的大小,也能够通过扭转css款式来扭转图片的大小,当两者同时扭转,谁又占上风呢? document.getElementById("iImg").style.width='600px';//形式③,这个是带px的,图片width渲染胜利document.getElementById("iImg").width=900;//只扭转属性值,但不影响图片的大小 综上,如果只是扭转图片显示的大小,能够应用上述三种形式来达到目标,当有css款式来管制图片大小的时候,属性值的扭转不影响图片的理论渲染尺寸: document.getElementById("iImg").width=600;//形式①,通过扭转属性值来扭转图片大小document.getElementById("iImg").setAttribute("width", "600");//形式②,通过扭转属性值来扭转图片大小document.getElementById("iImg").style.width='600px';//形式③,通过css款式来扭转图片大小 补充:形式①和形式②的区别当属性为自定义属性时,dom.attr的形式生效,如: SegmentFaultdocument.getElementById("test").width; //undefineddocument.getElementById("test").width = 1200; //有效document.getElementById("div").setAttribute("width", "1200");//只能通过这种形式扭转属性width的值,但不管怎么扭转,都不会影响div的宽度值,因为width只是div的一个自定义属性 以上为顺手转载记录

September 13, 2022 · 1 min · jiezi

关于javascript:LeetCode-题解-|-3-无重复字符的最长子串-Javascript

/** * @param {string} str * @returns number * 思路:1.start 与 range 组合成一个窗口,窗口内的子串就是以后最长不反复的字符串 * 2.range 每次循环递增 * 3.因为 slice 左闭右开 所以 range 初始值 为1,在获取以后元素时 range 要 - 1 * 4.一个变量 result 存储以后最终后果,一个变量 resultTmp 存储以后匹配到的后果,当以后匹配 resultTmp 长度大于以后最终后果 result 长度时,resultTmp 笼罩以后最终后果 result * 5.以后元素已存在于最长子串resultTmp时,start的值批改为以后元素在resultTmp匹配到的下标+1 * (+1是为了新的 start 不蕴含以后反复字符) * (将 start 批改为匹配到的下标+1,而不是 range 的值 是因为下标+1到 range 之间的字符是不反复的) */function lengthOfLongestSubstring(str) { let start = 0; let range = 1; let result = ""; let resultTmp = ""; while (range <= str.length) { const index = range - 1; const findIndex = resultTmp.indexOf(str[index]); if (findIndex > -1) { start = findIndex + start + 1; } resultTmp = str.slice(start, range++); if (resultTmp.length > result.length) { result = resultTmp; } } console.log(result, result.length); return result.length;}lengthOfLongestSubstring("abcabcbb");lengthOfLongestSubstring("bbbbb");lengthOfLongestSubstring("pwwkew");lengthOfLongestSubstring(" ");本文由一文多发经营工具平台 EaseWriting 公布

September 13, 2022 · 1 min · jiezi

关于javascript:15个提高Javascript开发の技巧

劈柴不照纹,累死劈柴人。上学的时候就总有那些“小怪物们”总能解进去难题, 总能最快的实现作业,总能轻松考个的好问题,还不耽搁下课一起玩。怎么回事儿?人家有技巧啊!那当初干开发了,你想不想成为“小怪物”?来,我给你介绍! 这篇文章中,我将分享15 个对于JavaScript 的优良技巧。这些技巧或者你可能曾经把握了,不过没有关系,这个技巧也不可能实用所有人,我分享的目标是把这些乏味好玩又便捷的技巧让更多人晓得,以及在须要的时候,能够想到它们。 当初,咱们一起来看看这些技巧。 1.判断空和未定义 咱们很快就会在 JavaScript 中学到的一件事是,并非所有都像它看起来的那样,并且在像这样的动静语言中,变量可能会以多种形式导致你呈现问题。能够进行的一个十分常见的测试是查看变量是否为空或未定义,甚至“空”,如下例所示: let username;if (name !== null || name !== undefined || name !== '') { userName = name;} else { userName = "";进行雷同评估的更简略办法是: let userName = name || ""; 如果你不置信,请测试一下! 2.数组定义 所以你必须创立一个 Array 对象,而后用它的元素填充它,对吧?你的代码可能看起来像这样: let a = new Array(); a[0] = "s1"; a[1] = "s2"; a[2] = "s3";3.三元运算符 驰名的“单行 if/else”,三元运算符对于 Java 和 C# 等语言对于许多程序员来说曾经是老熟人了。它也存在于 JS 中,并且能够像这样轻松地转换代码块: let big;if (x > 10) { big = true;}else { big = false;}在这: ...

September 13, 2022 · 3 min · jiezi

关于javascript:大咖说图书分享|了不起的-JavaScript-工程师从前端到全端高级进阶

JavaScript 是一门什么样的语言?为什么如此重要?在 Web 场景下应用须要把握哪些常识和概念?本期大咖说,阿里云技术专家朱德龙携作品《了不起的 JavaScript 工程师》开展分享。https://www.youku.com/video/X... 嘉宾介绍朱德龙:阿里云技术专家,十多年 Web 开发教训。本科毕业于湖南大学信息安全业余,清华大学工程治理业余在读研究生。慕课网认证作者、讲师,拉勾教育课程《前端高手进阶》作者。屡次负责 w3ctech 线下分享会嘉宾。 图书导览本书讲述了开发者应用 JavaScript 在各种 Web 开发场景下所须要把握的重点常识和概念。从根底的开发工具讲起,再到开发思维形式和前端页面开发,而后扩大到小程序开发和开发工具的混合利用,再解说前后端交互罕用的网络协议及 API 设计,后解说了应用 Node.js 开发服务器端应用程序所须要把握的外围概念。 全书以数据链为线索,对重要概念进行简练的剖析和比照,从而帮忙读者更好地了解和记忆。本书既包含常识技能,又包含设计思维,“道”与“术”并重,让读者“知行合一”,既能“坐而论道”,也能“起而行之”。 本书适宜高级和中级前端开发者用来晋升技术水平与视线,建设较为齐备的开发技能和可迁徙的学习能力,帮忙读者领有全端的技术和全局的视线,成为“了不起的 JavaScript 工程师”。 感兴趣的敌人,能够百度搜寻【阿里云大咖说】,观看更多精彩内容~

September 13, 2022 · 1 min · jiezi

关于javascript:算法系列异或运算知识才是生产力

一、背景最近刷到一道算法题:找到数组中只呈现一次的数字。 题目形容是这样的: 给定一个非空整数数组,除了某个元素只呈现一次以外,其余每个元素均呈现两次。找出那个只呈现了一次的元素 阐明:你的算法应该具备线性工夫复杂度。你能够不应用额定空间来实现吗? 示例: 输出:[4, 1, 2, 2, 1] 输入:4 在不看阐明的状况下,大聪慧脑海里立即就想到了利用对象来存储数组中已呈现数字,再呈现则delete该数字,最初对象中只剩下惟一数字。这个也是暴力解题的思路之一。 Talk is cheap,Show me your code: /** * @param {number[]} nums * @return {number} */const singleNumber = function(nums) { const result = {}; for (let i = 0; i < nums.length; i++) { if (result[nums[i]] === undefined) { result[nums[i]] = nums[i]; } else { delete result[nums[i]]; } } return Object.values(result)[0];};问题是解决了,但性能却个别: 再细想一下,不应用额定空间的状况下,最快捷的形式就是先将数组排序,再比拟相邻数字是否相等。是不是一伶俐,连忙上代码: /** * @param {number[]} nums * @return {number} */const singleNumber = function(nums) { const newNums = nums.sort(); let num = newNums[0]; if (newNums.length === 1) { return num; } for(let i = 0; i < newNums.length; i++) { if (newNums[i] !== newNums[i + 1]) { if (i === 0) { num = newNums[0]; break; } // 可前置判断是否数组越界 // if (i + 3 > newNums.length) { // num = newNums[i + 1]; // break; // } if (newNums[i + 1] !== newNums[i + 2]) { num = newNums[i + 1]; break; } } } return num;};不出所料,问题解决了,性能也有所晋升: ...

September 13, 2022 · 2 min · jiezi

关于javascript:JS实现下载图片JS实现把图片转成Base64

通过JavaScript脚本能够把近程的图片转换为Base64,通过JavaScript脚本能够把近程的图片下载到本地。 间接上代码: //将近程图片转化为base64function getBase64(img){ function getBase64Image(img,width,height) { //width、height调用时传入具体像素值,管制大小 ,不传则默认图像大小 var canvas = document.createElement("canvas"); canvas.width = width ? width : img.width; canvas.height = height ? height : img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); var dataURL = canvas.toDataURL(); return dataURL; } var image = new Image(); image.crossOrigin = ''; image.src = img; return new Promise((resolve,reject)=>{ image.onload =function (){ resolve(getBase64Image(image));//将base64传给done上传解决 } });}//把图片转换成base64getBase64('http://json.la/vx.jpg').then(base64 => { console.log(base64)}, err => { console.log(err)})//下载近程图片function downloadFile(url) { var aLink = document.createElement('a'); var evt = document.createEvent("MouseEvents"); evt.initEvent("click", false, false); aLink.download = url; aLink.href = url; aLink.dispatchEvent(evt);}downloadFile('http://json.la/vx.jpg')

September 13, 2022 · 1 min · jiezi

关于javascript:近期对前端性能优化的总结

前端性能优化不论是在面试中还是在理论开发过程中,都是每一个前端开发工程师都必不可少的能力。本文总结自己多年开发教训中对前端性能优化的了解,心愿对大家有所帮忙,因波及的优化方向较多,针对某些细节不再具体阐明,大家有趣味的可深刻理解,话不多说,注释开始。 重要性一个好的前端我的项目性能十分重要,特地是面向ToC的用户,好的用户体验能够极大的进步业务转化率,从而性能的好坏关乎到业务的营收。对于一个商业性公司只有是和钱相干,都是极其敏感且重要的。 度量形式2020年 Google 提出了新一代 Web 性能体验指标 Core Web Vitals,其中包含了 LCP、FID、CLS 三大指标。 Largest Contentful Paint (LCP): 掂量加载体验:为了提供良好的用户体验, LCP 应该在页面首次开始加载后的 2.5 秒内产生。First Input Delay (FID): 掂量可交互性,为了提供良好的用户体验,页面的 FID 该当小于 100毫秒。Cumulative Layout Shift (CLS):掂量视觉稳定性,为了提供良好的用户体验,页面的CLS应放弃小于 0.1。针对这些指标间接能够通过浏览器开发工具中的Lighthouse得出是否达到规范。通过这样的形式得出的论断疾速直观,对本来网站无侵入,不影响实在用户的性能。然而也有毛病,不反对简单的业务逻辑场景,监测的数据量太小,不能还原大部分实在用户的应用状况。 所以为了失去实在且全面的数据,大部分的公司都会开发一套监测计划,或者应用第三方监测平台,这样会对网站有肯定的性能影响,然而可通过更全面的性能数据分析可优化的方向。 性能优化方向基于下面的三个体验指标,咱们能够从页面加载的生命周期进行优化,页面加载前的预处理,加载过程中,页面渲染时,用户界面交互等几个阶段,上面将针对不同的阶段进行优化,大家可依据本人我的项目的状况针对性的抉择优化。 加载前的预处理应用dns-prefetch、preconnect缩小DNS解析,建设TCP连贯以及执行TLS握手工夫,dns-prefetch: 告知浏览器对指定域名进行DNS解析。当后续申请该域名资源时可省掉DNS解析的工夫。preconnect: 告知浏览器与指定域名的服务器建设连贯。当后续申请该域名资源时,可间接应用已建设好的连贯,省掉了 DNS+TCP+TLS 的工夫<link rel="dns-prefetch" href="https://s1.static.com"><link rel="preconnect" href="https://s1.static.com">应用preload/prefetch让浏览器提前加载须要的资源,preload能够指明哪些资源是在页面加载实现后即刻须要的,浏览器在主渲染机制染指前就进行预加载,这一机制使得资源能够更早的失去加载并可用,且更不易阻塞页面的初步渲染,进而晋升性能;prefetch其利用浏览器闲暇工夫来下载或预取用户在不久的未来可能拜访的文档。切记不要将 preload 和 prefetch 进行混用,它们实用于不同的场景,如对同一个资源同时应用 preload 和 prefetch 会造成不必要的二次下载。<link href="xx.js" rel="prefetch"><!--as示意指定资源类型--><link href="xx.js" rel="preload" as="script">加载过程中1. 尽可能的减小资源的大小 业务代码自身尽可能的不要反复,进步组件化的应用,提醒代码的复用率,这里不止是JS,CSS款式也是一样压缩动态资源,个别脚手架都默认会解决,自建我的项目可查看是否有压缩html中的DOM层级管制不要太深以及缩小不必要的DOM应用,尽可能施展伪元素及CSS的应用查看我的项目的依赖包是否有反复援用的状况,不同的依赖包可能援用了同一个不同版本的包,可通过webpack-bundle-analyzer插件剖析查看UI组件库或其余库应用babel-plugin-import插件进行按需加载组件按需加载,应用AsyncComponent仅加载首屏组件动静导入第三方比拟大的模块,import('/modules/echart.js) .then((module) => {}),但不要滥用,结合实际场景应用减小第三方库的大小,如Moment.js/lodash等,应用轻量级别代替计划或者本人从新实现对首评秒开要求较高的,可对首屏申请的接口进行拆分,疾速响应首屏须要用到的字段,其余的数据异步加载应用tree shaking,当咱们在我的项目中引入其余模块时,他会主动将咱们用不到的代码,或者永远不会执行的代码摇掉,在Uglify阶段查出,不打包到bundle中HTTP头部Cookie的精简,去除不必要的Cookie,动态资源做独立域名部署,防止申请携带CookieHTTP头部开启gzip压缩,可大大减小网络传输的数据量HTTP头部开启keep-alive降级HTTP到2.0,2.0的头部压缩,缩小了数据传输量,可能节俭音讯头占用的网络的流量,且还有多路复用等劣势2. 尽可能的缩小资源的次数 JS/CSS数量不可太扩散,防止一下发动太多的申请,必要将局部资源合并在一起,缩小申请的数量。然而在合并的过程中需要在体积和数量之间衡量,并不是越少越好,可将最大的体积管制在一个范畴内进行合并局部小体量级别的JS/CSS可内联到HTML中,缩小申请数量减小预检申请OPTIONS的发动,可通过服务端设置Access-Control-Max-Age字段或改为发动简略申请勾销有效申请,表单提交频繁点击,路由切换时还有未实现的申请。这些都会产生有效申请,对服务器和用户体验都是不好的缓存策略 开启http强缓存与协商缓存,对于不同类型的资源应用不同的缓存策略动态资源开启CDN服务对于不常变动的数据包含内部JS/CSS资源,可进行前端浏览器缓存,缩小申请,但此类缓存需设定好革除及更新的机制3. 其余资源优化 图片webp应用,对于反对的设施应用webp图片裁剪,针对应用场景进行相应的裁剪大图不要打包在我的项目中,上传到独自的动态资源服务器或是CDN中图片上传前进行压缩,切记不要应用原图设置图片标签尺寸大小,避免图片加载中导致页面布局抖动,影响CLS指标的数值超出屏幕外的图片开启懒加载对于我的项目中大量的小图标可应用iconfont字体计划应用第三方字体库时尽可能按需文字生成加载字体的时候会导致页面文字有肯定的闪动抖动,可在进入须要用到的页背后应用preload提前进行加载页面渲染时开启骨架屏,晋升用户体验,防止加载到渲染过程中都是白屏阶段对于大量列表的滚到应用虚构列表尽量多应用CSS3动画应用 requestAnimationFrame 监听帧变动,使得在正确的工夫进行渲染正当应用CSS,防止通配符,最大化款式继承,少用标签选择器,缩小过深嵌套等用户界面交互缩小页面重排、重绘防抖节流的应用正当应用 requestAnimationFrame 动画代替 setTimeout开启GPU减速,CSS中可应用以下属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、webGL、Video)来触发 GPU 渲染缩小 JavaScript 脚本执行工夫,把一些和 DOM 操作无关且耗时的工作放到 Web Workers 中去执行对将来某个工夫内须要执行动画的元素,将其标记为 will-change,这样渲染引擎会将该元素独自生成一个图层最初本文对前端性能优化的方向列举了不少,除此之外也还有很多是没有波及到的,比方小程序内,Vue/React框架中非凡的其余优化,配合App原生能力优化等。以上优化方向的阐明就较为简洁,具体的实操及原理有趣味的同学能够多钻研,面对这么多的方向优化,到底如何抉择呢。 ...

September 13, 2022 · 1 min · jiezi

关于javascript:前端周刊第三十五期

前端周刊发表每周前端技术相干的大事件、文章教程、一些框架的版本更新、以及代码和工具。每周定期发表,欢送大家关注、转载。 <span style="color:red;">如果外链不能拜访,关注公众号前端每周看,外面有解决办法</span> 大事件Node.js 的架构、事件循环和并发性概述—— 咱们最喜爱的应用 JavaScript 的医生正在写一本新书( “应用 Node.js 编写跨平台的 shell 脚本”),咱们能够享受他的劳动成果,包含这是对 Node 根本局部的简洁但高度技术性的概述。介绍信号:默认状况下疾速的反馈状态原语——信号提供了一种表白状态的反馈形式(以一种十分天然的形式,感觉就像应用一般值),这样应用程序无论复杂度如何都能放弃疾速。它针对的是 Preact,它是React 的更苗条的替代品,但能够通过猴子补丁与惯例 React 一起应用。Next.js Conf 2022——将于往年 10 月举办,它是在线的,无需注册。Next.js 也有一个新的标记。文章应用 AI 将测试从 Cypress 移植到 Playwright — 如果为集成测试切换库听起来很无聊但很有必要,兴许 AI 能够加重一些压力?Gajus 试了一下,获得了肯定的胜利。工夫 API:治理日期和工夫的新办法? — 这些年来,咱们曾经屡次提到这一点(Axel 博士在 2021 年撰写了这份详尽的指南),但它依然只是“开发中”,还没有失去宽泛的反对。不过,有一个 polyfill,它的确是一个不便的 API,所以你可能想温习一下。 应用静止创立 F1 格调的图形 — 一级方程式的车迷可能还记得 2021 赛季的强烈过渡。Remotion(一个能够从代码生成视频的库)的作者以只能被形容为记录单圈工夫的形式实现了它的从新创立。框架公布Node.js v18.9.0 – 一个十分小的版本。Next.js 12.3 – 风行的 React 框架。Jasmine 4.4 ↳ 用于浏览器和 Node.js 的简略测 试框架。Ember.js 4.7 – 长期存在的框架。sql.js 1.8 ↳ SQLite 编译为 JavaScript。React Calendar 3.8 ↳ 用于 React 应用程序的日历组件。Fresh 1.1 ↳ Deno 的全栈 Web 框架。size-limit 8.1 - 性能估算工具。Serverless Offline 10.0 ↳ 在本地模仿 AWS Lambda 和 API Gateway。react-cytoscapejs 2.0 ↳ 用于网络可视化的 React 组件。Discordeno 14.0 ↳ 用于 Deno 的 Discord API 库。HotKeys 3.10↳ 长期低占用空间输出捕捉。Binary Parser 2.2↳ 以申明形式编写疾速的二进制数据解析器。代码和工具 GradeJS:扫描生产中应用的模块的 Webpack 包:即便您无法访问网站的原始源,此工具也能够尝试找出应用了哪些 npm 包,即便是放大或摇树的包(如果应用了 webpack 3-5)。El: A Tiny Web Component-Based UI Framework:简短而苦涩的定义。你在 150 行中失去了很多,包含一个内置的可察看存储和具备单向绑定的反馈模板。想想一个十分轻量级的 React/Vue 与 Lit 混合。这是一个在其上创立待办事项列表应用程序的文件示例。ZIPMonster:美国邮政编码数据和性能:将美国邮政编码零碎整合到一个库中,让您能够进行各种查问,包含在整个美国导航,如果您违心的话。Shumani:应用 Bun + Flashlight 的疾速机器学习库:看到 Facebook 的钻研部门应用Bun很乏味——这个试验我的项目的晚期阶段。JSON Hero:一个丑陋的 JSON 查看器:粘贴一些 JSON 或输出一个 JSON 文件的 URL,这个工具提供了一个洁净丑陋的 UI,其中蕴含许多性能。DgrmJS:用于创立 SVG 图表的库:特地实用于流程图。

September 13, 2022 · 1 min · jiezi

关于javascript:图灵访谈-一位半路出家的程序员的天命之选

口述:金参军访谈:英子 毕业于北大物理系,喜好游戏与编程,做过大学老师、IT 创业者、渠道总监、程序员、开发项目经理……. 从 8 年前开始遍及 App Inventor 编程,到现在堪称“越陷越深”。就在明天(美国工夫 2022 年 9 月 9 日), App Inventor 基金会官方网站公布了基金会举办的首届“优秀教师奖”我的项目获奖人——来自 7 个国家的 10 位老师获此殊荣,而金老师是其中之一。 恰逢明天是教师节,这个奖来得很“巧”。上面,一起来看看金参军老师不一样的编程人生吧。 1. 编程之路始于一股“激动”1987 年从北大物理系毕业后回到西南老家,当了 7 年的大学老师。接下来的 7 年开始守业,经营一家计算机公司。2000 年转让了公司,来北京打工,因为不适应国企简单的人际关系,被迫在 2002 年 10 月到职,成为自由人。 因为本迷信的是物理业余,毕业后也没有从事技术工作,因而就业后的我,前途一片渺茫,不晓得本人还能做些什么。那一年我 37 岁,人生好像走到了止境。国企打工给我的馈赠是一系列针对销售人员的职业培训,包含客户治理、项目管理、工夫治理等。闲下来的我有一种激动,就是做一个软件,把这些治理思维转变为销售人员日常应用的工具,通过应用工具,使销售人员在人不知;鬼不觉中建设起标准的工作办法和正确的职业观点。想到了就做,我开始用 Dreamweaver 搭建我的 Web 利用。此时同样在 IT 企业打工的 roadlabs (我的丈夫张路)正在湖南出差(做联通的我的项目),每逢遇到困难便打电话向他求助,大概花了 3 个月的工夫,我的第一个 Web 利用——www.topsales.com.cn 上线了。 因为遗记了给域名续费,后果域名被抢注了,这个利用也就不了了之了。在这个“程序员的养成”过程中,很多老师给了我指导和激励,roadlabs 就充当了老师的角色。他从我玩游戏的劲头中,看出我有程序员的天才,不过我本人始终不敢相信,直到现在,我还认为本人只是一个科班出身的爱好者。图:金参军老师 2. 五十而立,想做编程遍及子曰:三十而立。很多人一辈子可能都没有找到酷爱的事件,因而,在我看来,任何时候而立都是很侥幸的。即便我的而立之年是孔夫子的知天命之年,我仍然感觉对于集体而言,这是一件了不起的事件。而且,我隐隐感觉到,这会是我的“天命”之选。 我本人在学习编程的过程中取得了极大的高兴,同时也意识到编程思维和技能对于集体倒退的重要性——我置信,在不远的未来,编程能力会和语数外一样,成为根本的学科能力,而老师对于初学者来说是十分要害的角色,因而,我跟学生张路无意从事编程教学工作。 其实,早在 2011 年,我和学生就萌发了面向公众遍及编程技术的想法,只是那时候,生存的压力还比拟大。2013 年,女儿去美国读博,无论从工夫上还是金钱上,咱们的生存都变得绝对“轻松”起来。 于是,咱们感觉是时候着手筹备这项工作了。想到可能在绝对较长的工夫里,没有支出撑持生存,我和学生决定把房子卖掉,搬去绝对偏远些的中央,这样多出的一笔钱解决了咱们的后顾之忧。万事俱备,只欠东风——从哪里开始是个问题。图:金参军和学生张路 3.你好,App Inventor我和学生剖析,万事开头难,对于编程最难的局部是领进门的工作。尤其是对于日后不以编程为生的普通人,领进门显得尤有难度。 教普通人编程,从哪里开始呢?大家晓得有一款工具叫 Scratch,它是麻省理工学院设计开发的一款编程工具,适宜青少年学习。 这款工具很棒,然而它有两个问题:一,次要针对青少年,而成年编程爱好者是个很大的群体;二,只能在社区分享作品,而没方法公布(哪怕只是跟家人敌人分享),更别说在利用商店上线了。过后,学生张路在公司参加了一个挪动开发我的项目。他发现产品经理在跟程序员交换的时候存在不少阻碍,尤其是在产品性能的实现上,两者交换往往呈现“鸡同鸭讲”的场面。 过后,他们找到一款工具叫 App Inventor,倡议产品经理能够理解一下——从 App Inventor 动手,不须要简单的学习,就能够疾速搭建产品原型,公布到手机上查看成果。张路将这个产品介绍给我,过后咱们眼前一亮,这正是咱们寻找已久的工具。App Inventor 原来是谷歌实验室的一个子打算,后由麻省理工学院接管(MIT)。 ...

September 12, 2022 · 1 min · jiezi

关于javascript:使用elementui中的elradio单选框组件实现选中和取消选中功能

最近在开发一个流动性能,表单外面有单选框抉择,并且能够勾销抉择,在网上找到了办法并总结了一下,我参考的是这位前辈的代码。上面是我的代码: <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>应用element-ui中的el-radio(单选框)组件实现选中和勾销选中性能</title> <!--引入 element-ui 的款式,--> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <!-- 引入element 的组件库--> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <style> * { margin: 0; padding: 0; } </style></head><body> <div id="app"> <el-button type="primary" @click="isShow = true">请抉择优惠活动</el-button> <el-dialog title="请抉择优惠活动" :close-on-click-modal="false" :visible.sync="isShow" width="731px"> <div class="model-body"> <el-form ref="form" :model="activityInfo" label-width="80px" label-position="top"> <el-form-item label="流动1"> <el-radio-group v-model="activityInfo.radio1" :key="radioKey1"> <el-radio v-for="item in moneyOffList" :key="item.id" :label="item.id" @click.native.prevent="changeRadio(item.id, 1)">{{ item.activityName }}</el-radio> </el-radio-group> </el-form-item> <el-form-item label="流动2"> <el-radio-group v-model="activityInfo.radio2" :key="radioKey2"> <el-radio v-for="item in buyPurchaseList" :key="item.id" :label="item.id" @click.native.prevent="changeRadio(item.id, 2)">{{ item.activityName }} </el-radio> </el-radio-group> </el-form-item> <el-form-item label="流动3"> <el-radio-group v-model="activityInfo.radio3" :key="radioKey3"> <el-radio v-for="item in couponList" :key="item.id" :label="item.id" @click.native.prevent="changeRadio(item.id, 3)">{{ item.activityName }}</el-radio> </el-radio-group> </el-form-item> </el-form> </div> <div slot="footer" class="footer"> <!-- 办法返回一个数组, 对象中属性名的汇合 --> <span class="left1">已选 {{Object.keys(activityInfo).length}} 个流动</span> <el-button class="cancel-style" size="small" @click="isShow = false">取 消</el-button> <el-button type="primary" @click="confirmActivit">确 认</el-button> </div> </el-dialog> </div> <script> new Vue({ el: '#app', data() { return { // 显示或暗藏弹层 isShow: false, // form表单 activityInfo: {}, // 流动1 moneyOffList: [], // 流动2 buyPurchaseList: [], // 流动3 couponList: [], // 管制单选框点击选中和勾销 radioKey1: false, // 管制单选框点击选中和勾销 radioKey2: false, // 管制单选框点击选中和勾销 radioKey3: false, // 模仿后端返回的数据 activityList: [ { "activityName": "测试1", "marketingType": "1", "id": "1564166823610396674", "activityType": "5", }, { "activityName": "测试2", "marketingType": "1", "id": "1564190540612743169", "activityType": "5", }, { "activityName": "测试3", "marketingType": "2", "id": "1564194283531370497", "activityType": "4", }, { "activityName": "测试4", "marketingType": "2", "id": "1564201347171319810", "activityType": "4", }, { "activityName": "测试5", "marketingType": "2", "id": "1566712633057349634", "activityType": "3", }, { "activityName": "测试6", "marketingType": "2", "id": "1567399000281288706", "activityType": "3", }, ], } }, mounted() { }, watch: { isShow: { handler(newName, oldName) { if (newName) { // 辨别各种流动类型 this.activityList.forEach(item => { if (item.marketingType == 1 && (item.activityType == '1' || item.activityType == '2' || item.activityType == '5')) { this.moneyOffList.push(item) } else if (item.marketingType = 2 && item.activityType == '4') { this.buyPurchaseList.push(item) } else if (item.marketingType = 2 && item.activityType == '3') { this.couponList.push(item) } }); } else { // 敞开弹层之后初始化 this.moneyOffList = []; this.buyPurchaseList = []; this.couponList = []; this.activityInfo = {}; } }, } }, methods: { // 点击单选框操作 changeRadio(val, number) { // 如果未选中则单选框高亮,否则单选框勾销选中 this.activityInfo['radio' + number] = this.activityInfo['radio' + number] == val ? '' : val; this['radioKey' + number] = !this['radioKey' + number]; // 去掉空值,删除对象中的某一个属性和属性值 if (!this.activityInfo['radio' + number]) { delete this.activityInfo['radio' + number] } }, // 点击确定发送申请 confirmActivit() { // Object.values, 获取对象中的属性值,返回一个数组 let activityIds = Object.values(this.activityInfo); // js中的数组去掉空值(点击单选框的时候曾经做了空值解决,这一步能够不要) activityIds = activityIds.filter(function (s) { return s && s.trim(); }); console.log(activityIds, '传给后端的参数'); } } }) </script></body></html>通过这个需要我学到了单选框勾销选中的办法,学习了vue对对象中的属性动静赋值,学习了Object.keys()办法和Object.values()办法。 ...

September 11, 2022 · 2 min · jiezi

关于javascript:微信小程序获取图片的原始尺寸并且重新设置宽高

最近在开发一个性能,接口返回的图片如果高度大于以后手机屏幕的高度,就让图片能够滚动,否则就让图片撑满整个屏幕,并且禁止滚动。办法是wx.getImageInfo,微信官网文档获取一张图片宽高的代码: wx.getImageInfo({ src: this.data.info.imgUrl, complete: (res) => { // 原图的宽度 let imgWidth = res.width; // 原图的高度 let imgHeight = res.height; // 设施的宽度 let screenWidth = wx.getSystemInfoSync().windowWidth; // 设施的高度 let screenHeight = wx.getSystemInfoSync().windowHeight; // 750 2000 // 图片的宽度除以屏幕的宽度 let ratio2 = imgWidth / screenWidth; // 获取被渲染后的图片高度 let saleHight = (imgHeight / ratio2).toFixed(2); if (saleHight >= screenHeight) { this.setData({ ['info.width']: screenWidth + 'px', ['info.height']: saleHight + 'px', ['info.mode']: 'aspectFit', }); } else { this.setData({ ['info.width']: '100%', ['info.height']: '100%', ['info.mode']: 'aspectFill', }); } } })获取循环外面图片宽高的代码: ...

September 11, 2022 · 1 min · jiezi