首页 文章 精选 留言 我的

精选列表

搜索[前端工具],共10000篇文章
优秀的个人博客,低调大师

几道高级前端面试题解析

为什么 0.1 + 0.2 != 0.3,请详述理由 因为 JS 采用 IEEE 754 双精度版本(64位),并且只要采用 IEEE 754 的语言都有该问题。 我们都知道计算机表示十进制是采用二进制表示的,所以 0.1 在二进制表示为 // (0011) 表示循环 0.1 = 2^-4 * 1.10011(0011) 复制代码 那么如何得到这个二进制的呢,我们可以来演算下 小数算二进制和整数不同。乘法计算时,只计算小数位,整数位用作每一位的二进制,并且得到的第一位为最高位。所以我们得出 0.1 = 2^-4 * 1.10011(0011),那么 0.2 的演算也基本如上所示,只需要去掉第一步乘法,所以得出 0.2 = 2^-3 * 1.10011(0011)。 回来继续说 IEEE 754 双精度。六十四位中符号位占一位,整数位占十一位,其余五十二位都为小数位。因为 0.1 和 0.2 都是无限循环的二进制了,所以在小数位末尾处需要判断是否进位(就和十进制的四舍五入一样)。 所以 2^-4 * 1.10011...001 进位后就变成了 2^-4 * 1.10011(0011 * 12次)010 。那么把这两个二进制加起来会得出 2^-2 * 1.0011(0011 * 11次)0100 , 这个值算成十进制就是 0.30000000000000004 下面说一下原生解决办法,如下代码所示 parseFloat((0.1 + 0.2).toFixed(10)) 复制代码 10 个 Ajax 同时发起请求,全部返回展示结果,并且至多允许三次失败,说出设计思路 这个问题相信很多人会第一时间想到 Promise.all ,但是这个函数有一个局限在于如果失败一次就返回了,直接这样实现会有点问题,需要变通下。以下是两种实现思路 // 以下是不完整代码,着重于思路 非 Promise 写法 let successCount = 0 let errorCount = 0 let datas = [] ajax(url, (res) => { if (success) { success++ if (success + errorCount === 10) { console.log(datas) } else { datas.push(res.data) } } else { errorCount++ if (errorCount > 3) { // 失败次数大于3次就应该报错了 throw Error('失败三次') } } }) // Promise 写法 let errorCount = 0 let p = new Promise((resolve, reject) => { if (success) { resolve(res.data) } else { errorCount++ if (errorCount > 3) { // 失败次数大于3次就应该报错了 reject(error) } else { resolve(error) } } }) Promise.all([p]).then(v => { console.log(v); }); 复制代码 基于 Localstorage 设计一个 1M 的缓存系统,需要实现缓存淘汰机制 设计思路如下: 存储的每个对象需要添加两个属性:分别是过期时间和存储时间。 利用一个属性保存系统中目前所占空间大小,每次存储都增加该属性。当该属性值大于 1M 时,需要按照时间排序系统中的数据,删除一定量的数据保证能够存储下目前需要存储的数据。 每次取数据时,需要判断该缓存数据是否过期,如果过期就删除。 以下是代码实现,实现了思路,但是可能会存在 Bug,但是这种设计题一般是给出设计思路和部分代码,不会需要写出一个无问题的代码 class Store { constructor() { let store = localStorage.getItem('cache') if (!store) { store = { maxSize: 1024 * 1024, size: 0 } this.store = store } else { this.store = JSON.parse(store) } } set(key, value, expire) { this.store[key] = { date: Date.now(), expire, value } let size = this.sizeOf(JSON.stringify(this.store[key])) if (this.store.maxSize < size + this.store.size) { console.log('超了-----------'); var keys = Object.keys(this.store); // 时间排序 keys = keys.sort((a, b) => { let item1 = this.store[a], item2 = this.store[b]; return item2.date - item1.date; }); while (size + this.store.size > this.store.maxSize) { let index = keys[keys.length - 1] this.store.size -= this.sizeOf(JSON.stringify(this.store[index])) delete this.store[index] } } this.store.size += size localStorage.setItem('cache', JSON.stringify(this.store)) } get(key) { let d = this.store[key] if (!d) { console.log('找不到该属性'); return } if (d.expire > Date.now) { console.log('过期删除'); delete this.store[key] localStorage.setItem('cache', JSON.stringify(this.store)) } else { return d.value } } sizeOf(str, charset) { var total = 0, charCode, i, len; charset = charset ? charset.toLowerCase() : ''; if (charset === 'utf-16' || charset === 'utf16') { for (i = 0, len = str.length; i < len; i++) { charCode = str.charCodeAt(i); if (charCode <= 0xffff) { total += 2; } else { total += 4; } } } else { for (i = 0, len = str.length; i < len; i++) { charCode = str.charCodeAt(i); if (charCode <= 0x007f) { total += 1; } else if (charCode <= 0x07ff) { total += 2; } else if (charCode <= 0xffff) { total += 3; } else { total += 4; } } } return total; } } 复制代码 详细说明 Event loop 众所周知 JS 是门非阻塞单线程语言,因为在最初 JS 就是为了和浏览器交互而诞生的。如果 JS 是门多线程的语言话,我们在多个线程中处理 DOM 就可能会发生问题(一个线程中新加节点,另一个线程中删除节点),当然可以引入读写锁解决这个问题。 JS 在执行的过程中会产生执行环境,这些执行环境会被顺序的加入到执行栈中。如果遇到异步的代码,会被挂起并加入到 Task(有多种 task) 队列中。一旦执行栈为空,Event Loop 就会从 Task 队列中拿出需要执行的代码并放入执行栈中执行,所以本质上来说 JS 中的异步还是同步行为。 console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); console.log('script end'); 复制代码 以上代码虽然 setTimeout 延时为 0,其实还是异步。这是因为 HTML5 标准规定这个函数第二个参数不得小于 4 毫秒,不足会自动增加。所以 setTimeout 还是会在 script end 之后打印。 不同的任务源会被分配到不同的 Task 队列中,任务源可以分为 微任务(microtask) 和 宏任务(macrotask)。在 ES6 规范中,microtask 称为 jobs,macrotask 称为 task。 console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); new Promise((resolve) => { console.log('Promise') resolve() }).then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end'); // script start => Promise => script end => promise1 => promise2 => setTimeout 复制代码 以上代码虽然 setTimeout 写在 Promise 之前,但是因为 Promise 属于微任务而 setTimeout 属于宏任务,所以会有以上的打印。 微任务包括 process.nextTick ,promise ,Object.observe ,MutationObserver 宏任务包括 script , setTimeout ,setInterval ,setImmediate ,I/O ,UI rendering 很多人有个误区,认为微任务快于宏任务,其实是错误的。因为宏任务中包括了 script ,浏览器会先执行一个宏任务,接下来有异步代码的话就先执行微任务。 所以正确的一次 Event loop 顺序是这样的 执行同步代码,这属于宏任务 执行栈为空,查询是否有微任务需要执行 执行所有微任务 必要的话渲染 UI 然后开始下一轮 Event loop,执行宏任务中的异步代码 通过上述的 Event loop 顺序可知,如果宏任务中的异步代码有大量的计算并且需要操作 DOM 的话,为了更快的 界面响应,我们可以把操作 DOM 放入微任务中。 Node 中的 Event loop Node 中的 Event loop 和浏览器中的不相同。 Node 的 Event loop 分为6个阶段,它们会按照顺序反复运行 ┌───────────────────────┐ ┌─>│ timers │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ I/O callbacks │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ idle, prepare │ │ └──────────┬────────────┘ ┌───────────────┐ │ ┌──────────┴────────────┐ │ incoming: │ │ │ poll │<──connections─── │ │ └──────────┬────────────┘ │ data, etc. │ │ ┌──────────┴────────────┐ └───────────────┘ │ │ check │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ └──┤ close callbacks │ └───────────────────────┘ 复制代码 timer timers 阶段会执行 setTimeout 和 setInterval 一个 timer 指定的时间并不是准确时间,而是在达到这个时间后尽快执行回调,可能会因为系统正在执行别的事务而延迟。 下限的时间有一个范围:[1, 2147483647] ,如果设定的时间不在这个范围,将被设置为1。 I/O I/O 阶段会执行除了 close 事件,定时器和 setImmediate 的回调 idle, prepare idle, prepare 阶段内部实现 poll poll 阶段很重要,这一阶段中,系统会做两件事情 执行到点的定时器 执行 poll 队列中的事件 并且当 poll 中没有定时器的情况下,会发现以下两件事情 如果 poll 队列不为空,会遍历回调队列并同步执行,直到队列为空或者系统限制 如果 poll 队列为空,会有两件事发生 如果有 setImmediate 需要执行,poll 阶段会停止并且进入到 check 阶段执行 setImmediate 如果没有 setImmediate 需要执行,会等待回调被加入到队列中并立即执行回调 如果有别的定时器需要被执行,会回到 timer 阶段执行回调。 check check 阶段执行 setImmediate close callbacks close callbacks 阶段执行 close 事件 并且在 Node 中,有些情况下的定时器执行顺序是随机的 setTimeout(() => { console.log('setTimeout'); }, 0); setImmediate(() => { console.log('setImmediate'); }) // 这里可能会输出 setTimeout,setImmediate // 可能也会相反的输出,这取决于性能 // 因为可能进入 event loop 用了不到 1 毫秒,这时候会执行 setImmediate // 否则会执行 setTimeout 复制代码 当然在这种情况下,执行顺序是相同的 var fs = require('fs') fs.readFile(__filename, () => { setTimeout(() => { console.log('timeout'); }, 0); setImmediate(() => { console.log('immediate'); }); }); // 因为 readFile 的回调在 poll 中执行 // 发现有 setImmediate ,所以会立即跳到 check 阶段执行回调 // 再去 timer 阶段执行 setTimeout // 所以以上输出一定是 setImmediate,setTimeout 复制代码 上面介绍的都是 macrotask 的执行情况,microtask 会在以上每个阶段完成后立即执行。 setTimeout(()=>{ console.log('timer1') Promise.resolve().then(function() { console.log('promise1') }) }, 0) setTimeout(()=>{ console.log('timer2') Promise.resolve().then(function() { console.log('promise2') }) }, 0) // 以上代码在浏览器和 node 中打印情况是不同的 // 浏览器中打印 timer1, promise1, timer2, promise2 // node 中打印 timer1, timer2, promise1, promise2 复制代码 Node 中的 process.nextTick 会先于其他 microtask 执行。 setTimeout(() => { console.log("timer1"); Promise.resolve().then(function() { console.log("promise1"); }); }, 0); process.nextTick(() => { console.log("nextTick"); }); // nextTick, timer1, promise1 1.如果觉得这篇文章还不错,来个分享、点赞吧,让更多的人也看到 如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star: http://github.crmeb.net/u/defu 不胜感激 ! 来自 “开源世界 ” ,链接: https://ym.baisou.ltd/post/754.html ,如需转载,请注明出处,否则将追究法律责任。

优秀的个人博客,低调大师

前端 JavaScript 中 JSON.stringify() 的基本用法

前言 在开发工作中,我们可能会碰到这样的需求:需要将某个对象内容弹窗显示或者保存在文件中,这时候如果你直接弹窗的话,很可能就是下面这样的: 因为很多接口它对参数有要求,比如只能是字符串之类的。 这时候,就需要我们将对象转换为字符串进行输出,JSON.stringify() 方法就可以帮我们实现将对象转为字符串的过程。 方法描述 JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。 语法 JSON.stringify(value[, replacer [, space]]) 参数说明: value 将要序列化成 一个 JSON 字符串的值。 replacer(可选) 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理; 如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中; 如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。 space(可选) 指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。 如果省略space,则将生成返回值文本,而没有任何额外空格。 如果 space是一个数字,则返回值文本在每个级别缩进指定数目的空格。 如果 space 大于 10,则文本缩进 10 个空格。 如果 space是一个非空字符串(例如“\t”),则返回值文本在每个级别中缩进字符串中的字符。 如果 space 是长度大于 10个字符的字符串,则使用前 10 个字符。 返回值 一个表示给定值的JSON字符串。 常规用法 console.log(JSON.stringify({name: "obj"})) // '{"name": "obj"}' repalacer 参数 replacer 参数可以是一个函数或者一个数组。作为函数,它有两个参数,键(key)和值(value),它们都会被序列化。 在开始时, replacer 函数会被传入一个空字符串作为 key 值,代表着要被 stringify 的这个对象。随后每个对象或数组上的属性会被依次传入。 函数应当返回JSON字符串中的value, 如下所示: 如果返回一个 Number,转换成相应的字符串作为属性值被添加入 JSON 字符串。 如果返回一个 String,该字符串作为属性值被添加入 JSON 字符串。 如果返回一个 Boolean, "true" 或者 "false" 作为属性值被添加入 JSON 字符串。 如果返回任何其他对象,该对象递归地序列化成 JSON 字符串,对每个属性调用 replacer 方法。除非该对象是一个函数,这种情况将不会被序列化成 JSON 字符串。 如果返回 undefined,该属性值不会在 JSON 字符串中输出。 有以下对象: const data = [ { name: "person1", sex: 0, age: 18, isStudent: true }, { name: "person2", sex: 1, age: 25, isStudent: false }, { name: "person3", sex: 0, age: 15, isStudent: true } ] 接下来我们针对这个对象做各种需求实现。 只输出姓名和性别 const res = JSON.stringify(data, ["name", "sex"]) console.log(res); // `[{"name":"person1","sex":0},{"name":"person2","sex":1},{"name":"person3","sex":0}]` JSON.stringify() 提供了分离出自己需要的那部分数据。 将性别转为中文字符 const res = JSON.stringify(data, (key, value) => { if (key == 'sex') { return ["女", '男'][value]; } return value; }) console.log(res); // `[{"name":"person1","sex":"女","age":18,"isStudent":true},{"name":"person2","sex":"男","age":25,"isStudent":false},{"name":"person3","sex":"女","age":15,"isStudent":true}]` JSON.stringify() 提供了回调函数做一个映射关系。 space 参数 const res = JSON.stringify(data, ["name", "sex"],4) console.log(res); 输出如下: 这里使用了 4 个空格作为层级缩进。 注意:使用 “\t” 得到的结果和使用 4 个空格得到的结果看起来很像,但实际不是一回事。 总结 JSON.stringify() 方法可以通过参数控制输出的数据和格式,灵活应用它会大大提高我们的工作效率。 学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂! 我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教! 你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠! 知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

优秀的个人博客,低调大师

前端 JavaScript 之『防抖』的简单代码实现

## 前戏 经过上一篇文章的总结,我们知道:短时间内高频率地触发事件,可能会导致不良后果。 具体到我们开发界来说,如果数据一致处于一种高频率更新的状态,那么可能会引发的问题如下: - 前后端数据交互频率过高,导致流量浪费。 - 界面高频率渲染更新,引发页面延迟、卡顿或假死等状况,影响体验。 在进入正题之前,我们先来看下面这个例子: ```html 名称 输入 ``` ```javascript window.onload = () => { const inputEle = document.querySelector("#name"); const resEle = document.querySelector("#res"); inputEle.addEventListener("input", function (event) { console.log(this.value); resEle.value += `\n${ this.value }` }); } ``` ![频繁触发](https://gitee.com/yinyiwang/blogImages/raw/master/images/20210617%20/18-04-32-ppAL3g.gif) 在输入框的 input 事件中,将该输入框的当前值输出在多行文本框中。可以看到,每输入一个拼音字母,都会有一条输出记录,触发频率取决于人的打字速度。 ## 新需求 假如,现在有这么一个新需求,要我们在 input 事件中加入新的逻辑:将输入框的当前值发往后台进行存储。 可以想象,这种情况下的前后端交互频率该有多高,其中很多数据都是没有必要即刻发送保存的,纯属浪费流量。 我们可以考虑对这个需求进行一下优化,只要控制一下交互频率就好,主要有以下两个方向: - 每隔几秒发送一次数据 —— 节流 - 每当用户停止输入之后,开始计时,一定时间后发送一次数据 —— 防抖 ## 实现防抖 首先,我们从防抖的方向进行实现:只有当用户停止输入一段时间后,才会将输入内容输出在多行文本框中。 ```javascript window.onload = () => { const resEle = document.querySelector("#res"); function changeOutputVal(value) { resEle.value += `\n${ value }`; } function debounce(fn, delay = 1000) { let timer = null; return function (...args) { console.log(args); if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(() => { fn.apply(this, args); }, delay); } } const outputRes = debounce(changeOutputVal, 1000); const inputEle = document.querySelector("#name"); inputEle.addEventListener("input", (eve) => { outputRes(eve.target.value); }); } ``` 代码说明: 1. 每一次事件被触发,都会清除当前的 timer 然后重新设置超时调用,即重新计时。 这就会导致每一次高频事件都会取消前一次的超时调用,导致事件处理程序不能被触发; 2. 只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行。 运行效果如下: ![](https://gitee.com/yinyiwang/blogImages/raw/master/images/20210617%20/20-29-25-R4l3jg.gif) 可以看到,在加入防抖代码之后,input 事件并不会每次输入都会输出在多行文本,而是会在用户停止输入 delay 时间之后触发输出,频率确实低了很多。从某种程度上来说,的确优化了页面显示效果,给人的视觉感受比较舒服。 ## 总结 巧用防抖函数的,既可以优化性能,又能优化显示效果,一举两得。 ~ ~ 代码比较粗糙,也比较基础,后面会逐步向着复杂的方向迭代,望各位看官海涵 ~ ~ ~ 本文完 > 学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂! > > 大家好!我是〖编程三昧〗的作者 **隐逸王**,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教! > > 知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬! ![mianshi](https://gitee.com/yinyiwang/blogImages/raw/master/images/20210616%20/20-45-17-6ya6Kf.jpg)

优秀的个人博客,低调大师

前端 CSS 变量简介及基本使用方法

背景 复杂的网站都会有大量的CSS代码,通常也会有许多重复的值。 举个例子,同样一个颜色值可能在成千上百个地方被使用到,如果这个值发生了变化,需要全局搜索并且一个一个替换,效率不高且容易出错。 自定义属性在某个地方存储一个值,然后在其他许多地方引用它。另一个好处是语义化的标识。比如,--main-text-color 会比 #00ff00 更易理解,尤其是这个颜色值在其他上下文中也被使用到。 概念 自定义属性(有时候也被称作CSS变量或者级联变量)是由CSS作者定义的,它包含的值可以在整个文档中重复使用。 由自定义属性标记设定值(比如: --main-color: black;),由 var() 函数来获取值(比如: color: **var(--main-color)**;)。 优势 在构建大型站点时,作者通常会面对可维护性的挑战。在这些网页中,所使用的CSS 的数量是非常庞大的,并且在许多场合大量的信息会重复使用。 例如,在网页中维护一个配色方案,意味着一些颜色在 CSS 文件中多次出现,并被重复使用。当你修改配色方案时,不论是调整某个颜色或完全修改整个配色,都会成为一个复杂的问题,不容出错,而单纯查找替换是远远不够的。 如果使用了CSS 框架,这种情况会变得尤其糟糕,此时如果要修改颜色,则需要对框架本身进行修改。 在这些场合使用 LESS 或 Sass 类似的预处理器是非常有帮助的,但是这种通过添加额外步骤的方式,可能会增加系统的复杂性。 CSS变量为我们带来一些预处理器的便利,并且不需要额外的编译。 这些变量的第二个优势就是名称本身就包含了语义的信息。CSS 文件变得易读和理解。main-text-color比文档中的#00ff00更容易理解,特别是同样的颜色出现在不同的文件中的时候。 用法 下面是 CSS 变量的使用方法和步骤。 CSS 中声明变量 我们都知道,在 JS 中要使用一个变量前,必须声明这个表变量。在 CSS 中也是一样的道理。 声明一个自定义属性,属性名需要以两个减号(--)开始,属性值则可以是任何有效的CSS值。和其他属性一样,自定义属性也是写在规则集之内的,如下: body { --bg-color: #7F583F; --color: #F7EFD2; } 上面代码中,body选择器里面声明了两个变量:--bg-color和--color。 它们与color、font-size等正式属性没有什么不同,只是没有默认含义。所以 CSS 变量(CSS variable)又叫做**"CSS 自定义属性"**(CSS custom properties)。 规则集所指定的选择器定义了自定义属性的可见作用域。通常的最佳实践是定义在根伪类 :root下,这样就可以在HTML文档的任何地方访问到它了: :root { --main-bg-color: #eee; } 自定义属性名是大小写敏感的,--my-color 和 --My-color 会被认为是两个不同的自定义属性。 CSS 中使用变量 通过var()函数来读取变量。语法如下: var(custom-property-name, value) name (必需) 变量名(以两条破折号开头)。 value (可选) 表示变量的默认值。如果该变量不存在,就会使用这个默认值。 变量名称必须以两个破折号(--)开头,且区分大小写! 使用方法: element { background-color: var(--main-bg-color); } 变量也可以使用在变量声明中: :root { --primary-color: #eee; --primary-bg-color: var(--main-bg-color); } 变量值只能用作属性值,不能用作属性名。 JS 操作 CSS 变量 在 JS 代码中,我们可能需要读取 CSS 变量的值,其方法如下: const root = document.querySelector(":root"); // 设置 CSS 变量 root.style.setProperty("--main-bg-color", "red"); // 读取 CSS 变量 const computedStyle = getComputedStyle(root); const mainBgColor = computedStyle.getPropertyValue("--main-bg-color"); console.log(mainBgColor); // 删除 CSS 变量 root.style.removeProperty("--main-bg-color"); 总结 以上就是关于 CSS 变量的一些基本概念及使用方法,更多详情待后续! 灵活使用 CSS 变量,不仅可以提高生产力,也能够提高代码的可阅读性和维护性。 ~ ~ ~ 本文完 学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂! 大家好!我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教! 知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

优秀的个人博客,低调大师

layui 2.6.8 发布,原生态前端 UI 框架

更新日志: # 2.6.8 [重写] sort 方法,以便对数字、非数字及混合类等所有内容的排序进行支持 [新增] dropdown 组件的 align 参数,用于控制下拉菜单水平对齐方式(支持 left、center、right) [新增] table 组件的 escape 参数,用于是否开启 xss 字符过滤(默认 false) [加强] table 组件的自定义模板功能,返回 LAY_COL 字段,可得到当前列的表头配置信息 [加强] form 组件对验证不通过的表单项自动定位到可视区域,不再是只对输入框自动获焦定位 #I3O5TC [加强] form 组件对 url 的验证 [修复] form 相关 css 的 layui-checkbox-disabled 书写错误(之前为 disbaled) #I1NGDC [修复] form 组件的 select option 内容出现换行时的样式异常问题 #I3T5ZC [修复] colorpicker 颜色选择组件在 Firefox 下选择颜色时的若干兼容问题 #I3POP2 [加强] colorpicker 组件的坐标定位计算方式 [修复] 低版本 ie 若干报错问题 该版本是 2.6.x的一个收尾版,基本很稳定,推荐官网下载升级(www.layui.com)。 那么下一个版本 2.7也将会开启另外一个篇章

优秀的个人博客,低调大师

Angular 12.0.0-rc.2 发布,Web 前端框架

Angular 12.0.0-rc.0现已发布,具体更新内容如下: Bug Fixes animations:确保过渡命名空间顺序一致(#19854)(01cc995) common:为具有 HttpClient request body 的布尔值添加正确的 ContentType(#38924)(#41885)(922a602) compiler-cli:将 linker作为 Babel 插件公开(#41918)(8fdac8f) compiler-cli:在 reference emitters 中更倾向于 non-aliased exports(#41866)(75bb931),closes#41443#41277 core:AsyncPipe 现在与 RxJS 7 兼容(#41590)(9759bca) core:使用表达式绑定处理多个 i18n 属性(#41882)(73c6c64),closes#41869 localize:将丢失目标的错误放宽为警告(#41944)(35ceed2),closes#21690 性能改进 core:对监听器指令的较小改进(#41807)(9346d61) 更新说明:https://github.com/angular/angular/blob/master/CHANGELOG.md

优秀的个人博客,低调大师

Angular 12.0.0-rc.0 发布,Web 前端框架

Angular 12.0.0-rc.0现已发布,具体更新内容如下: Bug Fixes animations:允许 shadow DOM 中的元素有动画(#40134)(dad42c8),closes#25672 common:viewport scroller 无法找到 shadow DOM 内的元素(#41644)(c0f5ba3),closes#41470 compiler:non-literal的内联模板在部分编译中处理不正确(#41583)(ab257b3) compiler:不为备用命名空间内的 ng-template 生成更新指令(#41669)(2bcbbda),closes#41308 compiler-cli:模板中的 autocomplete literal 类型(#41456)(#41645)(8b2b5ef) compiler-cli:如果组件没有内联样式,则在预置时不会出错(#41602)(a5fe8b9) router:只有当 reuse strategy表明它应该重新连接时,才会检索存储的路由(#30263)(a4ff071),closes#23162 router:递归合并空路径匹配(#41584)(1179dc8),closes#23162 性能改进 compiler:减少生成的安全访问和无效合并的代码量(#41563)(9a3b82f),closes#41437#41491 详情可查看:https://github.com/angular/angular/blob/master/CHANGELOG.md

优秀的个人博客,低调大师

Angular 11.1.0-next.2 发布,Web 前端框架

Angular 11.1.0-next.2现已发布,具体更新内容如下: Bug 修复 animations:在浏览器动画生成器中实现 getPosition compiler-cli:即使导入断开也能纠正incremental behavior compiler-cli:删除错误特征的概念 compiler-cli:使用 flag 跟踪poisoned scopes core:当 root view 被删除时,从可测试性注册表中删除应用程序 core:支持扩展与 root NgModule 不同 core:当 root view 被删除时,取消订阅 onError language-service:不返回不存在的外部模板 language-service:不要把 file URIs 当作一般的 URL 来处理 service-worker:使用 ErrorHandler 处理错误 upgrade:删除降级的组件时,避免内存泄漏 特性 compiler:允许在数组文字中使用逗号 compiler:在代码生成器中支持带标签的模板文字 language-service:为 lvy integrated LS 添加“find references”功能 language-service:为全局属性实现自动补全(Ivy) 更多详情可查看:https://github.com/angular/angular/blob/master/CHANGELOG.md#1110-next2-2020-12-09

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册