关于前端:Vue组件通信方式一文搞懂

本文整顿总结了开发中应用频率比拟多的vue组件通信形式,置信无论是面试还是理论开发,总会对你有所帮忙。 Props & $emit这是应用频率最多、最根底,必须要把握的用法,应用非常简单,用一个helloworld组件示例。 <div id="app"> <HelloWorld msg="Welcome to Your Vue.js App"/> </div><template> <div class="hello"> <h1>{{ msg }}</h1> </div></template>export default { name: 'HelloWorld', props: { msg: String }}数据从父级传递到子级,子级组件读取应用,子级不举荐间接在外部批改props(会导致渲染异样、监听错乱),而应该告诉父组件去更新msg。 <template> <div class="hello"> <h1>{{ msg }}</h1> <button @click="resetMsg">i want change msg</button> </div></template>export default { name: 'HelloWorld', props: { msg: String }, methods: { resetMsg () { this.$emit('update'); } }}父组件: <template> <div id="app"> <HelloWorld :msg="msg" @update="update" /> </div></template>methods: { update () { this.msg = "Welcome to my Blog"; } }$attrs & $listenners父组件不变,子组件用过$attrs在模板和JS中应用父组件提供的数据,应用$listenners执行父组件内办法(也能够用于跨级组件)。 ...

August 17, 2023 · 2 min · jiezi

关于前端:Spartacus-添加-PWA-应用到-home-的实现原理分析

代码地位:https://github.com/SAP/spartacus/blob/develop-6.4.x/projects/storefrontlib/cms-structure/pwa/services/add-to-home-screen.service.ts 这段Angular代码是一个用于增加到主屏幕(Add to Home Screen)性能的服务,它是为Spartacus我的项目中的PWA模块设计的。PWA代表Progressive Web App,是一种联合了网页和本地利用个性的Web应用程序。 该代码位于一个名为AddToHomeScreenService的可注入(Injectable)类中,该类提供了一系列性能来治理“增加到主屏幕”性能。上面将具体解释代码的各个局部及其性能。 模块导入和依赖注入: 通过import语句,引入了必要的Angular模块和Spartacus模块,包含@angular/core和@spartacus/core等。在类的构造函数中,通过依赖注入取得了PWAModuleConfig、GlobalMessageService和WindowRef等实例,这些将在后续代码中应用。AddToHomeScreenService类定义: 通过@Injectable装璜器,将这个类标记为一个可注入的服务,能够在整个利用中应用。定义了一个受爱护的成员变量deferredEvent,用于存储beforeinstallprompt事件对象。定义了一个canPrompt的BehaviorSubject,用于跟踪是否能够提醒用户增加到主屏幕。申明了一个canPrompt$的Observable,提供了对canPrompt状态的订阅。构造函数: 构造函数承受PWAModuleConfig、GlobalMessageService和WindowRef等依赖。在构造函数外部,如果配置中启用了addToHomeScreen性能(通过this.config.pwa?.addToHomeScreen的判断),则调用init()办法。init()办法: 在初始化办法中,通过this.winRef.nativeWindow判断浏览器是否提供了nativeWindow对象。如果提供了,通过addEventListener绑定了beforeinstallprompt和appinstalled事件的处理函数。beforeinstallprompt事件处理函数阻止了默认行为,并将事件对象存储到deferredEvent中,而后调用enableAddToHomeScreen()办法。appinstalled事件处理函数会在应用程序被胜利装置后触发,显示确认音讯后,调用disableAddToHomeScreen()办法将canPrompt设置为false,并将deferredEvent重置为null。其余办法: enableAddToHomeScreen()办法将canPrompt的值设置为true,示意能够提醒用户增加到主屏幕。disableAddToHomeScreen()办法将canPrompt的值设置为false,示意不再提醒用户增加到主屏幕。firePrompt()办法会查看deferredEvent是否存在,如果存在,则调用prompt()办法来触发“增加到主屏幕”的提醒。这段代码是 Angular 服务,名称为 AddToHomeScreenService,次要用于解决 PWA(Progressive Web App)的增加到主屏幕的性能。PWA 是一种能够像原生应用程序一样在用户的设施上装置和运行的网页应用程序。 首先,服务在根注入器中提供,这意味着这个服务在应用程序的整个生命周期中是单例的。它依赖于 PWAModuleConfig,GlobalMessageService 和 WindowRef。PWAModuleConfig 仿佛是用于配置 PWA 模块的服务;GlobalMessageService 用于全局音讯告诉;WindowRef 是对全局 window 对象的援用,以便进行跨浏览器的兼容解决。 这个服务中有一个名为 canPrompt 的 BehaviorSubject,它是一个能够发送和接收数据的对象,用于存储以后是否能够提醒用户增加利用到主屏幕。同时提供了一个名为 canPrompt$ 的 Observable,其余组件能够订阅这个 Observable 来获知是否能够提醒用户增加利用到主屏幕。 在服务的 constructor 构造函数中,查看了 PWAModuleConfig 中的 pwa.addToHomeScreen 配置。如果此配置为真,服务将初始化其性能。 在初始化函数 init 中,服务监听了两个全局事件:beforeinstallprompt 和 appinstalled。beforeinstallprompt 事件是在用户能够被提醒增加利用到主屏幕之前触发的。当这个事件产生时,服务会阻止事件的默认行为,存储事件对象以便稍后触发,而后调用 enableAddToHomeScreen 函数来容许提醒用户。appinstalled 事件在用户将利用增加到主屏幕后触发。当这个事件产生时,服务会发送一条全局音讯告诉用户利用曾经被增加到主屏幕,而后调用 disableAddToHomeScreen 函数禁止进一步的提醒,并革除存储的事件对象。 服务还提供了 firePrompt 函数,这个函数会触发存储的 beforeinstallprompt 事件的 prompt 办法,这将显示向用户增加利用到主屏幕的提醒。

August 17, 2023 · 1 min · jiezi

关于前端:关于-beforeinstallprompt-事件

当浏览器检测到网站能够作为渐进式 Web 利用程序安装时,会触发 beforeinstallprompt 事件。 没有保障触发此事件的工夫,但它通常产生在页面加载时。 此事件的典型用处是,当 Web 应用程序想要提供本人的应用程序内 UI 邀请用户装置该应用程序时,而不是浏览器提供的通用 UI 时。 这使应用程序可能提供无关应用程序的更多上下文,向用户解释为什么他们可能想要装置它。 在这种状况下,该事件的处理程序将: 保留对传入其中的 BeforeInstallPromptEvent 对象的援用显示其利用内装置 UI(默认状况下应暗藏,因为并非所有浏览器都反对装置)。当用户应用利用内装置界面装置利用时,利用内装置界面会调用保留的BeforeInstallPromptEvent对象的prompt()办法来显示装置提醒。 例如,开发人员可能不心愿在用户首次拜访站点时立刻显示装置提醒。应用 beforeinstallprompt 事件,开发人员能够阻止浏览器的默认装置提醒,而后在更适合的工夫(例如用户实现了某些交互后)再显示提醒。 上面是一个简略的 beforeinstallprompt 示例: let deferredPrompt;window.addEventListener('beforeinstallprompt', (e) => { // 阻止 Chrome 67 及更早版本主动显示提醒 e.preventDefault(); // 保留事件以便稍后应用 deferredPrompt = e; // 更新 UI 以告诉用户能够增加到主屏幕 addBtn.style.display = 'block';});addBtn.addEventListener('click', (e) => { // 暗藏咱们的用户界面,显示装置提醒 addBtn.style.display = 'none'; // 显示之前保留的提醒 deferredPrompt.prompt(); // 期待用户的响应以决定是否装置应用程序 deferredPrompt.userChoice.then((choiceResult) => { if (choiceResult.outcome === 'accepted') { console.log('用户承受了装置提醒'); } else { console.log('用户回绝了装置提醒'); } deferredPrompt = null; });});在这个例子中,咱们首先在全局作用域中定义了一个变量 deferredPrompt 以保留 beforeinstallprompt 事件。当 beforeinstallprompt 事件触发时,咱们阻止了默认的装置提醒,并将事件保留在 deferredPrompt 中。此外,咱们还更新了用户界面,通知用户他们能够装置 Web 应用程序。 ...

August 17, 2023 · 1 min · jiezi

关于前端:关于-PWA-应用的可安装性

PWA 的一个定义特色是它能够被装置在原生挪动设施上,而后对用户来说就像是一个平台的原生应用程序,是其设施的 permanent 性能。用户能够像启动任何其余应用程序一样,间接从挪动操作系统中启动它。 咱们能够这样概括: PWA 能够从平台的利用商店装置,或者间接从网页装置。PWA 能够像平台特定的利用一样装置,并能够自定义装置过程。一旦装置,PWA就会在设施上取得一个利用图标,与平台特定的利用并列。 一旦装置,PWA能够作为一个独立的利用启动,而不是在浏览器中的一个网站。 首先,咱们将探讨一个web利用必须满足的可安装性要求。 可安装性为了让一个 web 利用可装置,它须要满足一些技术要求。咱们能够将这些看作是一个web利用成为 PWA 的最低要求。 web app manifestWeb 利用程序清单是一个 JSON 文件,它通知浏览器 PWA 在设施上应如何显示和运行。 对于要成为 PWA 的 Web 应用程序,它必须是可装置的,并且要使其可装置,它必须蕴含清单。 manifest.json 文件通过 link 标签被引入 index.html: <!doctype html><html lang="en"> <head> <link rel="manifest" href="manifest.json" /> <!-- ... --> </head> <body></body></html>清单蕴含一个蕴含成员汇合的 JSON 对象,每个成员都定义 PWA 外观或行为的某些方面。 上面这是一个相当简略的清单,仅蕴含两个成员:“name”和“icons”。 { "name": "My PWA", "icons": [ { "src": "icons/512.png", "type": "image/png", "sizes": "512x512" } ]}对于可装置的 Web 应用程序,它必须蕴含一个带有 fetch 事件处理程序的 Service Worker,以提供根本的离线体验。 ...

August 17, 2023 · 1 min · jiezi

关于前端:Angular-应用启用-PWA-特性的-Angular-CLI-命令行

ng add @angular/pwa --project <project-name> 这条命令在 Angular CLI 中,是用于将一个规范的 Angular 应用程序转化为一个渐进式网页利用(PWA,Progressive Web App)的命令。 首先,咱们须要了解 PWA 是什么。PWA 是一种能够提供相似于原生利用体验的网页利用。它能够在离线时工作,可被用户增加到主屏幕,可能自动更新,并且可能发送推送告诉。PWA 的指标是利用古代浏览器的全副性能,同时放弃用户体验和应用程序性能的最优。 ng add @angular/pwa --project <project-name> 命令的具体解析如下: ng 是 Angular CLI 的命令行接口,咱们通过它来创立我的项目、生成代码和执行各种开发工作,如测试、打包和部署。add 是 Angular CLI 的一个命令,它用于增加和配置 Angular 库或者第三方库到你的我的项目中。@angular/pwa 是 Angular 团队提供的一套库,用于帮忙开发者将 Angular 应用程序转化为 PWA。--project 是一个选项,用于指定要增加 PWA 反对的我的项目的名称。在一个 Angular 工作空间中,可能会有多个我的项目,这个选项让咱们能够抉择一个特定的我的项目来增加 PWA 反对。这个命令会做什么呢? 它会增加 @angular/service-worker 包到你的我的项目中。Service Worker 是使 PWA 可能的关键技术,它运行在浏览器的后盾,独立于网页,为利用提供离线性能和资源缓存。在 angular.json 文件中,会主动配置 @angular/service-worker。特地是在 "build" 配置的 "configurations" 局部,会增加一个 "production" 配置,这个配置会在生产环境构建中蕴含 Service Worker。会在利用源代码的根目录下创立一个 ngsw-config.json 文件,这是 Service Worker 的配置文件。你能够在这个文件中配置哪些文件应该被 Service Worker 缓存,以及如何缓存。在 src/app/app.module.ts 文件中,会主动导入 ServiceWorkerModule,并在 imports 数组中增加 ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })。这段代码会在生产环境中注册 Service Worker。会在 src 目录下创立一个 manifest.webmanifest 文件,这是 PWA 的一个重要组成部分,它是一个 JSON 文件,定义了利用的名称、图标、URL、背景色彩、展现形式等信息,使得 PWA 能够被增加到用户的主屏幕,并以全屏形式运行,看起来更像一个原生利用。当波及到古代前端开发和构建简单的 Web 利用时,Angular 是一个备受欢送的框架之一。它提供了一种弱小的形式来构建可扩大、模块化和高性能的单页面利用(SPA)。然而,为了简化开发流程,Angular 团队创立了一个称为 "Angular CLI" 的工具,它是一个命令行界面,能够帮忙开发人员创立、构建和治理 Angular 我的项目。在这个背景下,让咱们深入探讨你提供的这行命令: ...

August 17, 2023 · 1 min · jiezi

关于前端:PWA-应用-addToHomeScreen-功能概述

PWA,全称为 Progressive Web App,即渐进式网页利用。它是一种将网页利用和原生利用相结合的新型利用模式,可能在用户没有装置利用的状况下,提供和原生利用类似的用户体验。在 PWA 中,addToHomeScreen 是一个十分重要的性能。它容许用户将 PWA 利用增加到设施的主屏幕上,就像增加一个原生利用的快捷方式一样。 addToHomeScreen 性能的外围在于提供一个更间接、更便捷的利用拜访形式,用户无需关上浏览器,间接从主屏幕点击图标,就能够关上并应用 PWA 利用。这大大提高了利用的可拜访性和用户体验。 举例来说,假如咱们有一个新闻浏览的 PWA 利用。当用户第一次拜访这个利用的时候,浏览器会通过 beforeinstallprompt 事件提醒用户将利用增加到主屏幕。代码如下: let deferredPrompt;window.addEventListener(`beforeinstallprompt`, (e) => { // 阻止 Chrome 67 及更早版本主动显示提醒 e.preventDefault(); // 将事件援用保留下来,以便稍后应用 deferredPrompt = e; // 更新界面,显示出一个 `增加到主屏幕` 的按钮 btnAdd.style.display = `block`;});在这段代码中,咱们首先定义了一个 deferredPrompt 变量,用来保留 beforeinstallprompt 事件。而后监听 beforeinstallprompt 事件,在事件被触发时阻止浏览器默认的提醒行为,并将事件保留到 deferredPrompt 中,最初显示一个 增加到主屏幕 的按钮。 当用户点击 增加到主屏幕 的按钮时,咱们能够通过调用 deferredPrompt.prompt() 办法来显示增加到主屏幕的提醒。代码如下: btnAdd.addEventListener(`click`, (e) => { // 暗藏咱们本人的 UI btnAdd.style.display = `none`; // 触发提醒 deferredPrompt.prompt(); // 期待用户的响应 deferredPrompt.userChoice.then((choiceResult) => { if (choiceResult.outcome === `accepted`) { console.log(`用户承受了 A2HS 提醒`); } else { console.log(`用户回绝了 A2HS 提醒`); } deferredPrompt = null; });});在这段代码中,咱们首先暗藏 增加到主屏幕 的按钮,而后调用 deferredPrompt.prompt() 来显示提醒。而后,咱们能够通过 deferredPrompt.userChoice 来获取用户的响应。如果用户承受了增加到主屏幕的提醒,咱们就能够做一些后续的操作,比方显示一个感激音讯。如果用户回绝了,咱们也能够做一些相应的解决,比方在一段时间后再次显示提醒。 ...

August 17, 2023 · 1 min · jiezi

关于前端:什么是电商解决方案的-Composable-特性

电商网站解决方案中的 "composable" 个性,或者叫 "组合性" 个性,是指电商平台的各种服务、性能和模块能够自由组合,以满足不同的业务需要。这种设计理念在古代电商平台的架构设计中失去了宽泛的利用和实际。 "组合性" 的长处是不言而喻的。首先,它能够进步零碎的灵活性和可扩展性。通过组合不同的服务和模块,电商平台能够疾速地适应和满足各种不同的业务需要。其次,它能够进步零碎的稳定性和可靠性。每个服务或模块都是独立的,因而在呈现故障时,能够疾速定位和解决问题,而不会影响到整个零碎的运行。最初,它能够进步零碎的效率。通过重用曾经存在的服务和模块,能够防止反复的开发工作,从而节俭开发工夫和老本。 上面,咱们来看一个具体的例子,以进一步了解 "组合性" 个性在电商网站解决方案中的利用。 假如咱们正在构建一个电商平台,这个平台须要提供商品展现、搜寻、购物车、领取和物流跟踪等性能。在传统的设计办法中,咱们可能会为每一个性能开发一个独自的零碎或利用,而后通过接口或数据交换来实现它们之间的互动。这样的设计尽管能够满足根本的需要,然而在扩展性、稳定性和效率上存在一些问题。 然而,如果咱们采纳 "组合性" 的设计办法,就能够很好地解决这些问题。在这种办法中,咱们会将这些性能合成为一组独立的服务或模块,例如商品服务、搜寻服务、购物车服务、领取服务和物流服务。这些服务或模块都是独立的,能够独自运行和保护,也能够与其余服务或模块组合在一起,以提供更简单的性能。 例如,当一个用户在电商平台上搜寻一个商品时,搜寻服务会与商品服务互动,以获取和显示商品信息。当用户将商品增加到购物车时,购物车服务会与商品服务和领取服务互动,以计算商品的总价和领取信息。当用户实现领取后,领取服务会与物流服务互动,以安顿商品的配送和跟踪。 通过这种形式,咱们能够轻松地增加、批改或删除任何一个服务或模块,而不会影响到其余的服务或模块。这使得咱们的电商平台变得更灵便、更稳固,也更易于保护和扩大。

August 17, 2023 · 1 min · jiezi

关于前端:SAP-CRM-One-Order-锁定模式用的是-Exclusive-Lock

在 SAP CRM WebClient UI 上点击 Edit 按钮后, 界面进入可编辑状态: 后盾 SM12 事务码察看到锁类型为 E,即 Exclusive lock,也就是排他锁。 其中 PRCD_HEAD 是 Pricing 模块低头级别的数据: CRM One Order 对应的 lock object 名称为:E_CRM_ORDER 对于这个叫做 prospect 的必填字段: 在SAP CRM零碎中,Opportunity(商机)是指一个潜在的销售机会,即无望成为理论销售交易的业务机会。Opportunity可能波及潜在客户,产品或服务,以及预计的销售金额和销售阶段等信息。为了更好地治理和跟踪销售机会,SAP CRM零碎提供了Opportunity治理性能,其中包含Opportunity明细界面,用于录入和查看Opportunity的详细信息。 在Opportunity明细界面中,"prospect"是一个必填字段,它示意潜在客户,即可能成为理论客户的集体或组织。这个字段的填写十分重要,因为它关联了Opportunity与具体的潜在客户之间的关系,有助于辨认Opportunity的起源和潜在的销售机会。 以下是一个示例,具体阐明在SAP CRM零碎Opportunity明细界面中"prospect"字段的含意: 假如咱们有一个销售团队,他们负责销售IT解决方案给潜在客户。团队成员应用SAP CRM零碎来治理和追踪销售机会。一位销售代表名为Alex,正在解决一个新的Opportunity,该Opportunity波及提供一套定制化的软件解决方案。 在Opportunity明细界面中,Alex须要填写各种信息,包含Opportunity名称、销售阶段、预计销售金额等。然而,其中一个最要害的字段就是"prospect"。在这个字段中,Alex须要抉择或输出一个潜在客户,这个潜在客户有可能成为理论的客户,从而实现销售交易。 Alex从SAP CRM零碎中查找潜在客户列表,发现有一家名为"TechSolutions"的公司可能是一个潜在的客户,因为他们始终在寻找一个适宜的IT解决方案。于是,Alex在"prospect"字段中抉择了"TechSolutions",将这个Opportunity与该潜在客户关联起来。 填写完必填字段后,Alex还能够填写其余相干信息,如Opportunity的详细描述、销售打算和下一步口头等。随着销售停顿,Alex能够依据理论状况更新Opportunity的状态和信息。 通过填写"prospect"字段,SAP CRM零碎可能精确地记录Opportunity的起源,即潜在客户。这有助于团队更好地理解Opportunity的上下文,并采取适当的销售策略。此外,关联潜在客户还能够帮忙系统生成相干的销售报告和剖析,以更好地理解销售机会的起源和趋势。 总之,"prospect"是SAP CRM零碎Opportunity明细界面中的一个必填字段,用于示意Opportunity的潜在客户。填写这个字段能够帮忙销售团队更好地治理销售机会,理解机会的起源,并采取相应的销售策略,以实现更好的销售业绩。

August 17, 2023 · 1 min · jiezi

关于前端:TypeScript-防抖节流

防抖(Debounce):防抖用于确保一个函数在指定工夫内只触发一次。它在短时间内多次触发同一个事件时,会勾销之前的触发,直到最后一次触发后的必定时间间隔内没有新的触发才执行函数。常见的利用场景蕴含:输入框实时搜查:当用户在输入框中输入时,可能利用防抖技术提前执行搜查查问,放大不必要的查问和服务器压力。窗口大小调整:当用户调整浏览器窗口大小时,可能利用防抖技术避免在调整过程中频繁地从新计算布局。表单验证:当用户在表单输入时,可能利用防抖技术在用户进行输入一段时间后再执行验证,放大验证的次数。 /** * @description 防抖函数 * @param {Function} fn * @param {number} delay * @param {boolean} immediate * @returns {Function} */export function debounce<T extends (...args: any[]) => any>( fn: T, delay: number, immediate: boolean = false): T & { cancel(): void } { let timerId: ReturnType<typeof setTimeout> | null = null; // 存储定时器 // 定义一个cancel方法,用于勾销防抖 const cancel = (): void => { if (timerId) { clearTimeout(timerId); timerId = null; } }; const debounced = function ( this: ThisParameterType<T>, ...args: Parameters<T> ): void { const context = this; if (timerId) { cancel(); } if (immediate) { // 如果 immediate 为 true 并且没有正在期待执行的定时器,立即执行指标函数 if (!timerId) { fn.apply(context, args); } // 设置定时器,在延迟时间后将 timeoutId 设为 null timerId = setTimeout(() => { timerId = null; }, delay); } else { // 设置定时器,在延迟时间后执行指标函数 timerId = setTimeout(() => { fn.apply(context, args); }, delay); } }; // 将 cancel 方法附加到 debounced 函数上 (debounced as any).cancel = cancel; return debounced as T & { cancel(): void };}节流(Throttle):节流用于确保一个函数在必定时间内最多只触发一次。它会在触发事件期间以固定的时间间隔执行函数,而不管事件触发得多频繁。常见的利用场景蕴含: ...

August 17, 2023 · 2 min · jiezi

关于前端:js-展示百度地图及添加标注

百度地图开放平台: https://lbsyun.baidu.com/ 新建利用 js开发文档: https://lbsyun.baidu.com/index.php?title=jspopularGL 咱们临时用的就是展现地图和标注:源码如下(ak换一下) <!DOCTYPE html><html lang="zh-CN"><head> <meta charset="utf-8"> <title>地图展现</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <style> body, html, #container { overflow: hidden; width: 70%; height: 70%; margin: 0; font-family: "微软雅黑"; } .info { z-index: 999; width: auto; min-width: 22rem; padding: .75rem 1.25rem; margin-left: 1.25rem; position: fixed; top: 1rem; background-color: #fff; border-radius: .25rem; font-size: 14px; color: #666; box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5); } </style> <script src="http://api.map.baidu.com/api?type=webgl&v=1.0&ak=yourApplicationKey"></script></head><body> <div class="info">最新版GL地图命名空间为BMapGL, 可按住鼠标右键管制地图旋转、批改歪斜角度。</div> <div id="container"></div></body></html><script> var map = new BMapGL.Map('container'); // 创立Map实例 var point = new BMapGL.Point(116.404, 39.915); map.centerAndZoom(point, 15); // 初始化地图,设置中心点坐标和地图级别 var marker = new BMapGL.Marker(point); // 创立标注 map.addOverlay(marker); map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放</script>

August 17, 2023 · 1 min · jiezi

关于前端:Docker数据持久化与数据共享

上篇文章的最初咱们应用Docker部署了一个纯前端我的项目,但还有一个很重要的问题就是容器中产生的数据(比方log文件),容器一旦被删除,容器内的所有数据也就没有了,为了防止这个问题咱们能够将数据存储到容器之外(比方宿主机),这样即便删除容器也不会失落数据。一旦容器故障,咱们能够从新创立一个容器,将数据挂载到容器里,就能够疾速复原。 数据存储形式Docker提供了以下几种存储形式: volume卷:这种形式是在宿主机文件系统调配一块专有存储区域,由 Docker治理,并且与主机的外围性能隔离。非 Docker 过程不能批改文件系统的这一部分。卷是在 Docker 中长久保留数据的最佳形式,它适宜存储数据库数据,可挂到多个容器上bind mount 绑定挂载:这种形式是间接把宿主机目录映射到容器内,适宜挂代码目录和配置文件,可挂到多个容器上tmpfs mount长期挂载:这种形式仅存储在主机零碎的内存中,并且永远不会写入主机零碎的文件系统,适宜存储临时文件,不可多容器共享 这张图很清晰的解释了volume、bind mount、temps mount与容器和宿主机之间的关系,这三者最终都是存储在宿主机上的。 重点理解volume数据卷:(其实绑定挂载也能够当成volume来了解) 数据卷其实是宿主机上的一个目录当容器目录与数据卷目录绑定之后,单方的批改都会立刻同步一个数据卷能够被多个容器挂载一个容器也能够挂载多个数据卷数据卷能够用来做容器数据长久化、内部机器与容器间接通信、容器之间间接通信 数据卷操作数据卷(Volume)也是常见的 Docker 对象类型的一种,因而它也反对创立、查看、删除等操作 创立数据卷应用docker volume create [name]指令来创立一个数据卷 docker volume create nanjiu-data 查看所有的数据卷docker volume ls 查看卷信息应用docker volume inspect [name]指令来查看对应卷信息 docker volume inspect nanjiu-data 从上图咱们能够看到Mountpoint数据卷挂载的地址,须要留神的是对于非 Linux 零碎而言(Windows 、Mac ),该目录不存在于你的文件系统中,而是存在于 Docker 虚拟机中。 删除数据卷应用docker volume rm [name]指令来删除对应的数据卷 docker volume rm nanjiu-data 这里须要留神的是: 数据卷是用来做长久化数据的,它的生命周期独立于容器,所以Docker不会在容器被删除后主动删除数据卷,并且也不存在垃圾回收这样的机制来解决没有任何容器援用的 数据卷如果须要在删除容器的同时移除数据卷,能够在删除容器的时候应用 docker rm -v 指令如果想要革除所有无容器援用的数据卷,能够应用以下指令: docker volume prune与容器一起应用数据卷自身是用来为容器做数据长久化的,所以独自创立一个数据卷的意义并不大 创立容器与数据卷命名数据卷能够应用docker run指定-v或-mount来创立数据卷,两者产生的后果雷同,最大的区别在于-v语法将所有选项组合在一个字段中,而--mount 语法则将它们离开。 docker run -itd -v nanjiu-vol:/nanjiu-data --name nanjiu nginx:latest这里通过-v指定了数据卷的名称为nanjiu-vol,并且对应绑定容器中的门路为/nanjiu-data ...

August 17, 2023 · 1 min · jiezi

关于前端:JavaScript实现访问本地文件夹

这个性能放在之前是不可能实现的,因为思考到用户的隐衷,然而最近有一个新的api能够做到这一点。上面来进行一个简略的性能实现。 如何抉择文件夹<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <button>关上文件夹</button> <script> var btn = document.querySelector('button'); btn.onclick=function() { showDirectoryPicker() } </script></body></html>咱们调用showDirectoryPicker这个函数就能够实现一个抉择文件夹的性能。 showDirectoryPicker()options 可选 选项对象,蕴含以下属性:id通过指定 ID,浏览器可能记住不同 ID 所对应的目录。当应用雷同的 ID 关上另一个目录选择器时,选择器会关上雷同的目录。mode字符串,默认为 "read",可对目录进行只读拜访。设为 "readwrite" 可对目录进行读写访问。startIn一个 FileSystemHandle 对象或者代表某个家喻户晓的目录的字符串(如:"desktop"、"documents"、"downloads"、"music"、"pictures"、"videos")。用于指定选择器的起始目录。 返回值一个 Promise 对象,会兑现一个 FileSystemDirectoryHandle (en-US) 对象。 异样AbortError 当用户间接敞开了目录选择器或抉择的目录是敏感目录时将会抛出 AbortError。 如何失去文件夹中的文件/子文件夹首先对于下面所写的货色,咱们进行try catch的优化 try { // 取得文件夹的句柄 const handle = await showDirectoryPicker();}catch { //用户回绝查看文件 alert('拜访失败')}之后咱们来看一下这个headler打印进去是什么 句柄的简略解释对于“句柄”,在下始终停留在只知其一;不知其二的意识层面,近日在下学习Windows编程,决定趁此机会将句柄彻底搞清楚。查阅了一些网络上的材料,发现网络上的解说大略能够分为两类:一种是以比喻、类比的形式阐明,这种办法尽管形象易懂,但并没有从原理上、实质上加以揭示,让人依然想问“为什么?”、“怎么实现?”。另一种是给出源代码,无可非议,这当然是最实质的阐明了,但这样一来,又显得不够直观,初学者了解起来有肯定的难度。鉴于此,在下尽微末之能,联合本人的愚见,在两者之间折中,用图解的形式来将原理出现进去,做到高深莫测。 这里须要阐明: 1.这里将句柄所能标识的所有货色(如窗口、文件、画笔等)统称为“对象”。 2.图中一个小横框示意肯定大小的内存区域,并不代表一个字节,如标有0X00000AC6的横框示意4个字节。 3.图解的目标是为了直观易懂,所以不肯定与源码齐全对应,会有肯定的简化。 让咱们先看图,再解释。 其中,图1是程序运行到某时刻时的内存快照,图2是程序往后运行到另一时刻时的内存快照。红色局部标出了两次的变动。 简略解释: Windows是一个以虚拟内存为根底的操作系统,很多时候,过程的代码和数据并不全副装入内存,过程的某一段装入内存后,还可能被换出到外存,当再次须要时,再装入内存。两次装入的地址绝大多数状况下是不一样的。也就是说,同一对象在内存中的地址会变动。(对于虚拟内存不是很理解的读者,能够参考无关操作系统方面的书籍)那么,程序怎么能力精确地拜访到对象呢?为了解决这个问题,Windows引入了句柄。 零碎为每个过程在内存中调配肯定的区域,用来寄存各个句柄,即一个个32位无符号整型值(32位操作系统中)。每个32位无符号整型值相当于一个指针,指向内存中的另一个区域(咱们无妨称之为区域A)。而区域A中寄存的正是对象在内存中的地址。当对象在内存中的地位发生变化时,区域A的值被更新,变为以后时刻对象在内存中的地址,而在这个过程中,区域A的地位以及对应句柄的值是不发生变化的。这种机制,用一种形象的说法能够表述为:有一个固定的地址(句柄),指向一个固定的地位(区域A),而区域A中的值能够动静地变动,它时刻记录着以后时刻对象在内存中的地址。这样,无论对象的地位在内存中如何变动,只有咱们把握了句柄的值,就能够找到区域A,进而找到该对象。而句柄的值在程序本次运行期间是相对不变的,咱们(即零碎)当然能够把握它。这就是以不变应万变,按图索骥,顺藤摸瓜。 **所以,咱们能够这样了解Windows **句柄: 数值上,是一个32位无符号整型值(32位零碎下);逻辑上,相当于指针的指针;形象了解上,是Windows中各个对象的一个惟一的、固定不变的ID;作用上,Windows应用句柄来标识诸如窗口、位图、画笔等对象,并通过句柄找到这些对象。 ...

August 17, 2023 · 2 min · jiezi

关于前端:京东门详一码多端探索与实践-京东云技术团队

本文次要讲述京东门详业务在撑持过程中遇到的窘境,面对问题咱们在效率晋升、品质保障等方向的摸索和实际,在此将实际过程中问题解决的思路和计划与大家一起分享,也心愿能给大家带来一些新的启发 一、背景1.1、京东门详介绍1.1.1、京东门详业务门店详情页简称门详,门详业务蕴含门店详情、列表、凑单、搜寻、到店等页面,最早于2020年在京东主站APP上线,最后是作为京东到家线下优质商家以线下店模式入驻京东主站,用户能够在门详内一站式实现门店信息查看、商品浏览、配送时效确认、领券、加车、下单等残缺购物流程。后续随着业务的倒退,门详陆续承接了天选、小时购、药急送、前置仓等更多的业务模式场景,逐步造成了以即时批发为个性,笼罩到家、到店场景,承接线上线下的通用综合型业务零碎 1.1.2、门详业务状态门详业务波及到家门详(小时购、药急送)、到店门详(POP、万家);技术栈波及京东小程序[2]、微信小程序[3]、H5、RN;页面波及门店首页、凑单、搜寻、评估、资质、列表等20+ 1.2、门详业务反对过程中面临的痛点京东app和微信小程序两端门详性能差别较大因历史起因面临同时保护京东app和京购小程序两套门详业务需要业务布局需求量微小,双端需要迭代频繁,研发资源缓和无奈短时间消化双端业务场景及不同的技术栈对品质保障带来较大挑战 1.3、京购小程序业务方对门详的诉求冀望将京购小程序门详性能对齐京东app新需要迭代心愿疾速同步到微信域冀望研发需要吞吐量减少,能够疾速消化更多的需要二、技术计划2.1、后期计划调研后期技术计划调研方面,咱们也理解了以后风行的各种多端框架像RN、Flutter、Taro、uni-app等,并从多端反对度、开发生态、前端框架反对状况、学习老本等各方面进行了调研比照;因为要反对京东APP及微信小程序,所以优先思考反对小程序的多端框架像Taro3[1]、uni-app[10]、mpvue[11]、chameleon[12]、WePY[13]等;联合对前端框架兼容状况、京东小程序[2]的反对度及团队本身状况(团队对React比拟相熟)等因素,综合思考最终决定采纳Taro框架来进行多端化重构。 2.2、技术计划制订及实际2.2.1、思考须要解决的问题如何更好的反对京东小程序、微信小程序、H5等多端需要?如何在革新过程中防止新需要反复开发?如何缩短研发交付周期?如何能力在开发过程中提高效率?如何在疾速迭代过程中保障研发品质?如何灵便反对更多的业务场景?如何保障页面性能?2.2.2、制订解决方案2.2.2.1、门详业务多端化解决方案整个计划通过前端、服务端、平台独特构建一套残缺的多端化、楼层化解决方案,服务端基于PaaS化架构将门详性能拆分为多个畛域服务、畛域模型及扩大点,前端基于iPaas楼层、组件规范制订门详多端化、楼层化计划,治理平台通过奥德修斯(小程序交易数字化平台)与黄流数字化平台、iHub平台能力买通,进行业务、页面、楼层、组件、数据等治理及上线公布,以下是整体解决方案全景图 2.2.2.2、门详前端技术框架前端基于Taro3[1] + React[8] + Recoil[7]为技术底座,将门详业务依照根底性能和根底组件准则拆分出网络、地址、埋点、优惠券、商卡、购物车等等50+性能点,页面规范在iPaas页面协定上减少了门详渲染引擎局部,通过iHub平台治理楼层及代码,最终由页面容器进行渲染,以下基于门详面临的痛点在门详多端化过程中的架构图及咱们在施行过程中的一些计划 2.2.3、技术计划施行过程1)业务性能归类及楼层和组件拆分 门详首页依照构造拆分成页头、列表、页尾、弹层等局部,依照楼层拆分成页面头部、门店信息、会员楼层、优惠促销、商品列表、结算条、购物车等12+楼层组件 2)多端适配过程中的差别解决 尽管多端化框架曾经帮我咱们解决了跨平台开发场景,但不同平台之间因为底层原理及根底能力实现形式的差别,依然存在一些须要依照特定平台进行适配解决的工作量,咱们首先梳理门详中应用到的小程序平台40+底层能力,列举并比照多端平台上的性能差别,针对平台差别制订两头适配层将API对立规范化(eg:登录、地址、埋点、路由、零碎信息等) 3)开发过程中的提效形式 组件化:组件封装分两层,底层是最小单元的性能组件,下层是最小可复用业务组件准则封装,无效的缩小了雷同和类似代码的冗余,同时也会定期通过工具jscpd[4]进行代码审计进一步找出类似代码片段进行优化 楼层化:组合相干业务组件晋升能力最大复用度,例如:门店信息楼层、优惠促销楼层等等,并且楼层组件依照页面schema协定开发,反对局部能力可定制化MVVM模式:利用react hook[6]形式将原有页面中的逻辑及数据处理提练到View Mode层,使逻辑和UI之间清晰拆散易于保护,还能够显著进步代码重用机会4)革新过程中新需要解决 旧门详采纳的京东小程序原生语言开发,新门详采纳Taro+React开发,在新门详未全量公布前新需要是须要双端反对的,这样也就意味着雷同需要会开发两次,通过摸索咱们通过混合开发模式[9]将Taro组件打包成小程序能够间接援用的原生组件,解决了新旧工程反复开发问题 2.3、门详小程序性能优化门详在公测阶段也裸露了一些性能问题,咱们依照场景划分为两类:体验性能、启动性能,上面在这里和大家一起分享下相干案例及解决思路,心愿能给有类似窘境的小伙伴一些新的思路 2.3.1、体验性能优化门详首页用户操作比拟频繁的就是分类切换、列表滑动等性能,也是用户反馈卡顿较为多的局部,上面针对以上两类问题进行相干案例剖析: 2.3.1.1、商品列表渲染性能优化在门详多端化革新后,咱们通过问卷调研形式收集用户体验反馈,发现局部用户反馈在滚动商品列表时存在卡顿的景象。咱们利用Taro的debug环境日志进行剖析,发现分页加载时setData体积一直增大,耗时一直增长 debug环境日志: setData耗时走势曲线: 经排查后发现是列表分页渲染时数据量较大导致丢帧。为了解决大范畴渲染及反复渲染问题,将原有的商品列表二维数组数据结构优化为链表+递归形式进行分层嵌套平铺渲染,数据上缩小多层级计算、视图上将分页加载渲染管制在单页内,以下为优化后的列表成果: 列表成果: setData耗时走势曲线: 优化前后分屏数据渲染耗时比照: 上图左侧为列表优化前成果,能够看到分页加载申请数据时的卡顿体感比拟显著,尤其是随着数据量的增大,卡顿工夫越来越长。右侧为优化后成果,在加载十几页之后仍然放弃高效的渲染性能。通过上述优化后每屏数据渲染耗时均维持在200ms左右,在分页数据加载较多的状况下渲染仍然放弃高效。 2.3.1.2、分类切换时列表渲染逻辑优化在前置仓的业务撑持过程中,发现在某些非凡场景下切换分类时等待时间较长,用户体验较差。经剖析发现在分类列表加载数据时前端解决逻辑是在商品不满一屏时主动加载下一页数据,补全商品列表让用户能够看到更多的商品数据,而在接口进行轮询申请时导致用户等待时间较长 上图左侧为优化前分类切换时商品加载的逻辑,为了缩小用户期待时长对分类渲染逻辑进行优化(如图右侧),调整分类点击后的解决逻辑,只申请以后分类下数据,不再进行跨一级分类接口申请。分类渲染耗时从n(接口申请次数)*250(接口申请耗时)+200ms(前端渲染耗时)缩小到250ms+200ms。 2.3.2、启动性能优化咱们针对门详小程序启动过程进行剖析,整顿启动的每个环节及对应的耗时数据,制订优化计划,优化次要方向如下: 京东小程序包压缩(将jdapkg文件进行zip压缩,文件大小从8.6MB升高到3.4MB)门详小程序模版包复用(防止多个小程序冷启动下载屡次)门详小程序模版包内置进APP(缩小小程序包下载耗时)APP启动时进行小程序模版包预加载(缩小小程序冷启动耗时)小程序引擎加载耗时优化(前置预热小程序引擎)小程序引擎启动主线程卡顿优化(逻辑层与渲染层并行处理)小程序代码构建包.jdapkg优化(引擎公共代码抽离)小程序信息接口由同步改为异步(线上均匀耗时缩小158ms)小程序网络库超时工夫及重试机制优化门详主接口耗时优化(非首屏必要数据异步化)门详业务代码包瘦身(代码优化、分包等,包大小从3.4MB升高到648KB)应用公共模版包,多个商家共用一个代码包,缩小反复下载 优化前门详小程序均匀启动耗时2227.7ms,经以上优化措施施行后,整体启动耗时缩小到954ms,启动速度晋升57.6%,在门详小程序启动优化过程中咱们也失去了京东小程序引擎团队的大力支持,也借此机会示意衷心的感激! 2.4、ISV共建计划及品质保障摸索2.4.1、为什么要进行共建摸索呢?对于业务侧大量的需要涌入,且有一部分并非门详通用性能属于非凡场景的个性化需要,而在研发资源紧缺的状况咱们也在思考如何能力晋升需要的吞吐量,为了更好的撑持业务,在与业务深度交换后发现局部业务侧也有本人的研发团队,能够自主个性化需要开发,单方沟通后达成共识在保障系统稳定性的同时,咱们在楼层化的根底上对系统进行改良反对黄流ISV平台接入,将局部独立楼层凋谢给业务侧自主接入,具体共建流程如下: 通过零碎ISV计划革新摸索后门详的个性化需要期待时长显著缩短,比照前两个季度个性化需要整体承接量增长30%以上,在需要大量增长的同时也是对系统和新架构的考验,为保证系统稳定性咱们对共建需要的接入、开发、上线等进行了共建流程标准制订及相干性能、品质等束缚 2.4.2、如何保障研发品质?多团队多人合作过程中咱们也发现了一些问题,为了防止一些惯例问题在此咱们制订了相干的开发标准,并在整个需要开发上线过程中减少一些必要的校验环节,具体细节如下: 对立标准规范制订(目录构造标准、git 分支标准、代码编写标准、开发标准、文件标准、上线标准等)需要评审后开发前进行前后端技术计划评审利用工具(ESLint)进行代码标准扫描及语法标准查看上线前进行code review及影响范畴预估上线中checklist(重要流程、外围性能、非凡场景)查看上线后灰度切量且察看监控、异样、客诉等零碎兜底计划反对线上页面、性能等一键降级三、技术积淀与业务赋能3.1、技术改造过程中的能力积淀多端化楼层化开发框架,反对ISV形式接入共建标准页面可编排楼层化协定,反对局部能力可动静配置标准化楼层组件开发模版,缩小组件开发配置过程根底性能库积淀根底API 16个、根底组件25个、业务组件50+、打包插件3个自研多端调试工具(nuclear)、发表公众号文章2篇、已进入国家专利局审核阶段专利2篇构建工具cola-cli、cola-server小程序标准化门详赋能SDK3.2、多端化带来的收益根底能力赋能新业务(前置仓门详、到店商详、POP门详等)开发效率晋升40%以上京东app上的门详新需要95%+的性能是能够间接复用到微信小程序、H5端,在无限的研发资源下大幅晋升了多端需要吞吐量通过4个月的多端化革新后补齐了京购小程序中门详业务滞后2年多的需要小程序赋能20+(eg:京购小程序、京东超市小程序、小时购等) 门详多端化楼层化过程中积淀的开发框架、根底性能库、通用开发模版,也在到店门详、到店商详、pop门详等业务中失去了较好的实际 3.3、前置仓门详疾速撑持在京东app前置仓二期建设过程中小程序门详组件及性能复用率达到95%+,基于多端化框架能力在2天内实现将前置仓门详赋能到京购小程序,业务侧提出冀望将前置仓门详能力能够引入到京东超市小程序(微信),基于后期门详多端化能力建设仅用2小时就实现了置仓门详能力赋能京东超市小程序(微信),也是在这个过程中咱们将门详多端化和楼层化能力与奥德修斯平台鉴权、模型治理、数据管理、可视化、配置化等能力相结合,通过脚手架与平台联合形式为业务方提供一键构建一站式赋能服务,通过这种标准化的形式既反对了京东超市小程序需要同时也裁减了黄流SDK中的标准化门详能力,一键触发5分钟既可实现整个黄流SDK赋能包的构建 四、将来瞻望随着门详业务波及的场景日益增多,通用的楼层组件逐步也无奈满足所有差异化场景,然而全副楼层都放入公共模版包中无疑是对小程序包大小的考验,基于一码多端框架和咱们自研的小程序公布零碎思考,能够将门详批量小程序进行分类管理,构建时按类型按需构建,将一个公共模版包拆分成多个模版,可依照差异化形式别离构建公布 在京东前端技术域iPaas2.0搭建平台建设逐步欠缺同时,门详业务得益于多端化、楼层化框架,也为门详小程序反对多端可视化搭建迈出了后退的一步,为更多业务场景提供标准化门详 参考资料[1]Taro3:https://taro-docs.jd.com/docs/ [2]京东小程序:https://mp-docs.jd.com/doc/dev/framework/-1 [3]微信小程序:https://developers.weixin.qq.com/miniprogram/dev/framework/ [4]jscpd:https://github.com/kucherenko/jscpd ...

August 17, 2023 · 1 min · jiezi

关于前端:展会预告-图扑与您相约用友-2023-全球商业创新大会

为汇聚商业智慧,开释企业潜能,深刻推动企业数智化转型降级,翻新客户价值,让数智化在更多的企业胜利,由用友主办的“2023 寰球商业翻新大会”,将于本月 8 月 18 日至 20 日,在上海市“国家会展中心”隆重召开。 图扑软件受邀缺席本次大会,届时将携诸多 Web 端的 UI/2D/3D、GIS、BIM 及 VR/AR 等可视化、数字孪生相干解决方案,亮相 4.2 馆 E 厅 B3 展位。咱们诚邀您光临参观,期待与各位领导、业界专家和潜在合作伙伴,独特探讨赋能行业数字化发展趋势。 本次大会以“数据驱动 智能经营”为主题,将深入探讨主题化交融翻新、全局数据治理、遍及 AI 利用、降级数智底座及全球化经营等企业关注的热点话题。大会设有价值、技术、生态 3 大主题峰会,40+ 专题论坛,3000+ m² 数智企业体验馆等诸泛滥流动安顿。会上,用友将与来自各畛域及行业的生态搭档、先锋企业、专家学者等千余位嘉宾共话业务新增长,共享用友 BIP 生态新成绩。 以 ChatGPT 为代表的 AI 热潮席卷寰球,标记着 AI 遍及利用时代的到来,企业的商业翻新,也由此前偏重数据服务的数字化,进入到数据服务与智能化并举的数智化新阶段。 作为专精可视化技术的图扑软件,咱们致力于成为企业数智化转型的优质赋能搭档,助推各畛域突破数据孤岛景象,让产业运维可追溯,设施运行可监管,实现智能制作和数字化转型。 牵手泛滥龙头企业,利用自研 HT for Web产品打造多项利用场景。已笼罩工业制作、楼宇园区、轨道交通、城市政务、水务能源、新基建、智慧运维、国防公安、医疗科研、金融军工等各个行业。 数百个工业互联网可视化我的项目施行教训,造成了⼀整套实践证明高效开发流程和生态系,可疾速实现现代化、高性能、跨平台桌面 Mouse/挪动 Touch/虚拟现实 VR 图形展现成果及交互体验。提供从征询、设计、施行到售后的全方位可视化反对服务。 您能够至图扑软件官网查看更多案例及成果:图扑软件 - 构建先进 2D 和 3D 可视化所须要的所有

August 17, 2023 · 1 min · jiezi

关于前端:一文了解-history-和-reactrouter-的实现原理

咱们是袋鼠云数栈 UED 团队,致力于打造优良的一站式数据中台产品。咱们始终保持工匠精力,摸索前端路线,为社区积攒并流传教训价值。 本文作者:霜序 前言在前一篇文章中,咱们具体的说了 react-router@3.x 降级到 @6.x 须要留神的问题以及变更的应用形式。 react-router 版本更新十分快,然而它的底层实现原理确是万变不离其中,在本文中会从前端路由登程到 react-router 原理总结与分享。 前端路由在 Web 前端单页面利用 SPA(Single Page Application)中,路由是形容 URL 和 UI 之间的映射关系,这种映射是单向的,即 URL 的扭转会引起 UI 更新,无需刷新页面 如何实现前端路由实现前端路由,须要解决两个外围问题 如何扭转 URL 却不引起页面刷新?如何监测 URL 变动?在前端路由的实现模式有两种模式,hash 和 history 模式,别离答复上述两个问题 hash 模式hash 是 url 中 hash(#) 及前面的局部,罕用锚点在页面内做导航,扭转 url 中的 hash 局部不会引起页面的刷新通过 hashchange 事件监听 URL 的扭转。扭转 URL 的形式只有以下几种:通过浏览器导航栏的后退后退、通过<a>标签、通过window.location,这几种形式都会触发hashchange事件history 模式history 提供了 pushState 和 replaceState 两个办法,这两个办法扭转 URL 的 path 局部不会引起页面刷新通过 popchange 事件监听 URL 的扭转。须要留神只在通过浏览器导航栏的后退后退扭转 URL 时会触发popstate事件,通过<a>标签和pushState/replaceState不会触发popstate办法。但咱们能够拦挡<a>标签的点击事件和pushState/replaceState的调用来检测 URL 变动,也是能够达到监听 URL 的变动,绝对hashchange显得稍微简单JS 实现前端路由基于 hash 实现因为三种扭转 hash 的形式都会触发hashchange办法,所以只须要监听hashchange办法。须要在DOMContentLoaded后,解决一下默认的 hash 值 ...

August 17, 2023 · 6 min · jiezi

关于前端:HtmlJavaScript实现手写签名

前言Hello各位,本葡萄又来啦,明天遇到的场景是这样的:在日常业务流程中,常常须要某一流程环节中相干责任人员进行审批签字,晚期许多公司为了省事就间接会把这位负责人的签名以键盘打字(楷体)的模式打印进去,然而这样的害处就是会导致所有的负责人的签名都是一样的,没有美感,为了解决这个问题,一些公司就开始应用手写签名(用鼠标或者是电子笔写进去的签名)代替电子签名,明天本葡萄就为大家简略的介绍下手写签名到底是怎么实现的。话不多说,先上效果图: 看完效果图之后,上面为大家介绍实现的具体过程。 应用Html+JavsScript实现手写签名的增加1.实现Html界面<!doctype html><html><head><title>SpreadJS in TypeScript</title><!--引入在线Excel资源--><link rel="stylesheet" type="text/css" href="node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css"><link rel="stylesheet" type="text/css" href="node_modules/@grapecity/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css"><script src="node_modules/systemjs/dist/system.src.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jSignature/2.1.3/jSignature.min.js" integrity="sha512-lZ7GJNAmaXw7L4bCR5ZgLFu12zSkuxHZGPJdIoAqP6lG+4eoSvwbmKvkyfauz8QyyzHGUGVHyoq/W+3gFHCLjA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="systemjs.config.js"></script><script>System.import('./src/app');</script></head><!--增加清空和确认性能--><body><div id="signArea" style="position: absolute;top:100px;left:200px;visibility:hidden;z-index:100"><div id="sign" style="height:300px;width:600px;border:1px dashed \#ddd;margin-bottom:10px"></div><div><button id="clear">清空</button><button id="confirm">确认</button></div></div><div id="designer-container" style="width:100%;height:90vh;border:1px solid darkgray"></div></body></html>首先引入须要的在线Excel资源包,而后增加减少清空和确认手写签名两个按钮。 2.手写签名的JavsScript实现办法(1) 增加手写签名: let config = JSON.parse(JSON.stringify(GC.Spread.Sheets.Designer.DefaultConfig))let customeAddSign = {"text":"增加手写签名",commandName:"customeAddSign",execute:() =\> {if(document.getElementById("signArea")){document.getElementById("signArea").style.visibility = 'visible'}}}(2) 追加右键自定义菜单: 外围代码: // 追加自定义右键菜单config.contextMenu.push("customeAddSign")config.commandMap = {customeAddSign}let designer = new GC.Spread.Sheets.Designer.Designer("designer-container",config)let spread = designer.getWorkbook()$("#sign").jSignature({lineWidth:'16',width:'100%',height:'100%'})document.getElementById("clear").onclick = function(){$("#sign").jSignature("reset")}document.getElementById("confirm").onclick = function(){let datapair = "data:" + $("#sign").jSignature("getData")let sheet = spread.getActiveSheet()let row = sheet.getActiveRowIndex()let col = sheet.getActiveColumnIndex()let picture = sheet.shapes.addPictureShape(`${sheet.name()}-${row}-${col}}`, datapair,0,0,100,100);picture.startRow(row)picture.endRow(row + 1)picture.startColumn(col)picture.endColumn(col + 1)picture.startRowOffset(0);picture.startColumnOffset(0);picture.endRowOffset(0);picture.endColumnOffset(0);picture.allowResize(false)picture.allowMove(false)picture.allowRotate(false)$("#sign").jSignature("reset")document.getElementById("signArea").style.visibility = 'hidden'}这一步的作用是实现在Excel单元格中增加手写签名的性能,右键菜单抉择手写签名后会调用对应的签名插件,在签名插件上能够用鼠标进行输出,输出完之后点击确认就会显示在单元格中。 残缺代码和在线Demo地址:置信看到这里,很多小伙伴曾经想操作一下了吧,本葡萄也为大家筹备了一个自由发挥的平台,点击下方链接便能够跳转到对应的Demo在线地址(平安可食): https://jscodemine.grapecity.com/share/sXBAh7hZ00SAsemg_1jLbQ... ...

August 17, 2023 · 1 min · jiezi

关于前端:产品经理实现一个微信输入框

近期在开发AI对话产品的时候为了晋升用户体验加强了对话输入框的相干能力,产品初期阶段对话框只是一个单行输入框,导致在文本内容很多的时候体验很不好,所以进行体验降级,相似还原了微信输入框的性能(只是其中的一点点哈)。 初期认为这应该改变不大,就是把input换成textarea吧。然而理论开发过程发现并没有这么简略,本文仅作为开发过程的记录,因为是基于uniapp开发,相干实现代码都是基于uniapp。 简略剖析咱们大略须要实现以下几个性能点: 默认单行输出可多行输出,但有最大行数限度超过限度行术后内容在外部滚动反对回车发送内容反对常见组合键在输入框内换行输出多行输出时高度自适应 & 页面整体自适应单行输出默认单行输出比较简单间接应用input输入框即可,应用textarea的时候目前的实现形式是通过设置行内款式的高度管制,如咱们的行内高度是36px,那么就设置其高度为36px。为什么要通过这种形式设置呢?因为要思考后续多行输出超出最大行数的限度,须要通过高度来管制textarea的最大高度。 <textarea style="{ height: 36px }" /> 多行输出多行输出外围要留神的就是管制元素的高度,因为不能随着用户的输出始终减少高度,咱们须要设置一个最大的行数限度,超出限度后就不再减少高度,内容能够持续输出,能够在输入框内高低滚动查看内容。 这里须要借助于uniapp内置在textarea的@linechange事件,输入框行数变动时调用并回传高度和行数。如果不应用uniapp则须要对输出文字的长度及以后行高计算出对应的行数,这种状况还须要思考单行文本没有满一行且换行的状况。 代码如下,在linechange事件中获取到最新的高度设置为textarea的高度,当超出最大的行数限度后则不解决。 linechange(event) { const { height, lineCount } = event.detail if (lineCount < maxLine) { this.textareaHeight = height }}这是失常的输出,还有一种状况是用户间接粘贴内容输出的场景,这种时候不会触发@linechange事件,须要手动解决,依据粘贴文本后的textarea的滚动高度进行计算出对应的行数,如超出限度行数则设置为最大高度,否则就设置为理论的行数所对应的高度。代码如下: const paddingTop = parseInt(getComputedStyle(textarea).paddingTop);const paddingBottom = parseInt(getComputedStyle(textarea).paddingBottom);const textHeight = textarea.scrollHeight - paddingTop - paddingBottom;const numberOfLines = Math.floor(textHeight / lineHeight);if (numberOfLines > 1 && this.lineCount === 1) { const lineCount = numberOfLines < maxLine ? numberOfLines : maxLine this.textareaHeight = lineCount * lineHeight}键盘发送内容失常咱们应用电脑聊天时发送内容都是应用回车键发送内容,应用ctrl,shift,alt等和回车键的组合键将输入框的文本进行换行解决。所以接下来要实现的就是对键盘事件的监听,基于事件进行发送内容和内容换行输出解决。 ...

August 17, 2023 · 1 min · jiezi

关于前端:webpack-从入门到放弃

webpackwebpack于2012年3月10号诞生,作者是Tobias(德国)。参考GWT(Google Web Toolkit)的code splitting性能在webpack中进行实现。而后在2014年Instagram团队分享性能优化时,提出应用webpack的code splitting个性从而大火。 当初webpack的呈现含糊了工作和构建的边界在webpack呈现之前,咱们应用gulp、grunt做工作的,构建是用其余工具实现,而当初webpack使其融为一体。 之前咱们在html加载js资源的时候,须要应用script标签,加载css也须要编写css文件进行加载,这样咱们每次html加载的时候就须要加载多个资源。而webpack将所有的资源都打包到js中,会有一个entry入口文件,entry引入了js、css等资源文件,打包到一个bundle文件中,这样就加载一个资源。 webpack最后外围解决的问题就是代码合并与拆分,它的核心理念是将资源都视为模块,对立进行打包和解决,而后再按规定进行拆分,提供了loader和plugin实现性能扩大。 webpack5常识体系:https://gitmind.cn/app/docs/m1foeg1o外围概念entry:入口模块文件门路output: 输入bundle文件门路module:模块,webpack构建 对象bundle:输入文件,webpack构建产物chunk:构建生成bundle过程中,产生的两头文件,webpack构建的两头产物loader:文件转换器plugin:插件,执行特定工作mode:工作模式,默认采纳production模式,我的项目初始化流程创立npm我的项目装置webpack依赖 webpack和webpack-cli创立js入口文件创立webpack配置文件配置package.json的build命令执行npm run build 打包Webpack工作模式Webpack 4 新增了一个工作模式的用法,这种用法大大简化了 Webpack 配置的复杂程度。你能够把它了解为针对不同环境的几组预设配置: production 模式下,启动内置优化插件,主动优化打包后果,打包速度偏慢;development 模式下,主动优化打包速度,增加一些调试过程中的辅助插件;none 模式下,运行最原始的打包,不做任何额定解决。针对工作模式的选项,如果你没有配置一个明确的值,打包过程中命令行终端会打印一个对应的配置正告。在这种状况下 Webpack 将默认应用 production 模式去工作。 production 模式下 Webpack 外部会主动启动一些优化插件,例如,主动压缩打包后的代码。这对理论生产环境是十分敌对的,然而打包的后果就无奈浏览了。 批改 Webpack 工作模式的形式有两种: 通过 CLI --mode 参数传入;通过配置文件设置 mode 属性。上述三种 Webpack 工作模式的具体差别咱们不再赘述了,你能够在官网文档中查看:https://webpack.js.org/configuration/mode/ 打包后果运行原理为了更好的了解打包后的代码,咱们先将 Webpack 工作模式设置为 none,这样 Webpack 就会依照最原始的状态进行打包,所失去的后果更容易了解和浏览。 依照 none 模式打包实现后,咱们关上最终生成的 bundle.js 文件,如下图所示: 咱们能够先把代码全副折叠起来,以便于理解整体的构造 整体生成的代码其实就是一个立刻执行函数,这个函数是 Webpack 工作入口(webpackBootstrap),它接管一个 modules 参数,调用时传入了一个数组。 开展这个数组,外面的元素均是参数列表雷同的函数。这里的函数对应的就是咱们源代码中的模块,也就是说每个模块最终被包裹到了这样一个函数中,从而实现模块公有作用域,如下图所示: 咱们再来开展 Webpack 工作入口函数,如下图所示: 这个函数外部并不简单,而且正文也很清晰,最开始定义了一个 installedModules 对象用于寄存或者缓存加载过的模块。紧接着定义了一个 require 函数,顾名思义,这个函数是用来加载模块的。再往后就是在 require 函数上挂载了一些其余的数据和工具函数,这些临时不必关怀。 ...

August 16, 2023 · 19 min · jiezi

关于前端:前端经典网页布局的实现方案你了解多少

前端开发,离不开日常的网页构造布局,现下有很多第三方的组件库,也自带着很多布局的计划,例如Ant Design中就领有一套本人的Grid 24栅格零碎和Layout布局,不便咱们进行网页排版。 接下来,咱们从前端技术角度上,去剖析一下3种经典布局的实现计划。 首先,咱们列出一些比拟惯例的布局: 圣杯布局双飞翼布局多列等分布局1. 圣杯布局圣杯布局: 左右两栏的宽度固定不变,两头那一栏宽度自适应,且两头盒子的内容优先渲染。 最早的圣杯布局的实现计划是:利用浮动和负边距来实现。 父级元素设置左右的 padding,三列均设置向左浮动,两头一列放在最后面,宽度设置为父级元素的宽度,因而前面两列都被挤到了下一行,通过设置 margin 负值将其挪动到上一行,再利用绝对定位,定位到两边。 圣杯布局的优缺点: 长处:不须要额定的DOM构造,两头栏放在文档流后面是优先渲染毛病:非凡状况下,当两头盒子宽度小于左盒子的时候 就会产生布局凌乱咱们能够通过3种技术计划来实现圣杯布局的布局成果,别离是float、float优化、Flex 实现代码: HTML构造: <div class="main"> <!-- 如果是圣杯布局的原始计划,此处的center盒子要放在最后面 --> <div class="center"></div> <div class="left"></div> <div class="right"></div></div>实现计划1:float+position+负边距.main { height: 200px; /* 外层大盒子设置左右的padding,给两侧小盒子预留出地位 */ padding: 0 200px;}.center, .left, .right { /* 三个盒子对立左浮动 */ float: left;}/* 留神,在HTML构造中,center盒子肯定要位于left和right盒子之前 */.center { /* 两头盒子占据父盒子宽度的100% */ width: 100%; height: 100%; background: lightgreen; }.left { width: 200px; height: 100%; background: lightseagreen; /* left被center盒子挤到了下方,设置margin负值会让三个盒子在一行上显示 */ margin-left: -100%; /* 通过定位负值让left盒子位于main盒子预留出的padding的地位 */ position: relative; left: -200px;}.right { width: 200px; height: 100%; background: lightskyblue; /* right被center盒子挤到了下方,设置margin负值会让三个盒子在一行上显示 */ margin-left: -200px; /* 通过定位负值让right盒子位于main盒子预留出的padding的地位 */ position: relative; right: -200px; }实现计划2:float优化.main { width: 100%; height: 100px;}.left { width: 200px; height: 100%; background: lightcoral; /* 左盒子左浮动 */ float: left;}.right { width: 200px; height: 100%; background: lightgreen; /* 右盒子右浮动 */ float: right;}.center { height: 100%; background: lightsalmon; /* 两头盒子左浮动 */ float: left; /* 两头盒子应用css的calc()去主动计算宽度,思维为:父盒子宽度100% - (左盒子 + 右盒子) */ /* 留神:如果网页中在意极致加载速度等优化效率时,尽量不要大量应用calc()函数 */ width: calc(100% - 400px);}实现计划3:Flex.main { width: 100%; height: 100px; /* 父盒子转为flex弹性盒子 */ display: flex; /* 子元素居中 */ justify-content: center; align-items: center;}.left { width: 200px; height: 100%; background: lightcoral;}.right { width: 200px; height: 100%; background: lightgreen;}.center { height: 100%; background: lightsalmon; /* 两头盒子占据剩下的全副空间 */ flex: 1;}当然,实现圣杯布局的成果,还能够应用其它的计划,比方Grid布局形式,只有可能实现其圣杯布局的成果,用什么形式均能够。 ...

August 16, 2023 · 2 min · jiezi

关于前端:可能是东半球最好的-Web-Font-优化方式中文网字计划

中文网字打算是收录泛滥中文字体并通过 Web Font 的模式为 网站开发者 提供漂亮字体的我的项目。 中文网字打算致力于在互联网中提供更加便捷实用的全字符集中文渲染计划。中文网字打算通过精美设计的字体分包形式,将宏大的字体文件切割为多个小型动态分包部署于云端,在全网畛域内都可快捷、稳固地进行加载。为进步中文字体在网络中的流通体验而致力!为什么要应用独特的中文字体进步艺术风格的表现力 前端畛域是信息出现最为丰盛、格调最为灵便的一个技术畛域。它不仅包含了各种以文本为主的新闻、博客、论坛网站,还涵盖了各类活泼灵便的数据可视化网站,以及格调别致的网页小游戏。在许多重视体现细节网站中,中文字体的作用不容小觑。例如在像素游戏应用像素字体来合乎整个游戏世界观,数据可视化网站中使用非凡装璜字体来出现主题所表白的情感,在集体博客中也有使用飘逸轻捷的字体来展示集体的艺术谋求的例子。能够说,抉择适宜的字体是使得网页出现独特格调的要害因素之一。 进步产品的格调辨识度和国内对立度中文字体可能无效地出现品牌形象,进步产品的辨识度,帮忙产品更好地传递本人的理念和价值观。中文字体在不同的设计元素中也有着其独特的利用。 举例来说,米哈游开发的原神中采纳 汉仪文黑字体,它在中、日、韩、英四种语言环境下体现出统一的艺术风格和文字表现力。即便在同一图片中出现也没有违和感,这对于不同语言玩家在游戏中的视觉效果和用户体验来说具备十分强烈的晋升。 在以后的互联网环境中,英文字体的利用曾经十分广泛。因为英文字符数量较少,因而加载整个字体包并不会对网页造成影响。然而,中文字符与英文字符相比,其数量和轮廓复杂度都更高。因而中文字体体积较英文字体大十分多,而且加载中文字体往往会占用大量的网络带宽。对于原生应用程序来说,能够通过内置字体包等形式解决这个问题,但这个弱点对于 Web 网页加载则是致命的。 如何实现 Web 场景下的网络字体减速手动、主动切割字体文件目前一种在网页中应用中文字体的办法是剖析网页所蕴含的中文字符,将字体切割进去,独自分包存储在服务器中。这种切割形式能够极大地减小字体大小对带宽的影响,实用于集体博客等类型的网站。然而,随着一个我的项目越来越大,所须要进行的切割文本越来越多,采纳这种非全量级的加载形式,可能会导致不同的文章波及的文字不同,从而造成打包字符区间不同,影响服务器的缓存和资源利用率。常见的工具有:字蛛、fontmin、fonttools 等 毛病:须要手动执行、只实用于动态场景、影响缓存效率 Google fonts 计划在 Google Fonts 网站中,Google 采纳最新的 CSS 个性 unicode-range 来实现按需加载 CJK (中日韩) 字体,并胜利地实现了中文字体在网页端的全量级按需加载。同时提供了如站酷系列、Noto 系列等字体的成果展现。从技术上看,所有加载文件为动态文件,能够通过 CDN 一次公布,随处加载,且具备牢靠的速度和稳定性。即便如博客论坛等专一长文本类型的网站,也可应用。但受限于版权问题,Google Fonts 中仅有开源字体,如果须要非凡字体须要进行自托管 https://fonts.googleapis.com/css2?family=Lexend+Exa:wght@900&family=Roboto:wght@100&display=swap 毛病:分包较大、国内拜访不佳或须要代理、须要自托管 中文网字打算计划 中文网字打算在 Google Fonts 的切割计划的根底之上,对字体的应用程序进行了排序分类,优化了各类字符的分包区间,并可应用更加疾速的寰球 CDN 服务,实现了近乎完满的中文字符落地计划。同时,打算中所开源的的开发工具流曾经能够无缝融入前端开发,为中文字体在网络中的应用提供实践和技术上的反对。 建设本人的字体服务上方介绍了三种不同的字体优化形式,现联合「中文网字打算」中的开源模块对字体进行优化 临时无奈在飞书文档外展现此内容 剖析这里取「阿里巴巴普惠体 3.0」进行测试,首先能够应用字体剖析工具对字体进行剖析 在线剖析工具:https://chinese-font.netlify.app/analyze/ 离线剖析工具:https://www.npmjs.com/package/font-analyze 能够看出,在 AlibabaPuHuiTi-3-55-Regular 文件的版权信息,同时中文文字覆盖率信息很好,CJK 覆盖率个别 切割@konghayao/cn-font-split 是一个基于 Node.js 的字体分包器,可能将起源字体文件分成多个包,并且提供附带成绩预览和数据分析性能 。中文网字体打算应用 @konghayao/cn-font-split 作为外围,构建了一系列字体的分包成品。如果您须要对公有字体进行简略分包和动态部署,抉择它再适宜不过了。 在线切割工具https://chinese-font.netlify.app/online-split/ ...

August 16, 2023 · 2 min · jiezi

关于前端:前端合成海报并保存到本地

近期给AI产品减少了推广返佣的能力,波及到推广就会有分享裂变,集体的专属分享链接及海报。本次文章次要记录前端合成海报并下载到本地的流程,因为产品运行的平台次要是在小程序和PC浏览器,所以次要也是实现这两个平台的图片下载,接下来开始注释。 浏览器端实现在实现下载之前首先要将海报内容合并成一张图片。这里用到了 html2canvas 这个库,这个置信很多人都有用到过。 html2canvas能够将网页中的HTML元素转换为Canvas图像,从而实现将网页内容截图的性能。它提供了一种简略的办法来捕获整个网页或特定的HTML元素,并生成对应的图像数据。 以下是一个简略的示例代码,第一个参数传入须要合并图像的DOM根元素,第二个参数传入相应的参数配置,在回调中即可获取到对应的canvas对象: html2canvas(this.$refs.poster.$el, { useCORS: true, allowTaint: true, scale: this.getDPR(),}).then(canvas => {})接下来就是将canvas对象转换成图片并下载到本地,通过canvas.toDataURL能够将canvas对象转换为base64的图片地址,再创立一个a标签模仿点击即可触发图片下载到本地。 const dataURL = canvas.toDataURL('image/jpeg', 0.8);const link = document.createElement('a');link.href = dataURL;link.download = 'poster.png';// 模仿点击链接,触发下载link.click();小程序端实现小程序实现就较为麻烦一些了,html2canvas在小程序外面不反对,能够应用wxml-to-canvas 代替,然而思考到接入的老本和以后实现的页面比较简单,目前实现是间接用原生canvas绘制海报,大略的代码如下所示,次要就是绘制图片及文本,如果波及到比较复杂的界面对应的代码复杂度也会升高很多,大家如果有更好的计划欢送探讨。 const ctx = wx.createCanvasContext('canvas');ctx.beginPath();ctx.drawImage('bg.png', 0, 0, this.canvasWidth, this.canvasHeight);ctx.setTextAlign('center');ctx.setFillStyle('#FFFFFF');ctx.setFontSize(24);ctx.fillText('海报文本', 150, uni.upx2px(90));ctx.draw();图片绘制好了接下来就是下载的过程。 在小程序外面下载图片须要用到 wx.canvasToTempFilePath,把以后画布指定区域的内容导出生成指定大小的图片,这里咱们传入对应的cavansID即可,在胜利的回调中就能获取到图片的临时文件门路 (本地门路)。 wx.canvasToTempFilePath({ canvasId: 'poster-canvas', success(res) { const tempFilePath = res.tempFilePath }})获取到了本地地址就能够进行图片的保留,然而可能存在用户未设置权限或回绝了存储到权限,所以下载之前须要进行权限相干的判断及提醒疏导操作。大略的代码如下: // 判断用户受权wx.getSetting({ success(res) { // 没有权限,发动受权 if (!res.authSetting['scope.writePhotosAlbum']) { wx.authorize({ scope: 'scope.writePhotosAlbum', success() { // 受权胜利,可下载 }, fail() { // 用户点击回绝受权,跳转到设置页,疏导用户受权 wx.openSetting({ success() { wx.authorize({ scope: 'scope.writePhotosAlbum', success() { // 可下载 }, fail() { this.$showToast("保留失败"); } }) }, fail(res) { this.$showToast("未取得权限保留图片"); } }) } }) } else { // 用户已受权,可下载保留到相册 } }})权限判断没问题即可调用wx.saveImageToPhotosAlbum传入后面从canvasToTempFilePath获取的tempFilePath进行下载: ...

August 16, 2023 · 1 min · jiezi

关于前端:⚡️-The-Cost-Of-JavaScript-2017-2023-JavaScript-性能优化之旅

如果你喜爱我的文章,心愿点赞 珍藏 评论 三连反对一下,谢谢你,这对我真的很重要!吐槽工夫不晓得从什么时候开始,前端开始卷一些 “高端常识”,动不动就浏览器底层原理,V8 是如何运行的,倒不是说这些没啥用,只是来势汹汹如同不懂这些就不能糊页面一样。 我工作中和内核团队与虚拟机团队也单干过并征询过他们这些相干问题,大家的态度也很明确,面对这种千万行代码的大型工程项目,他们作为专业人士也不是啥都懂,万一遇到个真的啥都懂的,人家必然也不会去做前端,这就显得一些面试官和求职者的八股攻防战可笑了起来。 那么如果真的遇到一些场景须要学习相干常识,或者就是单纯的集体感兴趣想理解一下原理和细节,最好的方法是什么呢?很简略,间接看相干团队的 Blog 或外围开发人员的 Blog & 演讲,这都是除去源码的第一手音讯,程度比那些二道贩子不晓得高到哪里去了。 The Cost Of JavaScript 明天的题目是 The Cost Of JavaScript,是作者 Addy Osmani 的系列 Blog 主题目,到往年为止一共写了 4 篇,从 开发者/内核/框架 等角度摸索如何优化 JS 执行老本。 Addy Osmani 何许人也?Google 工作 11 年,Chrome Developer Experience organization(Chrome DX 部门)的技术主管,这个 Title 很够重量了。 I am the engineering lead for Google Chrome's Developer Experience organization. Our projects include Chrome DevTools, Lighthouse, PageSpeed Insights and Chrome User Experience Report, Aurora and WordPress Performance. We recently shipped User Flows for DevTools and Lighthouse! ...

August 16, 2023 · 2 min · jiezi

关于前端:前端开发省时利器用dummyJSON快速构建模拟数据

在当今古代前端开发的畛域,模仿数据在测试、调试以及展现阶段施展着关键作用。然而,手动创立大量的模仿数据经常是繁琐而耗时的过程,而正是在这个问题上,DummyJSON 工具库应运而生。 DummyJSON 是一个收费的在线 REST API,只有您的前端网站或单页应用程序须要一些占位符数据,您就能够应用它,而无需运行任何服务器端代码。 这对初学者来说,让学习一个新的前端框架变得轻松不少。 在接下来的内容中,咱们将逐渐疏导您深刻理解 DummyJSON 的各个方面,帮忙您在前端开发的旅程中更进一步。 为什么要应用DummyJSON?大多数时候,当咱们创立一个用于学习或客户端的前端应用程序或网站时,咱们必须依赖后端来实现前端,或者如果咱们想创立一个简略的学习应用程序,咱们必须应用硬编码数据, 这会让整个学习过程变的很苦楚。 如果不通过硬编码的模式,咱们就须要每次都本人实现一套配套的后端服务。 这老本无疑是很高的。 DummyJSON , 就是为了降低成本而呈现的一个, 在线的版的 REST ful API 模仿网站。 网站: https://dummyjson.com/ DummyJSON 劣势无需注册,认证。 间接调用就能够应用。反对 GET、POST、PUT、PATCH 和 DELETE http 办法同时反对,HTTP 和 HTTPS 双协定与 React、Vue、Angular、Ember 和 vanilla JavaScript 等等 统统兼容DummyJSON 提供什么?DummyJSON 反对集体独立部署,同时也反对用户间接应用在线的API 。 整个 Mock server 提供了 8 类常见的场景API。次要场景有以下: 商品类 - 提供了 100条电商商品 mock 数据购物车类 - 20条 购物车数据以及相干API用户治理类博客文章类To Do 类登录注册类等等。 并且各种类别的API ,书写十分标准。 并配有应用示例。 如果,你不会写甚至能够间接复制粘贴。 还等什么赶快用起来吧!

August 16, 2023 · 1 min · jiezi

关于前端:小程序-CSSinJS-和原子化的另一种选择

小程序 CSS-in-JS 和原子化的另一种抉择小程序 CSS-in-JS 和原子化的另一种抉择 介绍疾速开始 pandacss 装置和配置 0. 装置和初始化 pandacss1. 配置 postcss2. 查看你的 panda.config.ts3. 批改 package.json 脚本4. 全局 css 注册 pandacss5. 配置的优化与别名weapp-pandacss 配置 0. 回到 postcss 进行注册1. 回到 package.json 增加生成脚本跨平台注意事项小程序预览事项高级配置文件配置项列表参考示例Bugs \& Issues介绍之前咱们写 tarojs 的利用的时候,想用CSS-in-JS 解决方案,就应用社区计划里举荐的 linaria, 这里我举荐另一种解决方案 pandacss。 pandacss 是个优良的 CSS-in-JS 编译时框架,相比 linaria,它的配置更加简略,智能提醒好,开发者体验也更好。 而且它也排汇了许多 tailwindcss 的长处,咱们能够自在的配置咱们的主题与款式,且原子化的类名也更容易进行自由组合。 weapp-pandacss 就是让你在小程序开发中应用它。 疾速开始pandacss 装置和配置0. 装置和初始化 pandacss首先咱们须要把 @pandacss/dev 这些都装置和配置好,这里咱们以 tarojs 我的项目为例: npm install -D @pandacss/dev weapp-pandacss postcss # 或者 yarn / pnpmnpx panda init此时会在当前目录生成一个 panda.config.ts 和一个蕴含大量文件的 styled-system。 ...

August 16, 2023 · 3 min · jiezi

关于前端:Big-IP-Edge-Client-里的-TLSv12

TLSv1.2 示意"Transport Layer Security version 1.2",是一种网络通信协定,用于在计算机网络上实现平安的数据传输。它是SSL(Secure Sockets Layer)协定的继任者,旨在确保网络连接的机密性和完整性。TLSv1.2 是一种加密协议,用于爱护敏感信息在网络中的传输,以避免窃听、数据篡改和其余网络攻击。 以下是对于TLSv1.2的简要解释和示例: TLSv1.2 的工作原理:TLSv1.2 应用加密和认证技术来爱护网络通信。当客户端(例如浏览器)与服务器建设连贯时,它们将协商应用的加密算法、密钥长度和其余平安参数。接下来,客户端和服务器之间的数据传输将通过这些协商的参数进行加密和解密,以确保数据在传输过程中不会被窃听或篡改。 示例:假如你正在应用一个Web浏览器,拜访一个须要登录的网站以查看个人账户信息。在这种状况下,TLSv1.2 将起到至关重要的作用,确保你的登录凭证和个人信息在传输过程中失去爱护。 握手协定:当你输出网站的URL并按下回车键时,浏览器将与该网站的服务器建设连贯。在连贯建设的过程中,TLSv1.2 的握手协定将开始执行。握手协定的指标是协商加密算法、密钥长度和其余平安参数。协商加密算法:浏览器和服务器将协商应用哪种加密算法来加密数据。TLSv1.2反对多种加密算法,如AES(Advanced Encryption Standard)和3DES(Triple Data Encryption Algorithm)。证书验证:服务器会向浏览器提供数字证书,以证实它的身份。浏览器将验证证书的有效性,确保连贯的指标是非法的服务器,而不是歹意的第三方。密钥替换:一旦证书验证胜利,浏览器和服务器将替换密钥。这些密钥用于数据的加密和解密过程。数据加密和传输:在连贯建设后,浏览器和服务器之间的数据传输将通过之前协商的加密算法进行加密和解密。这确保了数据在网络上传输时不会被窃听或篡改。在这个示例中,TLSv1.2 通过握手协定、加密算法、证书验证和密钥替换,确保了你在浏览器中输出的个人账户信息在与网站服务器之间的传输过程中失去爱护。这能够避免歹意用户从网络上窃取你的敏感信息。 综上所述,TLSv1.2 是一种用于爱护网络通信的协定,通过加密和认证技术来确保数据的机密性和完整性。在古代互联网中,TLSv1.2 在爱护用户隐衷和数据安全方面起着至关重要的作用。

August 16, 2023 · 1 min · jiezi

关于前端:Chrome-开发者工具里观察到的错误消息-net-ERRCONNECTIONRESET

关上网易邮箱,发现首页打不开,Chrome 开发者工具 console 面板看到如下的谬误音讯: net::ERR_CONNECTION_RESET net::ERR_CONNECTION_RESET 是一个常见的网络谬误,通常呈现在浏览器试图拜访网页时。这个谬误意味着在尝试拜访指标服务器时,TCP 连贯被忽然重置了。 首先,咱们必须了解什么是 TCP 连贯。TCP(传输控制协议) 是一种面向连贯的、牢靠的、基于字节流的传输层通信协议。当浏览器尝试拜访一个网页时,它会首先通过 TCP 协定与服务器建设一个连贯。如果这个连贯在数据传输过程中被忽然断开,就会呈现 net::ERR_CONNECTION_RESET 谬误。 net::ERR_CONNECTION_RESET 谬误有许多可能的起因。以下是一些常见的起因: 网络连接问题:如果你的网络连接不稳固,或者网络带宽有余,可能会导致 TCP 连贯被重置。服务器问题:如果服务器遇到问题,如过载或解体,也可能会断开 TCP 连贯。网络设备问题:例如,路由器、交换机或防火墙可能会因为各种起因中断 TCP 连贯。浏览器问题:浏览器或浏览器插件的谬误也可能导致此问题。代理服务器或 VPN:如果你正在应用代理服务器或 VPN,而它们的设置或状态有问题,也可能导致这个谬误。解决 net::ERR_CONNECTION_RESET 谬误的具体步骤取决于具体的起因。以下是一些可能的解决方案: 查看你的网络连接:确保你的网络连接是稳固和牢靠的。你能够尝试重新启动你的路由器或调整你的网络设备,看是否能解决问题。刷新页面或重启浏览器:有时候,简略地刷新页面或重启浏览器就能够解决问题。禁用或卸载可能有问题的浏览器插件:如果你狐疑问题可能由浏览器插件引起,能够尝试禁用或卸载它看看是否有帮忙。重置或更改你的代理服务器或 VPN 设置:如果你正在应用代理服务器或 VPN,能够尝试重置或更改它们的设置。分割网站管理员:如果你认为问题可能在服务器端,能够尝试分割网站管理员,看看他们是否能够解决问题。更新你的浏览器:有时候,旧版本的浏览器可能会呈现问题。确保你的浏览器是最新版本可能有助于解决问题。

August 16, 2023 · 1 min · jiezi

关于前端:三引用类型

前言本篇章次要介绍了援用类型的特点,诸如正则表达式、工夫类型、根本包装类、Object、数组等,至于function局部,内容较多,将另起篇章。面试答复1.援用类型:援用类型有array、object、function。援用类型属于堆内存,占用的空间不固定,保留和复制的是指针。援用类型罕用instanceof去判断,如果自身不晓得数据属于什么类型的话,就用object.prototype.toString.call办法去判断,不论是instanceof还是call办法,他们实质上都是通过原型链判断。 2.数组去重:最罕用的是利用Set这种数据结构,搭配Array.from或者扩大运算符来实现。至于其余形式,不论是利用indexOf、includes、sort(sort排序后雷同的元素会相邻),首先都会有一层遍历。 3.深浅拷贝:深浅拷贝的区别在于,浅拷贝只复制指针,新旧对象仍应用同一块内存。而深拷贝会创立一个截然不同的对象,开拓新的内存,因而批改新对象不会影响原对象。简略点,就用JSON.parse包裹着JSON.stringify,这种形式算深拷贝,因为它开拓了新的内存空间,只不过JSON.stringify会失落一些数据,比方undefined、function。精确点,就须要采取递归的形式去深拷贝,判断传入的数据是不是object,如果不是就抛出去,如果是那么就持续递归。 4.new关键字:new关键字先是创立新的对象,而后继承传入的函数原型,批改this指向并且执行构造函数,最初返回新的对象。 知识点援用类型都是堆(heap) ,有两个特色:1. 保留和复制都是指针。2.占用空间不固定(大小不定),也不会主动开释,堆内存中。 1.RegExp根本规定对于RegExp对象还是常常会应用到,比方限度input输入框(校验邮箱是否合乎)、匹配变量值做if判断等等。RegExp类型既能够通过字面量申明的形式创立,也能够通过new的形式创立; 字面量申明:/pattern/attributes ,例:let re1 = /ABC/g new申明:new RegExp(pattern, attributes),例let regex=new RegExp('/abc/',g) pattern既能够是正则表达式,也能够是字符串,如果是字符串,则如下: let reg = /hello/glet test = reg.test("hello World")console.log(test) // trueattributes为可选的字符串 ,含属性 "g"、"i" 和 "m",别离用于指定全局匹配、不辨别大小写的匹配和多行匹配 上面着重梳理几条规定,用来可能根本的辨认正则表达式,具体属性能够参考:RegExp根底规定 1./ xxx /g ,所有的正则表达式均写在/ /内,反斜杠代表本义,如\d,示意数字 2.^示意行的结尾,^\d示意必须以数字结尾 $示意行的完结,\d$示意必须以数字完结 有头有尾则必须完全符合规定才可匹配,如^\d{3}$则示意,间断三个数字才可匹配。 3.[]示意可能匹配的范畴,匹配的是单个字符 4.如果波及特殊字符如'-',在正则表达式中,要用'\-'本义,如,/^\d{3}\-\d{3,8}$/。 5.n{X,Y}示意至多呈现X个间断n ,至少呈现Y个间断n时,匹配。Y可不写。闭区间,含X,Y 6.*等于{0,} 即大于等于0次 ;+代表{1,} 即大于等于1次;?代表{0,1} 即0次或1次 7.用()示意的就是要提取的分组。比方:^(\d{3})\-(\d{3,8})$ 8.取反:[^abc],查找任何不在方括号之间的字符。 依据下面8条规定来辨认一下下述含意: let re = /^\d{3}\-\d{3,8}[0-9][a-z]$/;去掉//,主体为^\d{3}\-\d{3,8}$^,示意开始\d{3},示意间断三个数字\-,示意特殊字符-\d{3,8},示意至多间断3个数字至少间断8个数字[0-9],示意这个地位的字符必须为0-9[a-z],示意这个地位的字符必须为a-z$,示意完结罕用办法RegExp 对象有 4 个办法:test()、exec() 、compile()、match()。 test():test() 办法检索字符串中的指定值。返回值是 true 或 false。 match():match()办法返回值是合乎规定的值(数组)。 ...

August 16, 2023 · 6 min · jiezi

关于前端:二基础类型

前言本篇博客旨在清晰意识JS六种根底类型以及特色。面试答复根底类型:值类型有string、number、Boolean、undefined、null、Symbol。值类型是栈内存,占用空间固定,保留和复制的是值自身。个别咱们用typeof去判断值类型,不过不能用来判断null,因为null在内存中属于援用类型,只不过因为不便效率所以归为值类型。至于typeof的检测原理,波及信息贮存和机器码的问题,就没有深刻了。知识点根底类型都是栈(stack),简略了解一下,有两个特色:1. 保留和复制值的自身。2.占用空间固定, 栈内存中,由操作系统主动分配内存空间,主动开释。 1.Boolean对于Boolean类型就一句话:undefined、null、""、0、NaN、false除了这6个值在js中属于假值,其余均为真值。 2.Undefined定义undefined 示意申明了变量但未对其初始化时赋予该变量值的返回值。 利用场景1.返回undefined场景 //变量被申明了,但没有赋值时,返回undefinedlet i ;i //undefined//调用函数时,应该提供的参数没有提供,该参数为undefinedfunction f(x){ console.log(x)}f()//undefined//对象没有赋值的属性,该属性的值为undefinedlet j = {}j.p // undefined//函数没有返回值时,默认返回undefinedlet x = function z(){}x //undefined3.Null定义已定义,且示意"无"的值 对于null与undefined的异同能够从内存角度看:null在内存里属于援用类型,undefined在内存里属于根本类型。所以typeof null 的输入为Object,typeof undefined 的输入为undefined。之所以把null归为根本类型,是因为"效率"。当然,日常开发中,为了方便使用,将null了解为:申明并赋值的变量,该变量的值为null;将undefined了解为:申明变量,但没有赋值的返回值 4.Number利用场景1.精度问题 JavaScript 采纳“IEEE 754 规范定义的双精度64位格局” ,所以会呈现精度缺失的异常情况。 解决办法: 乘除法 //0.1+0.2 !== 0.3let number = 0.1*10+0.2*10let trueNumber = number/10 //0.3toFixed(n):保留n位小数,不精确,且n不能过大。 //0.1+0.2!== 0.3。let number = 0.1+0.2let trueNumber = number.toFixed(2) //'0.30' string类型 ,2.增加千分位 toLocaleString() let num = 10000000 //输出必须是number类型num.toLocaleString()//"10,000,000" 输入的是字符串当然简单非凡的增加千分号就不满足了,须要自定义,思路如下: 1、对立解决为字符串:JSON.stringify(a)2、切割整数和小数3、将整数局部颠倒,不便插入","4、for循环,每三位插入5、将整数局部颠倒回原样,并加上小数局部function transfor(data){ //1 if(typeof data === 'number'){ data = JSON.stringify(data) } //2、3 let integer = data.split('.')[0].split('').reverse() let decimal = data.split('.')[1] let num = '' //4 for(let i=0;i<integer.length;i++){ if((i+1)%3 === 0 && (i+1) !==integer.length ){ num += integer[i] + ',' }else{ num += integer[i] } } //5 num = num.split('').reverse().join('') if(decimal){ num = num +'.' + decimal }else{ num = num +'.00' } return num }console.log(transfor(1000000))//1,000,000.005.String罕用APIindexOf(): 返回字符串中指定文本首次呈现的索引地位 ...

August 16, 2023 · 2 min · jiezi

关于前端:表格JS实现在线Excel的附件上传与下载

摘要:本文由葡萄城技术团队于思否原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供业余的开发工具、解决方案和服务,赋能开发者。前言在本地应用Excel时,常常会有须要在Excel中增加一些附件文件的需要,例如在Excel中附带一些Word,CAD图等等。同样的,类比到Web端,当初很多人用的在线Excel是否也能够像本地一样实现附件文件的操作呢?答案是必定的,不过和本地不同的是,Web端不会间接关上附件,而是应用超链接单元格的模式来显示,明天小编将为大家介绍应用前端HTML+JS+CSS技术通过超链接单元格的模式实现在线Excel附件上传、下载和批改的操作。 应用JS实现附件上传实现的形式分为四个步骤: 1.创立前端页面 2编写暂存附件信息的办法 3.编写附件文件革除的办法 4.编写文件保留和文件加载的办法 1.创立前端页面外围代码: <div style="margin-bottom: 8px"><button id="uploadAttach">上传附件</button><button id="removeAttach">革除附件</button><button id="fileSaver">文件保留</button><button id="loadSubmitFile">加载文件</button><button id="loadPackage">打包下载</button></div><div id="fileOperate" style="visibility: hidden;position: absolute;top: 100px;left: 300px;z-index: 10; background-color: #eee;padding: 16px"><label for="choseFile">抉择文件\</label><input type="file" id="choseFile" name="choseFile"/><button id="submit">提交</button><button id="cancel">勾销</button></div>点击上传附件按钮能够把附件上传到对应的单元格,革除附件会清理掉所有曾经上传过的附件信息,打包下载会对所有的附件进行对立下载。 2.暂存附件信息办法这一步起始次要用来设置文件上传之后单元格超链接及tag信息。仔细的同学会留神到,这里我注册了一个命令,超链接自身会有一个跳转的行为,写command之后,会阻止这个默认跳转,转去执行对应的命令。注册的命令次要就是用来做附件文件的下载。 外围代码: function hasAttachFile(sheet,row,col,file){\*\*\* 附件文件暂存\* 这里因为没有服务端,所以我间接存了File对象,但File对象只有在理论应用时才会去获取理论的文件内容。在demo中可行\* 在理论我的项目中,须要将file对象上传到文件服务器中\* 上传实现后tag中的fileInfo应该代表的是文件的拜访地址,而不能再是File对象。\*sheet.setValue(row,col,file.name)sheet.setTag(row,col,{type: hyerlinkType,fileInfo: file // 理论我的项目中fileInfo应该为上传实现文件的拜访门路})sheet.setHyperlink(row, col, {url: file.name,linkColor: '#0066cc',visitedLinkColor: '#3399ff',drawUnderline: true,command:'downloadAttachFile',}, GC.Spread.Sheets.SheetArea.viewport);}在这里,我引入了三方组件库FileSaver,在点击超链接单元格时,能够反对以后附件文件的下载。 // 下载文件spread.commandManager().register("downloadAttachFile",{canUndo: false,execute: function(context,options,isUndo){let sheet = context.getActiveSheet()let row = sheet.getActiveRowIndex()let col = sheet.getActiveColumnIndex()let cellTag = sheet.getTag(row,col)console.log(sheet,row,col,cellTag)if(cellTag && cellTag.type==hyerlinkType){\*\*\*\* 纯前端demo,文件存在于本地,fileInfo中存储的是File对象,能够间接获取到文件\* 理论我的项目中,fileInfo应该是上传到文件服务器上的文件拜访地址。\* 因而这里须要发送申请,先获取文件blob,将获取的blob传递到saveAs的第二个参数中。\*saveAs(cellTag.fileInfo,cellTag.fileInfo.name)}}})3. 附件文件革除document.getElementById("removeAttach").onclick = function(){\*\*\*\* 革除附件\* 革除附件须要先删除近程文件服务器的文件,之后革除单元格的Tag信息。\* 这里前端演示demo,只删除了tag。\* 理论我的项目中tag中的fileInfo应该是文件上传后的门路\*let sheet = spread.getActiveSheet()let row = sheet.getActiveRowIndex()let col = sheet.getActiveColumnIndex()spread.commandManager().execute({cmd:"removeAttachFile",sheet,row,col})}4. 文件保留/加载将文件保留成为JSON构造: ...

August 16, 2023 · 1 min · jiezi

关于前端:Typescript-协变与逆变转换联合类型为交叉类型

最近在搬砖的时候,遇到一个场景,须要依据已存在的联结类型,将其转为穿插类型: type Preson = { name: string} | { age: number} | { needMoney: boolean}type Result = Uinon2Intersection<Preson>冀望通过 Uinon2Intersection 转换后,失去的 Result: type Result = { name: string} & { age: number} & { needMoney: boolean}刚开始感觉很简略。我想曾经会了类型体操根本动作四件套了。通过遍历联结类型,而后遍历的时候通过 key 读取属性值就行了,我啪啪啪就写进去了,就像这样: type U2I<T> = { [key in keyof T]: T[key]}type Result = U2I<Preson>理论失去的是: type Result = U2I<{ name: string;}> | U2I<{ age: number;}> | U2I<{ needMoney: boolean;}>Nmmm,这齐全不是我冀望的样子啊,而后又想了想根底四件套,感觉遇到坑了,如同仅靠四件套并不能解决啊。 先说下,下面这种状况是因为对于联结类型,在遍历操作或者进行条件类型判断的时候,会产生类型调配。就像上面: type ToArray<Type> = Type extends any ? Type[] : never;type StrArrOrNumArr = ToArray<string | number>;其实失去: ...

August 16, 2023 · 4 min · jiezi

关于前端:JavaScript-时间格式化函数

性能获取工夫戳格式化工夫=========================================================== 残缺代码 // _date 为须要格式化的日期,format 为须要格式化的款式function formatDate(_date, format) { const date = new Date(_date); switch (format) { case 'yyyy': return date.getFullYear(); case 'yy': return ('' + date.getFullYear).slice(-2); case 'M': return date.getMonth() + 1; case 'MM': return ('0' + date.getMonth()).slice(-2); case 'd': return date.getDate(); case 'dd': return ('0' + date.getDate()).slice(-2); case 'H': return date.getHours(); case 'HH': return ('0' + date.getHours()).slice(-2); case 'h': return date.getHours() % 12; case 'hh': return ('0' + date.getHours()).slice(-2); case 'm': return date.getMinutes(); case 'mm': return ('0' + date.getMinutes()).slice(-2); case 's': return date.getSeconds(); case 'ss': return ('0' + date.getSeconds()).slice(-2); case 'w': return ['日', '一', '二', '三', '四', '五', '六'][date.getDay()]; case 'stamp' /* 获取工夫戳 */: return Date.now(); default: return; }}应用 ...

August 15, 2023 · 1 min · jiezi

关于前端:使用-tailwindcsspatch2-来提取你的类名吧

应用 tailwindcss-patch@2 来提取你的类名吧应用 tailwindcss-patch@2 来提取你的类名吧 装置应用形式 命令行 Cli 开始提取吧Nodejs API 的形式来应用配置 初始化What's next?tailwindcss-patch 是一个 tailwindcss 生态的扩大我的项目。也是 tailwindcss-mangle 我的项目重要的组成部分。 最近我公布了 tailwindcss-patch 的 2.x 版本,次要增加了一个配置文件读取和工具类名提取额性能。 让咱们来看看怎么应用它吧。 装置抉择你喜爱的包管理器 <yarn|npm|pnpm> add -D tailwindcss-patch给 tailwindcss 打补丁npx tw-patch install在 npm 的 prepare hook 里退出指令package.json { /* ... */ "scripts": { "prepare": "tw-patch install" }}应用形式命令行 Cli开始提取吧npx tw-patch extract默认状况下,执行胜利后会有一个 json 文件 .tw-patch/tw-class-list.json 在你的我的项目中呈现。 当然,你能够通过配置文件 tailwindcss-mangle.config.ts 来自定义这个行为。 Nodejs API 的形式来应用import { TailwindcssPatcher } from 'tailwindcss-patch'const twPatcher = new TailwindcssPatcher(/* options */)// do patchtwPatcher.patch()// get all contexts at runtimetwPatcher.getContexts()// get all class generated by tailwindcss utilitiestwPatcher.getClassSet()配置初始化npx tw-patch init这样在你的以后的 cwd 中就会呈现一个 tailwindcss-mangle.config.ts 文件: ...

August 15, 2023 · 1 min · jiezi

关于前端:智能标签系统如何助力智能推送服务

智能推送零碎介绍 智能推送零碎是一种利用人工智能和大数据等技术,依据用户的需要、趣味、行为等信息,自动化地向用户推送个性化内容的零碎。它能够通过用户画像、历史行为、实时数据等多种数据源的剖析和开掘,为每个用户提供具备高度相关性和个性化的推送内容。 MobPush就是一款智能化推送零碎,它是由MobTech推出的一款收费的推送服务工具,客户端SDK反对iOS和Android两大平台,集成不便简略快捷,且提供残缺的可视化数据和弱小的治理后盾。它领有收费应用、自定义UI、服务稳固牢靠、7*24小时的业余技术服务反对、SDK体积小、平面数据统计等劣势。 智能标签零碎在智能推送零碎(MobPush)中如何利用? 在MobPush的功能模块中,Push2.0级的智能标签零碎的推出全面变革了推送的场景反对。MobPush所提供的智能标签零碎,标签维度要比同类产品深入整整一个层级。 智能标签零碎的性能如果用一句话概括,那就是“适合内容+适合工夫+适合用户”。 当用户接入App后,MobPush不仅可能依据用户的性别、职业、常驻地等根底属性来构建用户画像,还能从用户的网络沉闷、线上趣味等标签进行2级塑造,疾速判断出用户是手游达人、松软驴友还是抖音达人等等状态,最终构建出十几个维度的综合数据画像,并同步可视化输入。这样就能让开发者实时把握用户在不同工夫的趣味。 这样一来,App推送能够与智能场景深度交融,开发者就可能依据App的不同需要与用户的不同需要,疾速辨认用户推送场景,进行最无效的推送内容和流动营销,用户能够第一工夫看到价值信息,在最高需要点取得本人感兴趣的信息,疾速减少产品粘性,达到用户与App双赢的后果。 此外,MobPush还进一步欠缺了开发者经营治理平台,买通了推送、画像、统计等一系列功能模块,开发者能够实时观测到推送、回流、卸载、唤起等多方位数据。 领有智能标签零碎加持的MobPush可能帮忙开发者更加理解产品本身、理解受众特色,造成数据智能和场景驱动联合的服务体系,辅助App精细化经营,但智能推送零碎能带来的益处远远不止这些。 那么,智能推送零碎还可能给平台带来哪些帮忙呢? 进步用户参与度和留存率:通过智能推送,平台能够向用户提供个性化、相关性高的内容,减少用户的趣味和参与度。用户更容易受到推送的吸引,进步用户的留存率。优化用户体验:智能推送可能依据用户的趣味和行为,向其推送合乎其需要的内容,并尽量避免推送与用户无关的信息。这样能够晋升用户的满意度,优化用户体验。进步转化率和销售额:通过智能推送,平台能够针对用户的需要和购买偏好,精准推送相干产品和优惠信息,激发用户的购买欲望,进步转化率和销售额。升高营销老本和提高效率:智能推送能够依据用户的画像和行为自动化地进行推送,缩小人工干预的老本和工作量,进步推送的效率。相比传统的营销形式,节俭了人力、工夫和资源。建设用户粘性和品牌忠诚度:通过对用户的个性化推送和关心,平台能够建设用户与平台的粘性,减少用户的忠诚度和二次购买的可能性。用户在平台上失去称心的体验和服务,更偏向于长期应用和举荐。改善用户反馈和用户行为剖析:智能推送能够剖析用户的反馈数据和行为数据,能够深刻理解用户的需要和偏好,改善产品和服务,进一步晋升用户体验和平台的竞争力。智能推送零碎带来的这些帮忙对于平台的倒退和增长十分重要,而在智能推送零碎的抉择中,MobPush相对是其中最优的第一抉择。

August 15, 2023 · 1 min · jiezi

关于前端:如何唤醒潜在用户选择智能化推送系统的重要性

智能化推送零碎是什么?智能化推送零碎是一种基于人工智能和数据分析的零碎,旨在依据用户的趣味、行为和偏好,主动向其推送个性化的信息、内容或推广信息。 智能化推送零碎的指标是提供更好的用户体验和个性化服务。它能够帮忙用户发现新的趣味点、获取个性化的举荐内容,并进步用户对信息的满意度。同时,对于营销和广告畛域,智能化推送零碎也可能帮忙企业精准地将广告和促销信息传递给潜在客户,进步营销成果和ROI回报率。 智能化推送零碎的运作机制是什么? 数据处理和剖析:将收集到的用户数据通过解决和剖析,应用机器学习、数据挖掘和人工智能等技术,辨认用户的特点、趣味和需要。这些解决和剖析过程能够包含用户行为模型建设、趣味标签的生成、类似用户群体的聚类等。个性化举荐算法:零碎会依据用户的特色和剖析后果,应用个性化举荐算法来确定适合的推送内容。这些算法包含了协同过滤、内容过滤、基于关联规定的举荐等不同的办法。推送内容生成:零碎依据个性化举荐算法确定的内容,生成推送给用户个性化信息与文案。这能够包含文章、新闻、商品、广告等各种模式的内容。推送和反馈:零碎通过各种渠道,如推送告诉、电子邮件、短信等形式,向用户发送推送内容。用户收到推送后能够进行反馈,如点击、购买、评论等行为。零碎会依据用户的反馈来收集用户信息与偏好。迭代优化:零碎依据用户的反馈和行为数据,一直进行评估和优化,进步举荐的准确性和个性化水平,进行推送内容的一直迭代。智能化推送零碎通过数据收集、解决和剖析,应用个性化举荐算法来确定推送内容,而后通过适合的渠道将内容发送给用户,并依据用户反馈进行迭代优化,以提供更好的个性化体验。 智能化精准推送如何唤醒潜在用户? 数据分析与用户画像:通过对用户的行为数据和趣味偏好进行剖析,建设用户画像。理解用户的购买历史、浏览偏好、搜寻关键词等信息,以精确把握用户的趣味和需要,并在推送中针对性地满足其需要。个性化举荐:依据用户的兴趣爱好和行为习惯,定制化地推送合乎用户需要的个性化内容。利用智能举荐算法,依据用户的历史行为和类似用户的行为,推送相干产品、文章、流动等内容,从而吸引用户的趣味。行为触发推送:通过对用户行为的实时监测,及时触发相应的推送音讯。例如,当用户在网站上将商品增加到购物车但未付款时,能够基于此行为触发一条揭示推送,激发用户实现购买。社交化推送:基于用户社交网络的数据,将个性化推送与社交因素相结合。例如,将好友已购买的产品或好友的举荐发送给用户,以减少举荐的可信度和影响力,激发用户的购买欲望。定时揭示和流动促销:依据用户的购买习惯和行为数据,抉择适合的工夫点和形式进行推送,揭示用户关注限时促销流动、行将完结的特价商品等。在推送中重视营造紧迫感,引起用户的趣味和口头。A/B测试和数据分析:通过A/B测试,比拟不同推送策略的成果,抉择最优的推送形式。同时,通过数据分析和追踪,理解用户的反馈和行为变动,针对性地优化推送策略,继续晋升唤醒成果。由此可见,抉择智能化推送零碎对于唤醒潜在用户来说还是十分必要的,智能化推送不仅能进步用户体验,同时也能晋升营销成果,帮忙平台减少效益。 MobPush就是一款智能化推送零碎,它是由MobTech推出的一款收费的推送服务工具,客户端SDK反对iOS和Android两大平台,集成不便简略快捷,且提供残缺的可视化数据和弱小的治理后盾。它领有收费应用、自定义UI、服务稳固牢靠、7*24小时的业余技术服务反对、SDK体积小、平面数据统计等劣势。它能够帮忙开发者疾速集成实现推送性能,实现智能化精准推送,精准把握用户偏好,唤醒潜在用户的趣味,减少用户点击率,晋升用户活跃度,减少用户参加和转化的可能性,无效唤醒沉睡用户。

August 15, 2023 · 1 min · jiezi

关于前端:图扑数字孪生智慧乡村综合管控平台

数字农村是随同网络化、信息化和数字化在农业农村经济社会倒退中的利用,既是农村振兴的策略方向,也是建设数字中国的重要内容。为了进一步晋升农村治理智能化、专业化程度,解决建设顶层缺失、数据孤岛等问题,数字孪生技术被广泛应用于数字农村建设中。 听涛观海忆红帆,品鲜问渔游巴斗。弶港镇巴斗村,位于江苏省东台市黄海之滨,毗连黄海国家森林公园、世界天然遗产地 —— 条子泥,是中国人民海军起锚地,获评“江苏漂亮农村”、“江苏农村游览重点村”,入选江苏省第六批次特色田园农村名单,有“渔文化第一村”的美誉。 通过图扑软件 HT 弱小的渲染引擎,1:1 建模还原巴斗村全貌,从走近巴斗、数字安防、智慧康养、巴斗游览四大模块,建设起具备场景化、智能化、人性化的智慧农村综合管控平台,为管理者提供多元化、多角度、多数据的治理与决策依据。 走近巴斗基于 Web 3D 开发技术搭建的智慧农村,将农村内的修建、路线、河流、绿化等各种设施设施依照 1:1 建模还原。通过图扑软件 HT 自研引擎,并联合 PBR 物理渲染材质零碎,渲染出实在的农村环境成果。 收场以第一人称的模式,围绕着农村场景进行主动漫游展现,让用户好像置身于农村场景之中。图扑同样反对导入 IFC 格局的 BIM 模型文件生成场景,或渲染 3D Tiles 格局的歪斜摄影模型文件。 两侧展现巴斗村相干介绍和宣传视频,使用户更加深刻理解巴斗村的历史及游览信息。同时,接入当地天气、当日康养保障医生、老年人数量与散布统计,帮忙村委会和居民理解当天信息。 数字安防随着城市智慧化建设进度放慢,数字安防在农村建设中的重要性不容忽视。通过数字安防技术的利用,能够晋升农村的平安防备能力,预防和打击犯罪流动,爱护农村资源和环境,促成农村的倒退。 图扑 HT 通过参考现场理论监控点位,在三维场景中按点摆放监控模型,还原现场监控状况,让用户对现场监控点位安排状况高深莫测。通过与监控视频流的对接,实现在三维场景中任意交互某一监控模型,均可调用以后摄像头监控画面。 传统监控画面调用形式通常是通过抉择列表,很难将分镜头视频与理论地理位置绝对应,无奈对大场景进行无效直观的实时监测,不足态势感知。通过联合图扑三维场景的点位劣势,让用户对现场状况有着更清晰直观地理解。 联合摄像头算法,对农村人员进行定位和辨认,并联合图扑可视化引擎,将人员地位实时显示在三维场景中,处理过程如下: 摄像头部署:在须要进行人员定位的区域抉择适当的地位和角度来部署摄像头。摄像头数量和地位的抉择要依据具体的定位需要和场景来确定,确保可能全方位地监测到指标区域。视频采集与解决:摄像头开始采集视频,并将视频传输到后盾进行解决。视频解决能够应用计算机视觉和图像处理算法,对视频进行剖析和提取要害信息。人体检测与辨认算法:通过应用人体检测算法,能够辨认摄像头图像中的人体指标。对于人员定位来说,能够应用行人检测算法,将人体指标从其余物体中辨别进去。人脸识别算法:应用人脸识别算法对摄像头检测到的人体指标进行进一步的辨认。这些算法通常采纳深度学习和神经网络等技术,可能对人脸进行精确的辨认和匹配。地位确定与跟踪:联合摄像头视角和图像剖析后果,能够确定被辨认人体指标的地位,并进行实时跟踪。依据摄像头的地位和角度,能够计算出人体指标在天文区域中的具体位置。数据展现:通过数据可视化技术,将人员定位的后果以模型、图标等模式进行展现。能够实时显示人员地位信息,记录人员的静止轨迹,以及统计人员在不同区域的停留时间等。 图扑软件(Hightopo)还可实现视频交融解决方案。将 2D 图像交融到场景的 3D 模型中,为用户提供直观的视频图像和简略的视图管制。HT 视频交融技术采纳 WebGL 技术, 利用 GPU 高性能计算能力对视频图像进行实时处理,图像处理不占用 CPU 资源,整个计划画面晦涩。 智慧康养农村老龄化人口居多,衰弱问题在农村治理中起到重要作用,智慧康养旨在提供农村居民便捷的康养服务,促成居民的衰弱和幸福。 实现智慧康养,须要搭建相应的基础设施,包含网络覆盖、传感器设施、信息管理平台等。通过建设高速、稳固的网络,将农村与外界连接起来,为康养模块提供数据传输和通信性能。设置传感器设施监测人员的健康状况和环境条件,并将数据上传到信息管理平台进行剖析和治理。同时,提供衰弱监测与治理性能,包含定期衰弱体检、智能医疗设施(如电子血压计、体温计等)等。通过连贯这些设施,能够实时监测农村居民的健康状况,揭示他们进行衰弱治理,为医护人员提供参考和决策依据。 图扑智慧农村可视化平台,通过接入衰弱信息管理平台,将居民信息集成管控,并融入到三维场景中直观展现,蕴含以下内容: 衰弱实时数据:展现居民最近心率、体温、血压数据,并对异样进行统计。体温、血压、心率异样列表:展现居民衰弱异常情况,并联合 3D 定位,在 3D 场景中高亮显示,不便村委管理人员进行跟踪。在外务工人员,可通过该平台实时理解家中前辈健康状况,图扑 HT 反对手机、Pad 等挪动终端,也能随时随地查看家中前辈的体温、血压、心率等衰弱指标,无论身处何地都不会错过任何重要的衰弱变动。 农村游览可视化通过图扑 3D 可视化平台,针对重点的景点、建筑物进行精细化建模,为三维模型进行纹理贴图,使其具备更加真切的外观。能够利用实在的贴图资料、光照成果等,加强模型的真实感和视觉效果。同时,利用渲染技术,如暗影渲染、光照模仿等,进步模型的逼真度,展现农村的游览资源和特色。 ...

August 15, 2023 · 1 min · jiezi

关于前端:图扑数字孪生智慧乡村综合管控平台

数字农村是随同网络化、信息化和数字化在农业农村经济社会倒退中的利用,既是农村振兴的策略方向,也是建设数字中国的重要内容。为了进一步晋升农村治理智能化、专业化程度,解决建设顶层缺失、数据孤岛等问题,数字孪生技术被广泛应用于数字农村建设中。 听涛观海忆红帆,品鲜问渔游巴斗。弶港镇巴斗村,位于江苏省东台市黄海之滨,毗连黄海国家森林公园、世界天然遗产地 —— 条子泥,是中国人民海军起锚地,获评“江苏漂亮农村”、“江苏农村游览重点村”,入选江苏省第六批次特色田园农村名单,有“渔文化第一村”的美誉。 通过图扑软件 HT 弱小的渲染引擎,1:1 建模还原巴斗村全貌,从走近巴斗、数字安防、智慧康养、巴斗游览四大模块,建设起具备场景化、智能化、人性化的智慧农村综合管控平台,为管理者提供多元化、多角度、多数据的治理与决策依据。 走近巴斗基于 Web 3D 开发技术搭建的智慧农村,将农村内的修建、路线、河流、绿化等各种设施设施依照 1:1 建模还原。通过图扑软件 HT 自研引擎,并联合 PBR 物理渲染材质零碎,渲染出实在的农村环境成果。 收场以第一人称的模式,围绕着农村场景进行主动漫游展现,让用户好像置身于农村场景之中。图扑同样反对导入 IFC 格局的 BIM 模型文件生成场景,或渲染 3D Tiles 格局的歪斜摄影模型文件。 两侧展现巴斗村相干介绍和宣传视频,使用户更加深刻理解巴斗村的历史及游览信息。同时,接入当地天气、当日康养保障医生、老年人数量与散布统计,帮忙村委会和居民理解当天信息。 数字安防随着城市智慧化建设进度放慢,数字安防在农村建设中的重要性不容忽视。通过数字安防技术的利用,能够晋升农村的平安防备能力,预防和打击犯罪流动,爱护农村资源和环境,促成农村的倒退。 图扑 HT 通过参考现场理论监控点位,在三维场景中按点摆放监控模型,还原现场监控状况,让用户对现场监控点位安排状况高深莫测。通过与监控视频流的对接,实现在三维场景中任意交互某一监控模型,均可调用以后摄像头监控画面。 传统监控画面调用形式通常是通过抉择列表,很难将分镜头视频与理论地理位置绝对应,无奈对大场景进行无效直观的实时监测,不足态势感知。通过联合图扑三维场景的点位劣势,让用户对现场状况有着更清晰直观地理解。 联合摄像头算法,对农村人员进行定位和辨认,并联合图扑可视化引擎,将人员地位实时显示在三维场景中,处理过程如下: 摄像头部署:在须要进行人员定位的区域抉择适当的地位和角度来部署摄像头。摄像头数量和地位的抉择要依据具体的定位需要和场景来确定,确保可能全方位地监测到指标区域。视频采集与解决:摄像头开始采集视频,并将视频传输到后盾进行解决。视频解决能够应用计算机视觉和图像处理算法,对视频进行剖析和提取要害信息。人体检测与辨认算法:通过应用人体检测算法,能够辨认摄像头图像中的人体指标。对于人员定位来说,能够应用行人检测算法,将人体指标从其余物体中辨别进去。人脸识别算法:应用人脸识别算法对摄像头检测到的人体指标进行进一步的辨认。这些算法通常采纳深度学习和神经网络等技术,可能对人脸进行精确的辨认和匹配。地位确定与跟踪:联合摄像头视角和图像剖析后果,能够确定被辨认人体指标的地位,并进行实时跟踪。依据摄像头的地位和角度,能够计算出人体指标在天文区域中的具体位置。数据展现:通过数据可视化技术,将人员定位的后果以模型、图标等模式进行展现。能够实时显示人员地位信息,记录人员的静止轨迹,以及统计人员在不同区域的停留时间等。 图扑软件(Hightopo)还可实现视频交融解决方案。将 2D 图像交融到场景的 3D 模型中,为用户提供直观的视频图像和简略的视图管制。HT 视频交融技术采纳 WebGL 技术, 利用 GPU 高性能计算能力对视频图像进行实时处理,图像处理不占用 CPU 资源,整个计划画面晦涩。 智慧康养农村老龄化人口居多,衰弱问题在农村治理中起到重要作用,智慧康养旨在提供农村居民便捷的康养服务,促成居民的衰弱和幸福。 实现智慧康养,须要搭建相应的基础设施,包含网络覆盖、传感器设施、信息管理平台等。通过建设高速、稳固的网络,将农村与外界连接起来,为康养模块提供数据传输和通信性能。设置传感器设施监测人员的健康状况和环境条件,并将数据上传到信息管理平台进行剖析和治理。同时,提供衰弱监测与治理性能,包含定期衰弱体检、智能医疗设施(如电子血压计、体温计等)等。通过连贯这些设施,能够实时监测农村居民的健康状况,揭示他们进行衰弱治理,为医护人员提供参考和决策依据。 图扑智慧农村可视化平台,通过接入衰弱信息管理平台,将居民信息集成管控,并融入到三维场景中直观展现,蕴含以下内容: 衰弱实时数据:展现居民最近心率、体温、血压数据,并对异样进行统计。体温、血压、心率异样列表:展现居民衰弱异常情况,并联合 3D 定位,在 3D 场景中高亮显示,不便村委管理人员进行跟踪。在外务工人员,可通过该平台实时理解家中前辈健康状况,图扑 HT 反对手机、Pad 等挪动终端,也能随时随地查看家中前辈的体温、血压、心率等衰弱指标,无论身处何地都不会错过任何重要的衰弱变动。 农村游览可视化通过图扑 3D 可视化平台,针对重点的景点、建筑物进行精细化建模,为三维模型进行纹理贴图,使其具备更加真切的外观。能够利用实在的贴图资料、光照成果等,加强模型的真实感和视觉效果。同时,利用渲染技术,如暗影渲染、光照模仿等,进步模型的逼真度,展现农村的游览资源和特色。 ...

August 15, 2023 · 1 min · jiezi

关于前端:克服-ClickHouse-运维难题ByteHouse-水平扩容功能上线

前言 对于剖析型数据库产品,通过减少服务节点实现集群程度扩容,并晋升集群性能和容量,是运维的必要伎俩。然而对于相熟 ClickHouse 的工程师而言,听到“扩容”二字肯定会头疼不已。开源 ClickHouse 的 MPP 架构导致扩容老本高,已是 ClickHouse 运维的外围痛点。 次要体现在:·流程全手动,无数据可靠性保障。·扩容期间性能开销大,通常须要暂停服务。 基于字节跳动内宽泛的应用场景,ByteHouse 企业版基于开源社区 ClickHouse 进行了诸多优化,现已正式公测“程度扩容”性能。如果将“ClickHouse”比作一辆汽车,那么此次ByteHouse降级则实现了扩容“手动挡”变“自动挡”,同时“自动档"过程中还能省油减速,使得扩容整体操作更顺滑晦涩。 开源社区的实现计划在 开源社区文档 中,社区工程师通常举荐应用“数据重散布”思路来解决扩容问题,但存在以下问题:1.新增节点后,手动晋升新节点的导入权重,或临时进行旧节点的数据导入,直至数据平衡。这种配置要求 Distributed 表的分片键(Sharding-key)设置为 random,对于设定了指定的 sharding-key 的表,无奈采纳这种模式。此外,如果存量数据很大,通过该形式实现平衡十分迟缓,可能破费数天乃至数个月能力追平。2.手动在节点之间挪动分区,使节点间平衡。该形式须要大表均已设置比拟正当的分区键(Partition Key),并且分片键也只能为 Random,并且须要手动计算分区的挪动指标节点。3.应用 ClickHouse Copier或 Insert Into Select 形式,将现存表全副从新插入实现平衡。该形式开销十分高,将占用大量的 CPU / 存储 IO / 网络 IO 资源。此外,不论是哪种形式,都须要用户手动在新节点复制元数据、校验数据,拼装各环节流程,因而被称为“手动挡”。 ByteHouse 的优化计划 在字节跳动外部,业务的快速增长带来集群布局性能有余、亟需扩容的问题。ByteHouse 对内次要撑持数据看板、用户行为剖析性等业务模块,因而对服务继续在线、性能迅速晋升要求高,并且用户表的表构造也异样丰盛。因而,社区提供的计划均不能满足字节外部业务诉求。基于以上背景,ByteHouse 自研集群扩容能力,解决自动化流程的问题,也为用户提供了性能开销更低的扩容形式。具体咱们通过数据库引擎优化和操作界面优化两方面来实现。**数据库引擎优化ByteHouse 的数据库引擎自研 Alter Table...Resharding命令,将一张表以分区的粒度进行重散布到另一张表。该命令反对两种形式:·重散布到其余集群的另一张表·重散布到本集群的另一张表命令格局如下:alter table <db>.<table> resharding partition <partition_expr> with <sharding_expr> to shard [shard_list]通过该命令,能够实现提交从源表扩容到指标表的工作,该工作将实现 Split - Fetch,在原表拆分 Part,指标表拉取 Part,实现扩容。具体操作步骤如下:1.对于要扩容的表 table,新建指标表,如 table1_new;2.提交 Alter Table table1 Resharding Partition <partition_expr> with <sharding_expr> to table [table1_new_list];的工作会被存储到 ZooKeeper 上,后盾线程负责调度执行;3.所有提交的工作一一开始执行。每个工作首先执行 Part 拆分,将一个 Part 依据 Sharding-key 拆分为 N 份(N 为扩容后的分片数);4.Part 拆分完结后,将 Part 信息公布到对应的分片上,对应不同分片上的指标表 table1_new 会进入 FETCHING 状态,开始拉取 Part;5.期待这些 Part 被拉取实现,而后开始执行下一个工作,直至一张表的所有 Part 都被重散布实现在一张表实现后,能够进行校验数据,删除旧表(table1),重命名新表(table1_new -> table1)。实现了一张表的扩容。扩容全程能够通过零碎表 system.reshard_partition追踪进度,获得状态。这种扩容形式相比社区举荐的形式,有以下劣势:1.扩容的适应性好,对于是否设置分片键、分区键,均无硬性要求,都能够进行扩容。2.性能损耗小。整个重散布过程为一个旁路计算工作,开销远低于insert into select 全局数据从新插入的形式。3.执行过程中,数据放弃可查问,上游数据看板、数据分析等服务不必暂停。目前在扩容过程中,ByteHouse临时不反对写入。但就原理而言,扩容进度90%前都可写入,只须要最初阶段一次性 Resharding 在扩容工作执行过程中新写入的 Part 即可。因而,ByteHouse将来性能也有持续晋升的空间。 ...

July 13, 2023 · 1 min · jiezi

关于前端:Elementui-Switch-开关

Element-ui Switch 开关原文链接:https://note.noxussj.top/?source=sifo 通常用于切换开启和敞开状态。 按需引入形式如果是残缺引入可跳过此步骤 import Vue from 'vue'import { Switch } from 'element-ui'import 'element-ui/lib/theme-chalk/base.css'import 'element-ui/lib/theme-chalk/switch.css'Vue.use(Switch)根底用法<template> <el-switch v-model="value" active-color="#10b981" inactive-color="#424243"> </el-switch></template><script>export default { data() { return { value: true } }}</script>Attributes 原文链接:https://note.noxussj.top/?source=sifo

July 13, 2023 · 1 min · jiezi

关于前端:ES5与ES6语法的区别及优缺点分析

摘要:ES5(ECMAScript 5)和ES6(ECMAScript 2015)是JavaScript的两个次要版本,本文将介绍它们之间的区别,并剖析各自的个性的优缺点。最初,将总结何时应该应用哪个版本的语法。 1. ES5与ES6的区别1.1 let和const关键字ES6引入了let和const关键字,提供了块级作用域的变量申明形式。相比之下,ES5中应用var进行变量申明,它具备函数级作用域。 示例代码: ES5: function exampleES5() { if (true) { var x = 5; } console.log(x); // 5}ES6: function exampleES6() { if (true) { let x = 5; } console.log(x); // ReferenceError: x is not defined}1.2 箭头函数ES6引入了箭头函数语法,使函数定义更加简洁,并且箭头函数外部的this值绑定到了词法作用域。 示例代码: ES5: var multiplyES5 = function(a, b) { return a * b;};ES6: const multiplyES6 = (a, b) => a * b;1.3 类和模块ES6引入了类和模块的概念,使得面向对象编程更加直观和易用。应用class关键字能够定义类,应用export和import关键字导出和导入模块。 示例代码: ES5: function PersonES5(name) { this.name = name;}PersonES5.prototype.sayHello = function() { console.log('Hello, ' + this.name);};ES6: ...

July 13, 2023 · 2 min · jiezi

关于前端:社交直播游戏场景前端解决方案专栏二小游戏开发-The-React-Way

本文作者:小林前言在系列上一篇文章中,咱们介绍了自研 H5 小游戏引擎 Alice.js 的理念与架构设计,以及外围性能的实现。通过联合 React 生态与 WebGL 渲染能力,咱们能够让相熟 React 的开发人员低成本地入门 H5 游戏开发,在复用现有组件资产的同时,提供高性能的游戏画面,实现更简单的视觉效果。 在本篇中,咱们会联合一个理论的案例,来介绍如何通过 Alice,应用 React 的形式高效开发 H5 小游戏。 一、场景构建在游戏开发中,场景(Scene)的搭建是非常重要的环节。就像电影中的一个场景一样,游戏场景是一系列游戏元素的汇合,表白了游戏世界的一部分内容,也是咱们开发时组织游戏内容的核心。 本节咱们将借用 Cocos Creator 官网的示例,制作一款简略的 2D 平台跳跃类游戏。游戏规则也很简略: 开始游戏后,在地面随机生成肯定数量的冰块,每两块冰之间可能空 1 格或者不空企鹅一次能够向右跳 1 格或者 2 格企鹅跳到冰块上不会掉下去,跳到空白处就会掉下去跳齐全部的格子即游戏通关,中途落下则游戏失败 ▲ 背景图素材来自 OpenGameArt.org 1.1 用 React 组件组织游戏物件作为相熟古代前端框架的前端开发,拿到下面这样的一个页面,首先想到的是什么?没错,组件化!天上的云能够是组件,地面的冰块能够是组件,两头的企鹅也能够是组件,它们独特形成了这样的一个游戏场景。组件化、可复用是 React 的核心思想,这在 Alice 引擎中天然也实用。 将下面的场景形象为组件树后,就是这样的: 这样的树状构造也称为场景图(Scene Graph)。场景图是一种通用的数据结构,通常用于组织 2D/3D 图形场景中节点的逻辑与空间示意。怎么样,是不是和感觉和咱们的前端框架有些共通之处呢? 让咱们更进一步,将其拆分为具体的 React 组件。用 JSX 示意进去就是这样的: // 背景图层const Background = () => ( <View> <Image src="assets/bg.png" /> <Image src="assets/cloud.png" /> <Image src="assets/tree.png" /> </View>);// 咱们的配角小企鹅const PenguinHero = () => ( <Image src="assets/penguin.png" />);// 冰块们const IceBricks = () => ( <View> {array.map(() => <Image src="assets/brick.png" />)} </View>);// 组合成一个游戏场景const Scene = () => ( <View> <Background /> <PenguinHero /> <IceBricks /> </View>);That's it! 在 Alice 中,创立、组合组件就是这么天然,所有都和你相熟的一样。 ...

July 13, 2023 · 6 min · jiezi

关于前端:关于-Angular-应用的多语言设置问题

思考上面这段代码: import localeDe from '@angular/common/locales/de';import localeJa from '@angular/common/locales/ja';import localeZh from '@angular/common/locales/zh';这段代码从 @angular/common/locales 包中导入了三个不同的语言环境(locale):德语(localeDe)、日语(localeJa)和中文(localeZh)。这些语言环境蕴含了针对特定语言的一些本地化信息,例如日期格局、数字格局和货币符号等。在 Angular 利用中,能够应用这些语言环境来实现多语言反对和本地化。 要在 Angular 利用中应用这些导入的语言环境,你须要将它们注册到 LOCALE_ID 令牌中。例如,在 AppModule 中注册这些语言环境: import { BrowserModule } from '@angular/platform-browser';import { NgModule, LOCALE_ID } from '@angular/core';import { AppComponent } from './app.component';import localeDe from '@angular/common/locales/de';import localeJa from '@angular/common/locales/ja';import localeZh from '@angular/common/locales/zh';import { registerLocaleData } from '@angular/common';registerLocaleData(localeDe);registerLocaleData(localeJa);registerLocaleData(localeZh);@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule ], providers: [ { provide: LOCALE_ID, useValue: 'de' } ], bootstrap: [AppComponent]})export class AppModule { }在这个例子中,registerLocaleData() 函数被用于注册导入的语言环境。LOCALE_ID 令牌的值被设置为 'de',这意味着默认的利用语言环境将是德语。你能够依据须要更改此值以设置不同的默认语言环境。 ...

July 13, 2023 · 1 min · jiezi

关于前端:招聘前端开发工程师-北京外派驻场在BGC北京地球科学中心1530k

【招聘】:前端开发工程师 - 北京外派驻场在BGC(北京地球科学核心)15-30k咱们正在寻找一位经验丰富的前端开发工程师,以外派驻场的模式退出咱们位于BGC(北京地球科学核心)的团队。如果你酷爱前端开发,谋求卓越,同时喜爱与跨性能团队单干,这将是一个绝佳的机会退出咱们富裕生机和翻新的工作环境。 职责和资格: 负责公司外围web产品,APP产品的性能开发和保护;参加产品的技术实现探讨和Code Review;参加产品的性能、架构优化;其余团队无效单干,疾速定位问题解决问题。设计和开发具备高度交互性和用户敌对性的网页和Web应用程序。可能与设计师、产品经理和后端开发人员密切合作,独特实现高质量的前端解决方案。具备良好的团队单干和沟通能力,可能无效地参加我的项目探讨和决策。具备解决问题的能力和灵活性,可能适应疾速变动的需要和我的项目时间表。1-3年以上的挪动端h5开发教训,相熟罕用浏览器,能利用本人的教训无效地解决浏览器兼容问题和性能问题;精通 Javascript,精通各种前端调试工具;相熟JS性能优化;相熟常见前端类库(jQuery/Zepto等),相熟前端框架(ReactJS/VUE等);相熟HTML5/CSS3等技术;有解决问题、钻研新技术的趣味和能力,对业内新技术及趋势有较强的敏感度;思路清晰,具备良好理解能力,有强烈的责任心,抗压能力强;把握一门服务器端编程语言、相熟前后端单干开发者优先思考其余要求40岁以内,最好35以内。高级要5年以上工作教训软技能 : CET-4,英文读写,能做自我介绍.能够应用英文进行工作交换有志愿和能力继续学习有较强的内驱力和主动性咱们为你提供: 具备挑战性和创造性的我的项目,涵盖各种行业和应用领域。与优良的专业人士和团队严密单干的机会,独特成长和学习。丰盛的培训和倒退打算,反对你的集体和职业成长。灵便的工作环境和竞争力的薪资待遇。在BGC驻场工作,工作地点是在北京海淀区清华科技园翻新大厦 (近13号线地铁五道口站)享受便当的交通和便捷的生存设施。公司简介 : 北京地球科学核心(BGC)是斯伦贝谢在石油和天然气产业数字化转型方面的当先机构之一。BGC成立于2000年,坐落于北京大学集中区域的中心地带,并与许多当先的大学和钻研机构单干。自成立以来,BGC曾经从一个为地质力学开发解释产品的小型研发核心倒退到了斯伦贝谢最大的软件技术核心之一,领有来自寰球16个不同国家的约300名员工。大多数员工领有硕士或博士学位的软件专业人士,他们与石油技术专家并肩工作。BGC的使命是提供集成和翻新的软件开发流程和解决方案,以应答简单的工程挑战,包含用于油井施工的数字平台、实时数据采集和地层评估。BGC在前沿的软件开发和数字技术(如人工智能和机器学习、云利用微服务体系结构、自动化测试、继续集成和继续交付)方面投入了大量资金,并且为员工提供了全面的培训体系。公司采纳麻利的开发模式,一直摸索前沿科技,为客户发明最大价值。我的项目人数: 20人如果你对前端开发充满热情,有着丰盛的教训和技能,并渴望在一个充满活力和翻新的团队中倒退本人的职业生涯,咱们期待你的退出!无意增加微信:baggiomygod 或请将你的简历发送至 ou.chen@cienet.com.cn,附上你的个人信息和相干作品或我的项目链接。咱们将尽快与符合要求的候选人进行分割。请留神,只有合乎资格的候选人将会被分割安顿面试。感激你对咱们的公司和职位的关注!

July 13, 2023 · 1 min · jiezi

关于前端:腾讯面试官如何从0到1实现一个高性能Collapse折叠组件直到现在我还实现不出来

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接大家好,我是linwu,之后面腾讯某个部门的时候,面试官已经给了我一道手写题,题目大略就是从0到1实现一个Collapse折叠组件,而后我依据提供接口属性,我大略实现进去相似上面组件的状态,而后面试官问动画除了height模式,还有其余它形式么,因为height的变动会触发重排,另外折叠面板panel如果是大量数据,关上的时候会卡顿,该如何解决,这个我到时候解决了,提前渲染暗藏就行,`然而重排的问题直到现在我都没有解决,收回来问问大家,如果是你们,你们会如何思考`jcode 咱们先从最根本的实现开始,而后逐渐增加更多的性能,如手风琴模式、自定义箭头、禁用状态、暗藏时是否渲染DOM构造 组件接口定义Collapse属性阐明类型默认值accordion是否开启手风琴模式booleanfalseactiveKey以后开展面板的 key手风琴模式:string \null 非手风琴模式:string[]-arrow自定义箭头,如果是 ReactNode,那么 会主动为你减少旋转动画成果ReactNode \((active: boolean) => React.ReactNode)-defaultActiveKey默认开展面板的 key手风琴模式:string \null 非手风琴模式:string[]-onChange切换面板时触发手风琴模式:(activeKey: string \null) => void 非手风琴模式:(activeKey: string[]) => void-Collapse.Panel属性阐明类型默认值arrow自定义箭头ReactNode \((active: boolean) => React.ReactNode)-destroyOnClose不可见时卸载内容booleanfalsedisabled是否为禁用状态booleanfalseforceRender被暗藏时是否渲染 DOM 构造booleanfalsekey惟一标识符string-onClick标题栏的点击事件(event: React.MouseEvent<Element, MouseEvent>) => void-title标题栏左侧内容ReactNode-创立根底Collapse组件咱们创立一个根底的Collapse组件。这个组件须要有一个状态来追踪它是否被开展 import React, { useState } from 'react';const Collapse = ({ children }) => { const [isOpen, setIsOpen] = useState(false); return ( <div> <button onClick={() => setIsOpen(!isOpen)}> {isOpen ? 'Collapse' : 'Expand'} </button> {isOpen && <div>{children}</div>} </div> );};export default Collapse;拓展Collapse组件其它属性accordion:如果设置为true,咱们将启用手风琴模式。在这种模式下,只有一个面板能够被开展。当一个新的面板被开展时,之前开展的面板将被敞开。activeKey:以后开展面板的key。如果咱们处于手风琴模式,这将是一个字符串或null。如果咱们不在手风琴模式,这将是一个字符串数组。arrow:自定义的箭头。如果是一个React节点,将主动为你增加旋转动画成果。如果是一个函数,它将接管一个参数,示意面板是否被开展,并返回一个React节点。defaultActiveKey:默认开展面板的key。它的类型与activeKey雷同。onChange:它在面板切换时被触发。它接管一个参数,示意以后开展面板的key。它的类型与activeKey雷同。import React, { useState, useEffect } from 'react';const Collapse = ({ children, forceRender, accordion, activeKey, arrow, defaultActiveKey, onChange }) => { const [isOpen, setIsOpen] = useState(false); const [currentActiveKey, setCurrentActiveKey] = useState(defaultActiveKey); useEffect(() => { setCurrentActiveKey(activeKey); }, [activeKey]); const handleClick = () => { setIsOpen(!isOpen); if (accordion) { setCurrentActiveKey(isOpen ? null : activeKey); } onChange && onChange(isOpen ? null : activeKey); }; const renderArrow = () => { if (typeof arrow === 'function') { return arrow(isOpen); } return arrow; }; return ( <div> <button onClick={handleClick}> {isOpen ? 'Collapse' : 'Expand'} {renderArrow()} </button> <div style={{ display: isOpen || forceRender ? 'block' : 'none' }}> {children} </div> </div> );};export default Collapse;实现Panel咱们创立一个名为Collapse.Panel的子组件来反对这些新的属性。这个子组件将作为Collapse组件的一部分,用于示意一个可折叠的面板。 ...

July 12, 2023 · 3 min · jiezi

关于前端:你确定懂冒泡排序用动画的方式讲懂冒泡排序及其优化方式

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接基本概念冒泡排序是一种根底的排序算法。其根本思维是通过一直地比拟相邻元素并在必要时进行替换,将最大(或最小)的元素"冒"到序列的一端。排序步骤先来感触到冒泡排序的步骤吧jcode 以数组 [5, 3, 8, 4, 6]为例,冒泡排序的步骤如下: 第一轮排序:比拟相邻的元素。第一次比拟5和3,5大于3,替换它们两个,数组变成 [3, 5, 8, 4, 6];接着比拟5和8,5小于8,不必替换,而后比拟8和4,8大于4,替换,数组变为 [3, 5, 4, 8, 6];最初比拟8和6,8大于6,替换,数组变为 [3, 5, 4, 6, 8]。这样,第一轮比拟完结后,最大的数8被排到了最初。 第二轮排序:再次从前向后比拟相邻的元素,这次因为8曾经是最大的元素在开端,所以不再参加比拟。先比拟3和5,3小于5,不必替换;而后比拟5和4,5大于4,替换,数组变为 [3, 4, 5, 6, 8];接着比拟5和6,5小于6,不必替换。这样,第二轮排序完结,第二大的元素6也排到了它应该在的地位。 后续轮排序:如此重复进行,每一轮比拟的元素对都比上一轮少一对。直至实现所有的排序。 最终,数组 [5, 3, 8, 4, 6] 被排序为 [3, 4, 5, 6, 8]。 冒泡排序的实现let array = [5, 3, 8, 4, 6];for(let i = 0; i < array.length; i++) { for(let j = 0; j < array.length - i - 1; j++) { if(array[j] > array[j + 1]) { // 替换元素 let temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } }}console.log(array); // 输入: [3, 4, 5, 6, 8]此算法的工夫复杂度为O(n^2),因而在解决大量数据时可能效率较低。 ...

July 12, 2023 · 2 min · jiezi

关于前端:算法可视化用动画的方式讲解插入排序

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接插入排序(Insertion Sort)插入排序(Insertion Sort)是一种简略直观的排序算法。它的工作原理是通过构建有序序列,在未排序的局部中从后向前逐渐扫描,找到适合地位并插入元素。插入排序通常采纳原地排序(只应用O(1)的额定空间),因而在扫描过程中须要重复将已排序元素向后挪动,为新元素提供插入空间。 根本思维插入排序的根本思维是将数组分为已排序和未排序两局部,初始时已排序局部只蕴含第一个元素,而后顺次将未排序局部的元素插入到已排序局部的正确地位,直到所有元素都有序为止。实现逻辑从第一个元素开始,将其视为已排序局部。取出下一个元素,从后向前扫描已排序局部,找到插入地位。如果以后元素大于被比拟元素,则将被比拟元素向后挪动一位。反复步骤3,直到找到插入地位。将以后元素插入到插入地位后。反复步骤2~5,直到所有元素都插入到已排序局部。动图演示 性能剖析均匀工夫复杂度:O(n^2)最坏工夫复杂度:O(n^2)空间复杂度:O(1)排序形式:In-place稳定性:稳固排序算法代码实现// 插入排序function insertionSort(arr) { const len = arr.length; for (let i = 1; i < len; i++) { let current = arr[i]; let j = i - 1; while (j >= 0 && arr[j] > current) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = current; }} 起源 原本本人想写一个,可是太费时间了,里面找了一圈,发现有了,就拿来演示一下算法优化改良改良办法① - 二分插入排序二分插入排序是对间接插入排序的改良,应用二分查找来找到插入地位,从而缩小比拟的次数。 改良代码: // 二分插入排序function binaryInsertionSort(arr) { const len = arr.length; for (let i = 1; i < len; i++) { let current = arr[i]; let left = 0; let right = i - 1; while (left <= right) { let middle = Math.floor((left + right) / 2); if (arr[middle] > current) { right = middle - 1; } else { left = middle + 1; } } for (let j = i - 1; j >= left; j--) { arr[j + 1] = arr[j]; } arr[left] = current; }}改良办法② - 希尔排序希尔排序是对插入排序的进一步改良,通过将数组分成多个子序列进行插入排序,逐步放大子序列的距离,最终实现全局的排序。 ...

July 12, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程解读TSConfig

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接解读TSConfigTypeScript 配置文件(tsconfig.json)是用于配置 TypeScript 我的项目的重要文件。它容许开发者自定义 TypeScript 编译器的行为,指定编译选项、文件蕴含与排除规定、输入目录等。通过合理配置 tsconfig.json,咱们能够依据我的项目需要进行灵便的 TypeScript 编译设置。 本文将全面解读 tsconfig.json 的各个配置选项,并提供一些常见的应用场景和示例代码,以及封装定制化本人tsconfig.base配置 创立和根本配置要应用 TypeScript 配置文件,咱们首先须要创立一个名为 tsconfig.json 的文件,并将其搁置在我的项目的根目录下。 上面是一个根本的 tsconfig.json 配置示例: { "compilerOptions": { "target": "es6", "module": "commonjs", "outDir": "dist" }, "include": [ "src/**/*.ts" ], "exclude": [ "node_modules", "dist" ]}在上述示例中,咱们应用 compilerOptions 配置选项指定了 TypeScript 编译器的选项。其中: "target": "es6" 指定编译的指标 JavaScript 版本为 ES6。"module": "commonjs" 指定模块的生成形式为 CommonJS。"outDir": "dist" 指定输入目录为 "dist"。同时,咱们应用 include 和 exclude 配置选项别离指定了须要编译的源文件的蕴含规定和排除规定。 compilerOptionscompilerOptions 是 tsconfig.json 中最重要的配置选项之一,它容许咱们指定 TypeScript 编译器的各种行为和设置。以下是一些罕用的 compilerOptions 配置选项: targettarget 选项指定了编译后的 JavaScript 代码所要遵循的 ECMAScript 规范。常见的选项包含 "es5"、"es6"、"es2015"、"es2016" 等。 ...

July 12, 2023 · 2 min · jiezi

关于前端:现代TypeScript高级教程装饰器与反射元数据

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接装璜器与反射元数据介绍在过来的几年中,JavaScript及其生态系统产生了疾速的变动。其中,TypeScript已成为许多开发人员的首选语言。其次要劣势在于其动态类型零碎,它使咱们能够在编译时捕捉谬误,而不是在运行时。除此之外,TypeScript还为咱们提供了许多ES6+个性以及一些其余的独有个性,例如枚举、命名空间和装璜器。 装璜器简介在TypeScript中,装璜器是一种非凡类型的申明,能够被附加到类申明,办法,属性,拜访器或参数上。装璜器的核心思想是加强曾经存在的类、办法、属性等的行为,或者增加新的行为。通过装璜器,咱们能够在不扭转原始类的定义的状况下,为类增加新的个性。 在TypeScript中,装璜器应用@expression的模式。其中,expression必须为一个返回函数的表达式,这个函数在运行时会被调用,传入相干的装璜器参数。 TypeScript反对以下几种类型的装璜器: 类装璜器办法装璜器拜访器装璜器属性装璜器参数装璜器类装璜器类装璜器利用于类的构造函数,用于察看、批改或替换类定义。类装璜器在利用时,会作为函数调用,并将构造函数作为其惟一的参数。 function Sealed(constructor: Function) { Object.seal(constructor); Object.seal(constructor.prototype);}@Sealedclass Greeter { constructor(public greeting: string) {} greet() { return "Hello, " + this.greeting; }}办法装璜器办法装璜器利用于办法的属性描述符,并能够用于察看、批改或替换办法定义。当装璜器被调用时,它会接管到三个参数:以后类的原型,办法名,以及该办法的属性描述符。 function Log(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) { let originalMethod = descriptor.value; // 保留原始函数 descriptor.value = function (...args: any[]) { console.log("Arguments: ", JSON.stringify(args)); let result = originalMethod.apply(this, args); console.log("Result: ", result); return result; }}class Calculator { @Log add(x: number, y: number): number { return x + y; }}拜访器装璜器拜访器装璜器能够利用于拜访器的属性描述符,并能够用于察看、批改或替换拜访器的定义。拜访器装璜器和办法装璜器有类似的语法。 ...

July 12, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程类型兼容协变和逆变

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接类型兼容:协变和逆变引言在类型零碎中,协变和逆变是对类型比拟(类型兼容)一种形式化形容。在一些类型零碎中,例如 Java,这些概念是显式嵌入到语言中的,例如应用extends关键字示意协变,应用super关键字示意逆变。在其余一些类型零碎中,例如 TypeScript,协变和逆变的规定是隐式嵌入的,通过类型兼容性查看来实现。 协变和逆变的存在使得类型零碎具备更大的灵活性。例如,如果你有一个Animal类型的数组,并且你有一个Dog类型的对象(假如Dog是Animal的子类型),那么你应该可能将Dog对象增加到Animal数组中。这就是协变。反过来,如果你有一个解决Animal类型对象的函数,并且你有一个Dog类型的对象,你应该能够应用这个函数来解决Dog对象。这就是逆变。 协变和逆变还能够帮忙咱们创立更通用的代码。例如,如果你有一个能够解决任何Animal的函数,那么这个函数应该可能解决任何Animal的子类型。这意味着,你能够编写一段只依赖于Animal类型的代码,而后应用这段代码解决任何Animal的子类型。 协变(Covariance)协变形容的是如果存在类型A和B,并且A是B的子类型,那么咱们就能够说由A组成的复合类型(例如Array<A>或者(a: A) => void)也是由B组成的相应复合类型(例如Array<B>或者(b: B) => void)的子类型。 让咱们通过一个例子来了解协变。假如咱们有两个类型Animal和Dog,其中Dog是Animal的子类型。 type Animal = { name: string };type Dog = Animal & { breed: string };let dogs: Dog[] = [{ name: "Fido", breed: "Poodle" }];let animals: Animal[] = dogs; // OK because Dog extends Animal, Dog[] is a subtype of Animal[]这里咱们能够将类型为Dog[]的dogs赋值给类型为Animal[]的animals,因为Dog[]是Animal[]的子类型,所以数组是协变的。 协变:类型的向下兼容性协变是类型零碎中的一个基本概念,它形容的是类型的“向下兼容性”。如果一个类型A能够被看作是另一个类型B的子类型(即A能够被平安地用在冀望B的任何中央),那么咱们就说A到B是协变的。这是类型零碎中最常见和直观的一种关系,例如在面向对象编程中的继承就是协变的一种体现。 在TypeScript中,所有的类型都是本身的子类型(即每个类型到本身是协变的),并且null和undefined类型是所有类型的子类型。除此之外,接口和类也能够通过继承来造成协变关系。 class Animal { name: string;}class Dog extends Animal { breed: string;}let myDog: Dog = new Dog();let myAnimal: Animal = myDog; // OK,因为Dog是Animal的子类型这个例子中,咱们能够将一个Dog对象赋值给一个Animal类型的变量,因为Dog到Animal是协变的。 ...

July 12, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程类型兼容结构化类型

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接类型兼容:结构化类型TypeScript 是一种基于 JavaScript 的动态类型语言,它为 JavaScript 增加了类型零碎,并提供了弱小的类型检查和主动补全性能。TypeScript 的类型零碎有一个十分重要的个性,那就是 "鸭子类型"(Duck Typing)或 "结构化类型"(Structural Typing)(文章会以"鸭子类型"(Duck Typing)作为简称)。这种个性有时会让人感到诧异,但它是 TypeScript 加强 JavaScript 开发体验的重要形式之一。 鸭子类型的概念来自一个古老的英语成语:“如果它走起路来像一只鸭子,叫起来也像一只鸭子,那么它就是一只鸭子。”在 TypeScript(或更一般地说,动态类型语言)的上下文中,鸭子类型意味着一个对象的类型不是由它继承或实现的具体类别决定的,而是由它具备的构造决定的。 本文将全面深刻地探讨 TypeScript 中的鸭子类型,以及如何在理论的开发中利用和利用鸭子类型。 1. 鸭子类型:定义和示例鸭子类型的概念来自一个古老的英语成语:“如果它走起路来像一只鸭子,叫起来也像一只鸭子,那么它就是一只鸭子。”在 TypeScript(或更一般地说,动态类型语言)的上下文中,鸭子类型意味着一个对象的类型不是由它继承或实现的具体类别决定的,而是由它具备的构造决定的。 这是一个简略的鸭子类型示例: interface Duck { walk: () => void; quack: () => void;}function doDuckThings(duck: Duck) { duck.walk(); duck.quack();}const myDuck = { walk: () => console.log('Walking like a duck'), quack: () => console.log('Quacking like a duck'), swim: () => console.log('Swimming like a duck')};doDuckThings(myDuck); // OK在这个例子中,咱们定义了一个 Duck 接口和一个 doDuckThings 函数,这个函数须要一个 Duck 类型的参数。而后咱们创立了一个 myDuck 对象,它有 walk、quack 和 swim 这三个办法。只管 myDuck 并没有显式地申明它实现了 Duck 接口,然而因为 myDuck 的构造满足了 Duck 接口的要求(即 myDuck 有 walk 和 quack 这两个办法),咱们能够将 myDuck 作为参数传递给 doDuckThings 函数。 ...

July 12, 2023 · 2 min · jiezi

关于前端:现代TypeScript高级教程泛型和类型体操

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接泛型和类型体操泛型和类型体操(Type Gymnastics)是 TypeScript 中高级类型零碎的重要组成部分。它们提供了弱小的工具和技巧,用于解决简单的类型操作和转换。 泛型(Generics)1. 泛型函数泛型函数容许咱们在函数定义中应用类型参数,以便在函数调用时动静指定类型。例如: function identity<T>(arg: T): T { return arg;}let result = identity<number>(42); // result 的类型为 number在下面的示例中,identity 函数应用类型参数 T,并返回与输出类型雷同的值。通过显式传递泛型参数,咱们能够确保在函数调用时指定了具体的类型。 2. 泛型接口泛型接口容许咱们在接口定义中应用类型参数,以便在实现该接口时指定具体的类型。例如: interface Container<T> { value: T;}let container: Container<number> = { value: 42 };在下面的示例中,咱们定义了一个泛型接口 Container,它蕴含一个类型参数 T。通过指定 Container<number>,咱们创立了一个具体的实现,其中的 value 属性类型为 number。 3. 泛型类泛型类容许咱们在类定义中应用类型参数,以便在创立类的实例时指定具体的类型。例如: class Stack<T> { private items: T[] = []; push(item: T) { this.items.push(item); } pop(): T | undefined { return this.items.pop(); }}let stack = new Stack<number>();stack.push(1);stack.push(2);let item = stack.pop(); // item 的类型为 number | undefined在下面的示例中,咱们定义了一个泛型类 Stack,它应用类型参数 T 来示意堆栈中的元素类型。通过创立 Stack<number> 的实例,咱们限度了堆栈中的元素必须为 number 类型。 ...

July 12, 2023 · 3 min · jiezi

关于前端:现代TypeScript高级教程类型守卫

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接类型守卫概述在 TypeScript 中,类型守卫能够用于在运行时查看变量的类型,并在代码块外部将变量的类型范畴放大到更具体的类型。这种类型收窄能够让 TypeScript 编译器更好地了解咱们代码的用意,从而提供更精确的类型推断和类型查看。 类型守卫通常应用类型断言、类型谓词、typeof 操作符、instanceof 操作符或自定义的谓词函数来判断变量的具体类型,并依据判断后果收窄变量的类型范畴。 typeof 类型守卫typeof 类型守卫容许咱们应用 typeof 操作符来在代码中依据变量的类型范畴进行条件判断。以下是一个示例: function printValue(value: string | number) { if (typeof value === 'string') { console.log(value.toUpperCase()); } else { console.log(value.toFixed(2)); }}printValue('hello'); // 输入: HELLOprintValue(3.1415); // 输入: 3.14在下面的示例中,咱们应用 typeof 操作符在条件语句中查看变量 value 的类型。如果它的类型是 'string',则调用 toUpperCase 办法;如果是 'number',则调用 toFixed 办法。通过应用 typeof 类型守卫,咱们可能依据不同的类型执行不同的代码逻辑。 instanceof 类型守卫instanceof 类型守卫容许咱们应用 instanceof 操作符来查看对象的类型,并在代码块外部收窄对象的类型范畴。以下是一个示例: class Animal { move() { console.log('Animal is moving'); }}class Dog extends Animal { bark() { console.log('Dog is barking'); }}function performAction(animal: Animal) { if (animal instanceof Dog) { animal.bark(); } else { animal.move(); }}const animal1 = new Animal();const animal2 = new Dog();performAction(animal1); // 输入: Animal is movingperformAction(animal2); // 输入: Dog is barking在下面的示例中,咱们应用 instanceof 操作符在条件语句中查看变量 animal 的类型。如果它是 Dog 类的实例,则调用 bark 办法;否则调用 move 办法。通过应用 instanceof 类型守卫,咱们能够依据对象的具体类型执行不 ...

July 12, 2023 · 3 min · jiezi

关于前端:现代TypeScript高级教程类型推断

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接类型推断TypeScript通过类型推断能够主动推导出变量和表达式的类型,进步代码的可读性和可维护性。 类型推断类型推断是 TypeScript 在编译时依据上下文主动推导变量和表达式的类型。它依据变量的赋值、函数的返回值、表达式的操作等信息来确定变量或表达式的最佳类型。 1. 根底类型推断TypeScript依据变量的初始值来推断根底类型,包含字符串、数字、布尔值等。 let name = "John"; // 推断为string类型let age = 30; // 推断为number类型let isStudent = true; // 推断为boolean类型2. 最佳公共类型推断当咱们将不同类型的值赋给一个变量或数组时,TypeScript会依据这些值的类型推断出一个最佳公共类型。 let values = [1, 2, "three", true]; // 推断为(number | string | boolean)[]在下面的示例中,数组values蕴含了数字、字符串和布尔值,TypeScript推断出这个数组的类型为(number | string | boolean)[],即联结类型。 3. 上下文类型推断TypeScript会依据上下文中的预期类型推断变量的类型。这种上下文能够是函数参数、赋值语句等。 function greet(person: string) { console.log(`Hello, ${person}!`);}greet("John"); // person的类型推断为string在下面的示例中,函数greet的参数person的类型被推断为string,因为在函数调用时传入的实参是一个字符串。 4. 类型断言如果咱们心愿手动指定一个变量或表达式的类型,能够应用类型断言(Type Assertion)来通知TypeScript咱们的用意。 let value = "Hello, TypeScript!";let length = (value as string).length; // 类型断言为string在下面的示例中,咱们应用类型断言as string将变量value的类型指定为string,以便在前面获取其长度时,TypeScript能正确推断出类型。 5. 类型推断和泛型在应用泛型时,TypeScript会依据传入的参数类型推断泛型类型的具体类型。 function identity<T>(value: T): T { return value;}let result = identity("Hello, TypeScript!"); // result的类型推断为string在下面的示例中,泛型函数identity的参数value的类型被推断为传入的实参 ...

July 12, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程高级类型

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接高级类型映射类型(Mapped Types)映射类型(Mapped Types)是 TypeScript 中一种弱小的类型操作工具,它容许咱们在编译时转换已知类型的属性,并创立一个新的类型。通过映射类型,咱们能够对已有类型的属性进行转换、批改或增加新的属性。这在许多状况下都十分有用,例如将属性变为只读或可选,从现有属性中抉择一部分属性等。 映射类型的语法模式为: type NewType = { [Property in keyof ExistingType]: TransformType;};其中,NewType 是咱们要创立的新类型,Property 是 ExistingType 的键,TransformType 是对应属性的转换类型。 上面是一些常见的映射类型的示例: 1. ReadonlyReadonly 是 TypeScript 内置的一个映射类型,它将给定类型的所有属性变为只读。 type Readonly<T> = { readonly [P in keyof T]: T[P];};示例应用: interface Person { name: string; age: number;}type ReadonlyPerson = Readonly<Person>;const person: ReadonlyPerson = { name: "John", age: 30,};person.name = "Alice"; // Error: Cannot assign to 'name' because it is a read-only property.2. PartialPartial 是另一个内置的映射类型,它将给定类型的所有属性变为可选。 ...

July 12, 2023 · 2 min · jiezi

关于前端:现代TypeScript高级教程类型系统层级

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接类型零碎层级TypeScript 的类型零碎是强类型和动态类型的,这为开发者提供了弱小的类型检查和类型平安保障,同时也减少了肯定的学习复杂性。为了更好地了解 TypeScript 的类型零碎,本文将全面介绍其类型零碎层级,包含顶层类型(Top Type)和底层类型(Bottom Type),以及在这个层次结构中如何解决和操作各种类型。了解 TypeScript 的类型零碎层级有助于咱们更好地应用和把握 TypeScript,写出更强壮、可保护的代码。 1. 顶层类型(Top Type)顶层类型是所有其余类型的父类型,这意味着在 TypeScript 中的任何类型都能够看作是顶层类型的子类型。TypeScript 中有两个非凡的顶层类型:any和unknown。 1.1 any 类型any类型是 TypeScript 的一个逃生窗口,它能够承受任意类型的值,并且对 any 类型的值进行的任何操作都是容许的。应用 any 类型,能够使咱们绕过 TypeScript 的类型查看。上面的例子展现了 any 类型的灵活性: let a: any = 123; // OKa = 'hello'; // OKa = true; // OKa = { id: 1, name: 'Tom' }; // OKa.foo(); // OK咱们能够看到,咱们能够将任何类型的值赋给 any 类型的变量,甚至能够对 any 类型的值进行咱们想要的任何操作,而 TypeScript 编译器并不会对此做出任何投诉。然而,正是因为其超高的灵活性,使得 any 类型在肯定水平上减弱了 TypeScript 的类型安全性,因而在咱们编写 TypeScript 代码时,应尽量避免应用 any 类型。 1.2 unknown 类型unknown 类型与 any 类型在承受任何类型的值这一点上是一样的,但 unknown 类型却不能像 any 类型那样对其进行任何操作。咱们在对 unknown 类型的值进行操作之前,必须进行类型查看或类型断言,确保操作的安全性。 ...

July 12, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程命名空间和模块

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接命名空间和模块命名空间(Namespace)在 TypeScript 中,命名空间是一种将代码封装在一个特定名称下的形式,以避免全局作用域净化并防止命名抵触。命名空间在 TypeScript 中十分重要,因为它们为模块化和封装提供了灵便的选项。 创立命名空间的语法如下: namespace MyNamespace { export const myVar: number = 10; export function myFunction(): void { console.log("Hello from MyNamespace"); }}在此例中,咱们创立了一个名为MyNamespace的命名空间,该命名空间内有一个变量myVar和一个函数myFunction。export关键字容许咱们从命名空间内部拜访这些元素。 命名空间中的元素能够通过以下形式拜访: console.log(MyNamespace.myVar); // 输入:10MyNamespace.myFunction(); // 输入:Hello from MyNamespace咱们也能够应用嵌套的命名空间: namespace ParentNamespace { export namespace ChildNamespace { export const myVar: number = 20; }}console.log(ParentNamespace.ChildNamespace.myVar); // 输入:20命名空间(Namespace)应用场景在 TypeScript 的晚期版本中,命名空间被宽泛地应用来组织和包装一组相干的代码。然而,随着 ES6 模块零碎(ES6 Modules)的呈现和宽泛应用,命名空间的用法变得越来越少,当初被视为一种遗留的形式来组织代码。第三方库一些第三方库依然应用命名空间来组织本人的代码,并提供命名空间作为库的入口点。在这种状况下,咱们须要应用命名空间来拜访和应用库中的类型和函数。 namespace MyLibrary { export function myFunction() { // ... }}MyLibrary.myFunction();兼容性在一些遗留的 JavaScript 代码或库中,命名空间依然是一种常见的组织代码的形式。如果咱们须要与这些代码进行交互,咱们可能须要创立命名空间来适应它们。 // legacy.jsvar MyNamespace = { myFunction: function() { // ... }};MyNamespace.myFunction();在下面的示例中,咱们演示了命名空间的几个应用场景。第一个示例展现了如何应用命名空间拜访和应用第三方库的函数。第二个示例展现了如何应用命名空间来治理全局状态。第三个示例展现了如何在与遗留 JavaScript 代码进行交互时创立命名空间。 ...

July 12, 2023 · 1 min · jiezi

关于前端:带你走过动态表单的那些坑

某些场景下,咱们的表单须要做成可配置表单,依据管理员配置好的表单信息来动静生成表单,比方业务员就只能填写业务类型的表单信息,经营人员能够配置流动类型的表单信息,相似于表单的权限管制。 预览动静表单成果在文章最初 动静表单校验 <el-form ref="ruleForm" :rules="ruleArr" :model="ruleForm" label-width="80px" > <div v-for="(item, index) in formArr"> <div v-if="item.isShow == 1 && item.type == 1"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''" > <el-input v-model="ruleForm[item.name]" :placeholder="`请输出${item.label}`" ></el-input> </el-form-item> </div> <div v-if="item.isShow == 1 && item.type == 2"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''"> <el-select v-model="ruleForm[item.name]" :placeholder="item.rules"> <el-option label="区域一" value="shanghai"></el-option> <el-option label="区域二" value="beijing"></el-option> </el-select> </el-form-item> </div> <div v-if="item.isShow == 1 && item.type == 3"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''"> <el-date-picker v-model="ruleForm[item.name]" type="daterange" format="yyyy-MM-dd" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="完结日期" > </el-date-picker> </el-form-item> </div> <div v-if="item.isShow == 1 && item.type == 4"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''"> <el-switch v-model="ruleForm[item.name]"></el-switch> </el-form-item> </div> <div v-if="item.isShow == 1 && item.type == 5"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''"> <el-checkbox-group v-model="ruleForm[item.name]"> <el-checkbox label="美食/餐厅线上流动" name="type"></el-checkbox> <el-checkbox label="地推流动" name="type"></el-checkbox> <el-checkbox label="线下主题流动" name="type"></el-checkbox> <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox> </el-checkbox-group> </el-form-item> </div> <div v-if="item.isShow == 1 && item.type == 6"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''"> <el-radio-group v-model="ruleForm[item.name]"> <el-radio label="线上品牌商资助"></el-radio> <el-radio label="线下场地收费"></el-radio> </el-radio-group> </el-form-item> </div> <div v-if="item.isShow == 1 && item.type == 7"> <el-form-item :label="item.label" :prop="item.isRule ? item.name : ''"> <el-input :placeholder="`请输出${item.label}`" type="textarea" v-model="ruleForm[item.name]" ></el-input> </el-form-item> </div> </div> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')" >立刻创立</el-button > <el-button @click="resetForm('ruleForm')">重置</el-button> <el-button @click="backData">回显</el-button> </el-form-item> </el-form> ...

July 12, 2023 · 3 min · jiezi

关于前端:极光笔记-解锁Web推送的潜力提升网站收入

01引 言Web推送告诉的定义和概述Web推送告诉是网站向用户发送的音讯,即便用户没有在被动拜访该网站。告诉会在用户设施上以弹出窗口的模式显示,提供快速访问信息、新闻更新、优惠等。Web推送告诉是一种能够接触到用户并减少用户与网站内容互动的无效形式,Web推送告诉的次要劣势在于,它可能在用户没有在网站上沉闷时也能接触到用户,老本效益十分高,并且开启和点击率高于电子邮件。 Web推送告诉的益处Web推送告诉为企业提供了许多益处,包含减少用户互动和留存、推动更多销售以及提供一种经济高效的形式来接触用户。通过Web推送告诉,企业能够在用户没有在网站上沉闷时也能接触到用户,减少用户与内容互动的机会。Web推送告诉还使企业可能向用户细分发送定向音讯,进步互动和转化的可能性。此外,Web推送告诉比传统营销办法要便宜得多,这使其成为估算无限的企业的一种吸引人的抉择。此外,Web推送告诉的开启和点击率高于电子邮件,使其成为接触用户的更无效形式。最初,企业能够通过Engagelab控制台测量告诉的体现,并剖析数据,以优化推送流动以取得更好的后果。 02、利用Web推送告诉的力量晋升您网站的支出最近,Web推送告诉曾经成为一个要害的用户触达渠道,本文将介绍一些具体的场景,展现如何利用Web推送告诉来最大化您本人网站的支出。 将未知访客转化为首次购买者将未知访客转化为首次购买者是一个重要挑战,因为您的网站访问者中有近90%是匿名的。您曾经破费了大量的工夫和资源来吸引这些访问者,如果他们不实现任何操作或交易,这可能对您的业务形成致命威逼。然而,您无奈通过付费的从新定位广告或电子邮件等形式与这些用户间接分割。在这种状况下,Web推送告诉能够施展重要作用,帮忙您吸引和转化这些匿名访客成为首次购买者并推动业务收入。比方您能够您能够仅给这部分访客发送web推送告诉,提供一些可用于购买物品的优惠券,促使访客实现付费转化。 揭示用户有待购买的物品在线购物车的放弃率均匀达到67%,对于企业来说,这听起来并不衰弱。产生这种景象有多种起因,比拟常见的有:"客户意外来到了他们的计算机"。尽管您无奈阻止用户长期来到,但在他们回到计算机时,您须要找到一种办法与他们从新分割起来。应用Web推送告诉,即便他们曾经敞开了网站,您也能够针对这些放弃购物车的用户,促使他们回来并实现购买!当购物车中的商品长时间未领取或订单被放弃时,您能够应用EngageLab WebPush提供的标签别名API为这部分用户打上对应标签,并应用创立推送API向这部分标签用户发送优惠券或折扣券,以进步转化率。 重要变更音讯告诉揭示客户他们能够在您的网站上取得哪些服务是十分理智的,因为这样能够无效地传播给他们对于您的网站所提供的价值和劣势。通过揭示客户,您能够引起他们的留神并激发他们的趣味,让他们晓得他们能够从您的网站中取得什么样的服务和益处。这种揭示能够帮忙客户更好地理解您的产品或服务,并激发他们进行进一步的摸索和互动。客户可能会遗记或不晓得您网站上提供的某些服务,因而揭示他们能够进步他们对您网站的参与度。 通过向客户发送个性化的揭示音讯,您能够定时提供无关特定服务或优惠的信息,以满足他们的需要和冀望。这种定向的揭示能够减少客户的满意度和忠诚度,促使他们更频繁地拜访和利用您的网站。 另外应用Web推送告诉能够不便地向客户发送付款、物流进度、账户更改、投诉反馈和敌人的音讯等重要告诉。 通过减少网站访问量来推动支出广告支出曾经成了网站支出的重要组成部分。在这方面,Web推送告诉是一种有助于营销人员实现目标的无效工具。它能够吸引新订阅者并激发反复访问者的趣味。 测试案例显示,社交Web推送告诉对于吸引反复访问者和新订阅者都十分无效。通过应用Engagelab推送服务的Web推送告诉,一个社交网络网站在100天内吸引了超过10,000个用户,均匀页面浏览量减少了32%。相比一般访问者,通过Web推送告诉的访问者的停留时间减少了120%,而且Web推送告诉的点击率达到了32%。这些数据表明,通过吸引更多的流量和相干受众,客户可能从Web推送告诉中取得良好的回报率。 综上所述,利用Web推送告诉,特地是社交Web推送告诉可能吸引新订阅者和激发反复访问者的趣味,从而进步网站的流量和点击率,带来更好的广告支出回报率。 03、如何进步Web推送告诉的受权率当初,让咱们持续探讨EngageLab是如何进步Web推送告诉的受权率的。"受权"是要求用户容许发送推送告诉的权限。浏览器会弹出提示框,须要用户点击"容许"能力进行订阅。Web推送告诉实用于PC桌面和安卓设施。苹果不反对在iOS设施(如iPhone和iPad)上的Web推送告诉。各种浏览器提供了本人的原生受权提示框,用户须要点击"容许"能力订阅您的网站。如果贸然获取受权用户很可能回绝告诉,尔后该用户都不能再接管到您的音讯。 EngageLab提供了“软提醒”,这些提醒会在原生受权提示框之前显示,并疏导用户抉择他们感兴趣的音讯类别。这些提醒不会代替原生提示框,也不会订阅用户的Web推送告诉。这些提醒十分无益,因为它们减少了用户放弃订阅您的音讯的可能性,并且受到浏览器的高度举荐。受权提醒有三个作用:● 向用户介绍订阅推送告诉的价值。● 避免用户被阻止订阅。● 用户示意容许告诉的志愿再触发原生提醒。 EngageLab的提醒是一种“软申请”,这意味着它们不会触发浏览器的原生受权提示框中的“硬申请”。这一点很重要,因为如果用户回绝了原生提醒,开发人员将无奈再次提醒用户。然而,如果用户疏忽了软提醒,应用程序或网站依然能够稍后再次提供选项。第一次取得受权十分重要。通过进步Web推送告诉的受权率,您能够更好地与用户建立联系,提供个性化的内容和优惠,从而实现更高的参与度和转化率。 总结Web推送告诉是进步网站支出的弱小工具。通过正当利用Web推送告诉的各种策略,您能够将匿名访问者转化为首次购买者,揭示用户有待购买的物品,发送重要变更音讯告诉以及通过减少网站访问量推动支出增长。EngageLab的软提醒性能有助于进步用户受权率,使您可能与用户保持联系并提供有价值的内容。 拜访https://www.engagelab.com/web-push,申请收费试用! 对于极光极光(Aurora Mobile,纳斯达克股票代码:JG)成立于2011年,是中国当先的客户互动和营销科技服务商。成立之初,极光专一于为企业提供稳固高效的音讯推送服务,凭借先发劣势,曾经成长为市场份额遥遥领先的挪动音讯推送服务商。随着企业对客户触达和营销增长需要的不断加强,极光前瞻性地推出了音讯云和营销云等解决方案,帮忙企业实现多渠道的客户触达和互动需要,以及人工智能和大数据驱动的营销科技利用,助力企业数字化转型。

July 12, 2023 · 1 min · jiezi

关于前端:AIGC浪潮下鹅厂新一代前端人的真实工作感受

腾小云导读 AIGC 这一时代潮流未然不可阻挡,咱们要做的不是慌乱,而是把握住这个时代的机会。本文就和大家一起来摸索在 AIGC 下,前端工程师行将面临的挑战和时机。聊聊从以前到当初,AIGC 给咱们带来了怎么样的变动,下一代前端工程师又该何去何从? 目录 1 疯狂的 AIGC 2 范式迁徙 —— AIGC 下开发模式扭转的实质 2.1 命令式 -> 申明式 2.2 申明式 -> AIGC 式 3 下一代前端工程师 3.1 要长于利用 3.2 要纵观全局 3.3 要懂得批评 3.4 要正当应用 4 将来可期 5 望天下再无码农 6 探讨 6.1 AIGC 下,前端会隐没吗? 6.2 前端开发工程师会过分依赖 AI 吗? 01疯狂的 AIGC记得 ChatGPT4 刚进去的时候,OpenAI 总裁 Greg Brockman 用笔和纸画了一个网页草图,GPT4 仅用几秒的工夫便实现了网页的设计和代码的编写。 不晓得过后前端同学们看到是个怎么的想法哈,反正我过后心都凉了,好不容易把 vue 的源码搞懂了,这就没啥用了,饭碗砸了,蓝瘦香菇。 好吧,开个玩笑 。AI 未然如此,此时就不得不问那个陈词滥调的问题了,前端工程师们该何去何从呢? 想来定有一些同学持乐观态度:前端已死,不值得做上来了,AI 马上就代替了。也会有些同学与之相同吧:AI 来临,神级辅助,又不吃经济,又有大用。我想说的是,AIGC 肯定会对前端开发的将来会产生重大影响,至于这个影响对于前端工程师来说,是正是反,素来都不是工具决定的,而是用工具的人来决定的。咱们要做的,不是去担心焦虑,而是把握住它。 02、范式迁徙 —— AIGC 下开发模式扭转的实质在这之前,咱们先来聊聊前端开发这些年的倒退。 ...

July 12, 2023 · 2 min · jiezi

关于前端:为什么还技术债的人总是我

腾小云导读 不论你的研发团队有如许丰盛的教训,还是领有何等体量的代码,或者是新技术的使用,总会产生肯定水平的技术债。本篇作者进入腾讯十余年,总结剖析了技术债生成的起因并联合集体我的项目经验分享技术债权应答办法。欢送围观~ 目录 1 根本认知 1.1 技术债权的含意 1.2 技术债权无奈打消 2 典型成因 2.1 外因 2.2 内因 3 应答的方法论 3.1 以业余做事为纲 3.2 业余地做事 4 一些具体案例与教训 4.1 一些案例 4.2 一些教训感悟 5 写在最初 5.1 技术债治理须要有价值观的坚守 5.2 放任技术债会毁坏团队 5.3 要放弃对技术事务的资源投入 5.4 要就地取材 5.5 再谈业余地做事 01、根本认知1.1 技术债权的含意所谓技术债权,艰深地讲,其实就是那些技术上没做好的事件,会逐步体现为长期的老本。 如果把视线再拔高一点,其实不单单是技术有债权的问题,业务倒退带来各种各样的债权,例如团队治理、项目管理、常识治理等,其实都可能造成债权。 对于技术债权精确的定义与分类,因为不影响外围的思考,这里不做开展。 1.2 技术债权无奈打消技术债权其实无奈彻底消除的,只有业务在继续运行,就肯定会产生债权,重点是管制债权的规模,使其受控即可。 02、典型成因从不同的维度看,技术债权的成因会有各种各样的类别。这里咱们仅从研发团队的内外视角登程,能够分成外因和内因两大类。 2.1 外因技术倒退因为技术的倒退,原先采纳的技术曾经落后业界,体现为落后于时代的生产力,研发效力落后于竞争对手。 业务倒退因为业务的倒退,原先采纳的技术曾经无奈适应业务,体现为业务受限,或研发效率、品质产生下滑。 团队变动因为组织结构调整,遗留下来的祖传老业务,若不能舍弃,在重复交接后导致保护越来越艰难。 2.2 内因团队治理急功近利的文化,习惯性地将长期利益让位于短期利益,适度谋求短期交付效率。团队人员的选、育、用、留不当,人才培养跟不上,体现为团队成员的能力有余。(没招到 / 没留住 / 没造就出适合的人才,导致团队能力本质上无奈匹配所需解决的问题) 基础薄弱团队所采纳的基础设施落后,没有建设好对立的技术栈底座(根底库、框架、中间件等)。 规范缺失团队没有依据最佳实际,继续建设好标准规范并遵循。 03、应答的方法论3.1 以业余做事为纲这里想换个自顶而下的视角,不盯着债权自身。不单纯地为解决技术债而解决技术债,而是自身就是依照最业余最迷信的形式来做事件,这样天然后果之一就会是技术债规模可控。 3.2 业余地做事做什么有宏观策略思考,指标导向,不要忙于战术而不自知,防止形式主义,不要混同办法伎俩和指标,不要应用伪方法论。 须要有洞察力,对业务、技术、组织架构、组织能力进行顶层思考,做 zero-based thinking。 ...

July 12, 2023 · 1 min · jiezi

关于前端:掌握这些写简历投简历的黑魔法告别简历已读不回

“哎,我还能找到工作吗?”这是最近加我微信的好友,问的最多的一句话。 太卷了最近加我微信的敌人很多,我都很奇怪,最近也没怎么发文章,怎么会有这么多人加我。 大略就是因为太卷了,之前写的待业和接单的文章,被平台举荐了。 最近加我的敌人能够分为两大类:一类是想接私活赚外快的(汗啊,我那篇明显是劝退文,心愿大家好好工作,不要想着接私活,好伐!?)原文链接在这里:程序员接单避坑指南。 怎么就起到反向带货的作用了呢?有的敌人说是因为:文章写的真挚,比拟可信。 哈哈哈,有情理。 另外一类敌人就是收回题目这种感叹,发愁找不到工作,须要简历优化和就业辅导的。 不论是那种,都显著感觉到焦虑和迷茫,难啊。 谁要是说不难,哼,那你可真是佼佼者了! 对,“搞钱能力医治焦虑!”,待业环境再差,再卷,咱们也得想方法解围进去不是。 这篇文章就和大家唠唠:我帮粉丝做了100屡次简历优化后的感触,把对大家有帮忙的共性问题整理出来。 打招呼很多敌人都是依照招聘网站中默认的那几个文案,去打招呼。 这么搞必定不灵的,起因也很简略,80%的人都是这么搞的。 就像“王晗旭”说的一样:太普通了! 你要想方法引起HR的留神。 我送给大家一个打招呼的模板: 你好!我叫xx,全日制统招一本,应聘贵公司Golang后端开发工程师的岗位。有x年的后端开发教训,x年的高并发开发教训。 1. 纯熟应用Gin GoFrame GoZero Kratos等支流框架 2. 纯熟应用Goroutine和Channel,深刻了解CSP模型;深刻了解垃圾回收机制和三色标记法,有过理论调优教训 3. 精通MySQL的底层构造、存储引擎、事务隔离级别、锁、索引、相熟MySQL的优化工作 4. 相熟 Redis 长久化机制,过期策略以及集群部署 5. 相熟NSQ、Kafka等音讯队列事务音讯底层原理,把握音讯失落、音讯反复、音讯幂等问题的解决方案。 想在XX城市找一份Golang开发工程师的工作,冀望可能有机会退出贵公司。更多信息请您浏览我的附件简历,谢谢! 受到启发的敌人千万点个关注哦! 留神:1. 下面提到的Gin GoFrame GoZero Kratos等框架,联合本人状况减少或者删减,保留本人善于的框架 2. 下面提到的NSQ、Kafka、RabbitMQ,联合本人的状况减少或者删减,保留本人善于的技术栈 在线简历(微简历)有些招聘平台是有在线简历,或者叫微简历性能的。 这个灰常重要!肯定要器重!!!认认真真写好喽! 因为很多HR就是先看在线简历,要害信息符合要求,才会下载附件简历的。 投递工夫HR也是人啊,人家也要劳动。 你放假人家也放假。 你到职状态,然而人家退职呀~ 你投递简历是为了让HR看到,并且通过筛选,约面试。所以什么时候投递也很重要。 栈这个数据结构,置信大家都很相熟:先进后出。咱们投递到公司的简历就像入栈一样。 所以,肯定防止在周六日和节假日投递简历,因为会被压入栈底。 比拟好的投递工夫是:周一到周五的上午9点半~11点半,下午1点半~4点半。周五下午尽量也别投递了。 你就换位思考一下: 你下班的时候什么工夫在工作,那也是HR在工作的工夫,能疾速的看到你的简历。 你周五下午想摸鱼,HR也没有那么好的急躁去筛选你的简历。 指标明确你到底是要找哪个岗位?到底是Go?还是Java?还是PHP? 当初待业市场原本就不好,你可别又想学这个,又想做那个,到最初啥都没学好,这是最坑的事件。 找我做辅导的敌人,我会联合他们的状况,先明确好最适宜他们的指标,再奔着这个指标去致力。 千万别在多个指标之间重复横跳,不仅解决不了任何问题,反而会更焦虑。 求职岗位求职岗位有很多敌人不写,甚至还有敌人写了多个,求求你,不要这么干呀! 我晓得你可能懂Golang、Java、Python、PHP、前端你也能写一些,你挺全栈的~ 你就把下面这些语言一股脑都写简历中了,你感觉HR看到你的简历会眼前一亮,理论状况恰恰相反!!! 你如果要找Go的,请你写分明求职岗位:Golang后端开发工程师。 把和Go后端开发间接相干的技术栈放到「专业技能」的前几位,像前端什么的请放到最初或者别写了。 如果你应聘其余岗位,思路也一样,别让HR和面试官去猜! 你要晓得HR每天筛选的简历可能比你投递的公司都多。 ...

July 12, 2023 · 1 min · jiezi

关于前端:占位隐藏与非占位隐藏

占位暗藏含意:只是不可见,但仍占用页面中的地位,只是暗藏了。 $("#div_id").css("visibility", "hidden"); 反:"visible" 非占位暗藏含意:从页面中彻底隐没 $("#div_id").css("display", "none"); 反:"block"、"inline"$("#div_id").hide(); 反: .show()$('#input_id').attr('hidden','true') 反:false 第三种只是用于input标签,它自带有hidden属性,批改该属性来实现非占位暗藏

July 12, 2023 · 1 min · jiezi

关于前端:Vue将后端返回的数据中的字段替换成想要的数据

res.data.data.list = [ { id:"1", name:"Lily", project:"math" }, { id:"2", name:"Lucy", project:"English" }, { id:"3, name:"John", project:"math" },]我想将数据中project为math的全都替换成Chinese 代码: //接口返回的数据下res.data.data.list.forEach(item=>{ item.project = this.changeItem(item.project )})//定义在method中的办法changeItem(value){ if(value.project == 'math'){ value.project = 'Chinese'} else { return value }}

July 12, 2023 · 1 min · jiezi

关于前端:保护你的JavaScript代码深入了解JS混淆加密及其特点

当波及到JavaScript代码的爱护和暗藏时,混同加密是一种常见的技术。它通过对代码进行转换和重组,使其难以了解和逆向工程。以下是JS混同加密的几个特点以及它们各自的优缺点: 变量和函数名压缩: 特点:将代码中的变量和函数名替换为更短、随机的名称,如应用单个字母或无意义的字符串。长处:缩小代码可读性,使代码更难以了解和剖析。这能够减少反向工程的难度。毛病:升高了代码的可维护性和可读性。如果须要调试或批改代码,会变得更加艰难。示例代码:function myFunction() { var a = 1; var b = 2; return a + b;}// 通过混同加密后的代码function f() { var x = 1; var y = 2; return x + y;}字符串和常量加密: 特点:对于敏感字符串和常量,将其进行加密或转换,使其难以间接获取或应用。长处:减少了代码的安全性,避免歹意用户或反向工程师间接获取敏感信息。毛病:减少了代码的复杂性和运行时的开销。在运行时须要进行解密或转换操作。示例代码:// 原始代码var apiKey = "my-api-key";// 通过混同加密后的代码var _0x4e3b=["\x6D\x79\x2D\x61\x70\x69\x2D\x6B\x65\x79"];var apiKey=_0x4e3b[0];代码构造和控制流混同: 特点:批改代码的构造和管制流程,如插入无意义的语句、条件判断的重排和转换等。长处:减少了代码的复杂性,使逆向工程变得更加艰难。代码的用意变得更加含糊。毛病:减少了代码的复杂性和运行时的开销。可能会影响代码的性能和可维护性。示例代码:// 原始代码if (condition) { doSomething();} else { doSomethingElse();}// 通过混同加密后的代码if (1 < 2) { doSomething();} else { doSomethingElse();}通过JS混同加密,能够减少代码的保护性和安全性,使其更难以逆向工程和了解。这能够避免代码被歹意用户盗用、批改或剖析。然而,混同加密也会减少代码的复杂性和运行时的开销,可能升高代码的可维护性和可读性。因而,在应用混同加密技术时,须要衡量安全性和代码品质之间的均衡。 如果您对文章内容有不同认识,或者疑难,欢送到评论区留言,或者私信我、到咱们的官网找客服号都能够。如遇本人js加密源码加密后没备份,能够找咱们解决解出复原源码,任何加密都能够

July 12, 2023 · 1 min · jiezi

关于前端:JVS低代码开发平台多账号统一登录功能介绍

JVS根底框架的定位是企业级的对立信息化的数字底座,对立登录时JVS根底框架最根底的能力,上面咱们先看下登录的演示操作: JVS对立登录性能介绍性能需要阐明 性能需要来源于企业的日常工作过程中,有太多的账号与明码须要记录,因互联网的应用习惯所致,很多客户提出了通过扫码认证登陆的模式,在便捷登陆的同时要保障信息安全的要求,也就是内部的账号 仅仅用于扫码登录,其余的零碎相干信息属于外部零碎, 钉钉登陆、微信登陆、企微登陆等等。JVS构建了对立认证平台,联合对立账户体系实现了三方利用的 对立登陆。如图所示,能够通过钉钉或者三方利用登陆 扫码登陆(钉钉、微信、企微) 零碎登录的背景图反对配置化,不同零碎不同租户能够采纳不同的登录背景图。 对立登录能力JVS整个零碎认证采纳Oauth2 认证计划,目前反对目前登陆形式如下: 对立账户体系JVS实现的对立登录的根底是对立的账户体系, 如图所示,JVS构建了对立的账号,账号能够关联用户的多种信息,包含三方账号关联的信息,用户根本信息等,如下图所示。 用户的账号绑定操作用户登录进入零碎后,点击集体核心, 账号中保留 用户账号名称、邮箱、手机号等根本信息,也可对三方的账号进行关联绑定。 在绑定实现后,反对解绑,解绑后能够持续绑定三方账号。备注:这里反对三方账号绑定是须要零碎先实现三方登录的配置。 利用的单点登录点击单点曾经对接了单点登录的零碎的导航入口,如下图所示 点击对应的零碎图标,即可进入对应零碎,无需登录 进入对应的零碎 登录日志治理JVS提供对立的登录日志,登录日志中蕴含 零碎会自动记录登录的账号、登录人员的昵称、登录形式、登录的IP地址、登录状态、登录的利用名称、登录的设施信息以及登录工夫等。登录模式包含:账号密码,WECHAT_MP(微信扫码登录),inside(外部单点跳转登录)、phone(通过手机号登录),WECHAT_ENTERPRISE(企微登录) 登录性能的配置登录相干性能配置地位如图所示: 在这里,能够设置零碎相干的根底信息,平台名称、登录背景图、零碎logo等操作 在这里,能够设置利用登录的具体认证形式,不同的产品能够有不同的登录认证形式 总结:目前在JVS体系内所有原生利用都是反对多账号对立,其中包含 “无忧·企业文档”、“无忧·企业打算”、“无忧·企业邮筒”、“无忧·视频会议”、“规定引擎”、“JVS智能BI”等等。JVS根底框架开源地址:https://gitee.com/software-minister/jvs-docker-compose

July 12, 2023 · 1 min · jiezi

关于前端:每个前端开发需要了解的15个强大的CSS属性

微信搜寻 【大迁世界】, 我会第一工夫和你分享前端行业趋势,学习路径等等。本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。快来收费体验ChatGpt plus版本的,咱们出的钱 体验地址:https://chat.waixingyun.cn 能够退出网站底部技术群,一起找bug,另外新版作图神器已上线 https://cube.waixingyun.cn/home 这篇文章介绍了15个重要的CSS属性,旨在进步读者的CSS常识和技能。文章以清晰的形式解释了每个属性的作用和用法,并提供了相应的示例代码。通过这篇文章,读者能够理解到一些乏味且实用的CSS属性。 :in-range 和:out-of-range 伪类CSS的:in-range和:out-of-range伪类用于款式化在指定范畴限度内和外的输出。 (a) :in-range如果输出元素的以后值在 min 和 max 属性的范畴之间,那么它就处于范畴内。 这个伪类能够不便地确定字段的以后值是否可承受。 (b) :out-of-range如果输出元素的以后值超出了min和max属性的范畴,那么它就是超出范围的。 它给用户一个视觉批示,通知他们字段值是否超出了范畴。 /* in-range */input:in-range{background-color: rgba(0, 255, 0, 0.25);}/* out-of-range */input:out-of-range{background-color: rgba(255, 0, 0, 0.25);} 留神:这些伪类只实用于具备范畴限度的元素,没有这个限度,元素就无奈处于范畴内或范畴外。 相干文档:https://developer.mozilla.org/en-US/docs/Web/CSS/:in-range 2. grayscale() 函数如果应用0到100%之间的值,能够创立不同的成果。较低的值将保留一些色彩,而较高的值将使图像更靠近黑白。 这种图像成果能够通过CSS的滤镜属性实现。通过将图像的filter属性设置为grayscale(100%),能够将图像齐全转换为黑白。要创立不同的成果,能够尝试不同的grayscale值,例如grayscale(50%)将使图像出现一种半色调成果。 应用CSS的图像转换成果,能够通过调整值来轻松地将彩色图像转换为黑白,并实现各种不同的成果。 .grayscale-image{ filter: grayscale(100%);} 3. 玻璃成果咱们能够应用几行代码实现一个玻璃成果。玻璃成果十分漂亮,能够为咱们的设计削减优雅。 Glass.CSS是最受欢迎的玻璃成果生成器,咱们能够收费为我的项目创立CSS玻璃成果。只须要依据您的需要调整一些设置,并将CSS代码复制粘贴到您的我的项目中即可。 .glass-effect{ -webkit-backdrop-filter: blur(6.2px); backdrop-filter: blur(6.2px); background: rgba(255, 255, 255, 0.4); border-radius: 16px; border: 1px solid rgba(255, 255, 255, 0.24); } ...

July 12, 2023 · 2 min · jiezi

关于前端:Elementui-Select-选择器

Element-ui Select 选择器原文链接:https://note.noxussj.top/?source=sifo 当选项过多时,应用下拉菜单展现并抉择内容。 按需引入形式如果是残缺引入可跳过此步骤 import Vue from 'vue'import { Select, Option } from 'element-ui'import 'element-ui/lib/theme-chalk/base.css'import 'element-ui/lib/theme-chalk/select.css'import 'element-ui/lib/theme-chalk/option.css'Vue.use(Select)Vue.use(Option)根底应用v-model 的值为以后被选中的 el-option 的 value 属性值 <template> <el-select v-model="value" placeholder="请抉择"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select></template><script>export default { data() { return { value: '', options: [ { value: '1', label: '西米露' }, { value: '2', label: '双皮奶' }, { value: '3', label: '龟苓膏' }, { value: '4', label: '烤乳鸽' } ] } }}</script>Select Attributes ...

July 12, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程接口和类

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接接口和类在 TypeScript 中,接口(Interfaces)和类(Classes)是实现面向对象编程(Object-Oriented Programming,OOP)的根底工具。这些工具提供了一种形式来定义和组织简单的数据结构和行为。 接口接口在 TypeScript 中扮演着要害的角色,用于强类型零碎的反对。接口能够形容对象的形态,使咱们能够编写出预期的行为。接口可用于形容对象、函数或者类的公共局部。 以下是一个根本的接口示例: interface LabelledValue { label: string;}function printLabel(labelledObj: LabelledValue) { console.log(labelledObj.label);}let myObj = { size: 10, label: "Size 10 Object" };printLabel(myObj);在这个例子中,LabelledValue接口就像一个名片,通知其余代码,只有一个对象有label属性,并且类型为string,那么就能够认为它是LabelledValue。 接口也能够形容函数类型: interface SearchFunc { (source: string, subString: string): boolean;}let mySearch: SearchFunc;mySearch = function(src: string, sub: string): boolean { let result = src.search(sub); return result > -1;}此外,接口还能用于形容数组和索引类型: interface StringArray { [index: number]: string;}let myArray: StringArray;myArray = ["Bob", "Fred"];interface Dictionary { [index: string]: string;}let myDict: Dictionary;myDict = { "key": "value" };类与传统的 JavaScript 一样,TypeScript 也应用类(Classes)来定义对象的行为。然而,TypeScript 的类具备一些额定的个性,如拜访修饰符(Access Modifiers)、动态属性(Static Properties)、抽象类(Abstract Classes)等。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代TypeScript高级教程函数

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接函数TypeScript提供了丰盛的函数类型定义形式,能够对函数参数、返回值进行类型注解,从而提供了更为弱小的类型查看。 函数申明在TypeScript中,你能够在函数申明中对函数的参数和返回值进行类型注解。以下是一个例子: function add(x: number, y: number): number { return x + y;}在这个例子中,咱们定义了一个add函数,它承受两个参数x和y,这两个参数都是number类型,函数的返回值也是number类型。 如果你尝试调用这个函数并传入一个非数字类型的参数,TypeScript编译器会报错: add("Hello", 1); // Error: Argument of type '"Hello"' is not assignable to parameter of type 'number'.函数表达式在JavaScript中,函数不仅能够通过函数申明的形式定义,还能够通过函数表达式定义。在TypeScript中,函数表达式也能够应用类型注解: let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y;};在下面的例子中,咱们首先定义了myAdd变量的类型为一个函数类型(x: number, y: number) => number,而后将一个匿名函数赋值给myAdd。这个匿名函数的参数x和y的类型是number,返回值的类型也是number。 可选参数和默认参数TypeScript反对可选参数和默认参数。你能够应用?来标记可选参数,或者应用= 来指定参数的默认值: function buildName(firstName: string, lastName?: string) { if (lastName) return firstName + " " + lastName; else return firstName;}let result1 = buildName("Bob"); // works correctly nowlet result2 = buildName("Bob", "Adams"); // ah, just right在下面的例子中,lastName是一个可选参数。你能够不传这个参数调用buildName函数。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代TypeScript高级教程类型

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接类型TypeScript提供了JavaScript的所有根本数据类型,如:number、string、boolean等。它还减少了额定的类型,比方any、unknown、never、void等。 number在TypeScript中,所有的数字都是浮点数。这些数字的类型是number。上面是一些例子: let decimal: number = 6; // 十进制let hex: number = 0xf00d; // 十六进制let binary: number = 0b1010; // 二进制let octal: number = 0o744; // 八进制stringstring类型示意文本数据。你能够应用单引号(')或双引号(")定义字符串,也能够应用反引号(`)定义模板字符串: let color: string = "blue";color = 'red';let fullName: string = `Bob Bobbington`;let age: number = 37;let sentence: string = `Hello, my name is ${ fullName }. I'll be ${ age + 1 } years old next month.`;booleanboolean类型有两个值:true和false: let isDone: boolean = false;Array在TypeScript中,数组类型有两种表达方式。一种是在元素类型前面加上 [],示意由此类型元素组成的一个数组。另一种形式是应用数组泛型,Array<元素类型>: ...

July 11, 2023 · 2 min · jiezi

关于前端:现代TypeScript高级教程概述

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接概述引言在TypeScript的倒退过程中,对类型零碎的继续改良始终是其外围工作。这在2.0版本中引入的严格的空值查看(--strictNullChecks)中体现得尤为显著,这个性能帮忙开发者在编译时捕捉可能的null或undefined援用谬误。 TypeScript 2.1带来了映射类型,这是一种创立新类型的形式,基于旧类型转换其属性。2.8版本则引入了有条件的类型,使得类型零碎具备了更多的表达力。 TypeScript 3.0引入了我的项目援用,这是一种新的架构工具,容许大型项目更容易地组织代码和依赖项。3.7版本中,TypeScript反对了可选链和空值合并运算符,这是两个罕用的JavaScript个性。 在最新的TypeScript版本中,提供了更丰盛的语法个性和工具反对,比方更弱小的类型推导,更准确的类型查看,以及更欠缺的IDE反对。 劣势TypeScript的劣势还包含它的可互操作性。因为TypeScript是JavaScript的超集,所以开发者能够轻松地将JavaScript代码迁徙到TypeScript。同时,开发者还能够应用来自JavaScript生态系统的库和工具。TypeScript还反对最新的ECMAScript个性,如箭头函数、模块、解构等。 TypeScript也为大型项目提供了必要的工具。TypeScript的类型零碎使得开发者能够明确定义对象和函数的构造,这样在大型项目中保护和了解代码就更加简略。此外,TypeScript还有良好的工具反对,比方TSLint和Prettier,这些工具能够帮忙开发者编写更统一、更可读的代码。 在性能方面,因为TypeScript在运行前进行编译,因而能够提前发现并修复很多可能在运行时才会呈现的谬误。这种预编译的形式能够大大提高应用程序的性能,因为运行时须要进行的工作量较少。 TypeScript的类型定义文件(.d.ts)是一个独特的长处,它们为已有的JavaScript库提供类型信息。这使得开发者能够在应用这些库的同时享受到类型查看的益处。而且,因为有大量的开源贡献者,绝大多数风行的JavaScript库都有相应的类型定义文件。 总的来说,TypeScript联合了JavaScript的灵活性和动态类型语言的安全性,使得它成为了古代Web开发的重要工具。

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程页面生命周期

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接页面生命周期: DOMContentLoaded, load, beforeunload, unload引言在 Web 开发中,理解页面生命周期是十分重要的。页面生命周期定义了页面从加载到卸载的整个过程,包含各种事件和阶段。在本文中,咱们将具体介绍四个要害事件:DOMContentLoaded、load、beforeunload 和 unload。咱们将探讨这些事件的属性、API、利用场景,并提供一些代码示例和参考资料。 1. DOMContentLoaded1.1 属性type:事件类型,值为 "DOMContentLoaded"bubbles:布尔值,批示事件是否会冒泡,默认为 falsecancelable:布尔值,批示事件是否能够被勾销,默认为 falsetarget:事件的指标对象,即触发事件的元素1.2 APIEventTarget.addEventListener():用于注册事件监听器,以便在 DOMContentLoaded 事件触发时执行相应的处理函数。1.3 利用场景DOMContentLoaded 事件在页面的 HTML 和 DOM 树加载实现后触发,但在所有内部资源(如图像、样式表、脚本等)加载实现之前。这使得咱们能够在 DOM 加载实现后执行一些操作,例如初始化页面元素、注册事件监听器、执行一些初始的 JavaScript 逻辑等。 常见的利用场景包含: 初始化页面元素注册事件监听器发送初始的 AJAX 申请执行一些初始的 JavaScript 逻辑1.4 示例代码document.addEventListener('DOMContentLoaded', function() { // DOMContentLoaded 事件触发后执行的逻辑 console.log('DOMContentLoaded event triggered');});在下面的示例中,咱们应用 addEventListener 办法注册了一个 DOMContentLoaded 事件监听器。当 DOMContentLoaded 事件触发时,控制台将输入 'DOMContentLoaded event triggered'。 2. load2.1 属性type:事件类型,值为 "load"bubbles:布尔值,批示事件是否会冒泡,默认为 falsecancelable:布尔值,批示事件是否能够被勾销,默认为 falsetarget:事件的指标对象,即触发事件的元素2.2 APIEventTarget.addEventListener():用于注册事件监听器,以便在 load 事件触发时执行相应的处理函数。2.3 利用场景load 事件在整个页面及其所有内部资源(如图像、样式表、脚本等)加载实现后触发。这意味着页面的所有内容曾经可用,并且能够执行与页面渲染和交互相干的操作。 常见的利用场景包含: 执行一些须要页面齐全加载后能力进行的操作初始化和配置第三方库和插件启动动画或其余视觉效果2.4 示例代码 window.addEventListener('load', function() { // load 事件触发后执行的逻辑 console.log('load event triggered');});在下面的示例中,咱们应用 addEventListener 办法注册了一个 load 事件监听器。当 load 事件触发时,控制台将输入 'load event triggered'。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程Performance-API-提升网页性能的利器

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接Performance API: 晋升网页性能的利器引言在古代 Web 开发中,性能优化是一个要害的方面。用户冀望疾速加载的网页,而慢速的加载和响应工夫可能导致用户散失和不良的用户体验。为了满足用户的需要,咱们须要精确地测量和剖析网页的性能,并采取相应的优化措施。 Performance API 是浏览器提供的一组接口,能够让开发者测量和监控网页的性能体现。它提供了丰盛的属性和办法,能够帮忙咱们理解网页加载的工夫、资源的应用状况、代码执行的性能等要害指标。本文将具体介绍 Performance API 的属性和 API,探讨其利用场景,并提供相干的代码示例和援用材料链接。 1. Performance API 简介Performance API 是 Web API 的一部分,旨在提供与浏览器性能相干的信息和指标。它通过提供一组属性和办法,使开发者可能测量和剖析网页的性能,以便进行性能优化。 Performance API 的外围对象是 performance,它代表了网页的性能信息。通过 performance 对象,咱们能够拜访各种性能指标、测量和记录时间戳、计算代码执行工夫等。 以下是一些罕用的 Performance API 属性: navigation:提供了与导航相干的性能指标,如页面加载工夫、重定向次数、响应工夫等。timing:提供了与页面加载和资源加载相干的性能指标,如 DNS 查问工夫、TCP 连接时间、DOM 解析工夫等。memory:提供了与内存应用状况相干的性能指标,如内存限度、已应用内存、垃圾回收次数等。navigationTiming:提供了更具体的页面加载工夫指标,如重定向工夫、解析 DOM 树工夫、首次渲染工夫等。Performance API 还提供了一些办法,用于测量和记录时间戳、增加标记、计算代码执行工夫等。 2. Performance API 属性和 API2.1 navigationperformance.navigation 属性提供了与导航相干的性能指标,能够帮忙咱们理解页面的加载工夫、重定向次数、响应工夫等。 以下是一些罕用的 navigation 属性: performance.navigation.type:示意导航类型,如新页面加载、页面刷新、页面后退等。performance.navigation.redirectCount:示意页面重定向的次数。这些 navigation 属性能够用于剖析页面的导航行为和性能体现。 示例代码: console.log(`导航类型: ${performance.navigation.type}`);console.log(`重定向次数: ${performance.navigation.redirectCount}`);2.2 timingperformance.timing 属性提供了与页面加载和资源加载相干的性能指标,能够帮忙咱们理解页面加载的各个阶段所破费的工夫。 以下是一些罕用的 timing 属性: performance.timing.navigationStart:示意页面开始导航的工夫。performance.timing.fetchStart:示意开始获取页面资源的工夫。performance.timing.domContentLoadedEventStart:示意 DOMContentLoaded 事件开始的工夫。performance.timing.loadEventStart:示意 load 事件开始的工夫。这些 timing 属性能够用于剖析页面的加载性能,找出加载过程中的瓶颈。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程requestAnimationFrame优化动画和渲染的利器

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接requestAnimationFrame:优化动画和渲染的利器引言在Web开发中,实现平滑且高性能的动画和渲染是一个要害的需要。而requestAnimationFrame是浏览器提供的一个用于优化动画和渲染的API。它能够协调浏览器的刷新率,帮忙开发者实现晦涩的动画成果,并提供更高效的渲染形式。本文将具体介绍requestAnimationFrame的属性、利用场景以及应用示例,帮忙读者深刻了解和利用这一弱小的工具。 1. requestAnimationFrame简介requestAnimationFrame是浏览器提供的一个用于优化动画和渲染的API。它基于浏览器的刷新率,调度回调函数的执行,以确保动画和渲染的流畅性和高性能。 应用requestAnimationFrame,开发者能够在每个浏览器刷新帧之前申请执行一个函数。浏览器会在适当的机会调用这个函数,以保障动画和渲染的协调性。通过与浏览器的单干,requestAnimationFrame能够防止不必要的渲染操作,并确保动画的成果更加平滑。 requestAnimationFrame在古代浏览器中失去广泛支持,并成为实现高性能动画和渲染的首选形式。 2. requestAnimationFrame的属性requestAnimationFrame提供了一些属性,用于管制和治理动画和渲染的执行。上面是一些罕用的属性: callback:一个函数,示意要在下一次浏览器刷新帧之前执行的回调函数。id:一个整数,示意回调函数的惟一标识符。能够用于勾销回调函数的执行。通过这些属性,开发者能够准确地管制和治理动画和渲染的执行过程。 3. requestAnimationFrame的利用场景requestAnimationFrame在许多场景下都能施展重要作用。上面是一些常见的利用场景: 3.1 动画成果当须要实现平滑的动画成果时,requestAnimationFrame是一个现实的抉择。通过应用requestAnimationFrame,能够在每个浏览器刷新帧之前更新动画的状态,并在适合的机会进行渲染。这样能够确保动画的流畅性,并缩小不必要的渲染操作。例如,实现平滑的过渡成果、动静的图表展现等都能够应用requestAnimationFrame来实现。 3.2 游戏开发在游戏开发中,高性能和晦涩的渲染是至关重要的。requestAnimationFrame提供了一种高效的渲染形式,能够与游戏引 擎配合应用,实现晦涩的游戏画面和良好的用户体验。通过在每个浏览器刷新帧之前更新游戏的状态并进行渲染,能够实现高性能的游戏成果。例如,实时的射击游戏、跑酷游戏等都能够应用requestAnimationFrame来实现。 3.3 数据可视化在数据可视化的场景中,展现大量的数据并实时更新是一项挑战。应用requestAnimationFrame,能够在每个浏览器刷新帧之前更新数据的可视化状态,并进行相应的渲染。这样能够实现高效的数据可视化,并保持良好的性能和交互性。例如,绘制实时图表、展现动态地图等都能够应用requestAnimationFrame来实现。 3.4 UI动效在网页开发中,为用户提供吸引人的UI动效是一种常见的需要。应用requestAnimationFrame,能够实现各种各样的UI动效,如平滑的滚动成果、突变动画、拖拽成果等。通过在每个浏览器刷新帧之前更新UI状态并进行渲染,能够实现晦涩和高性能的UI动效。 4. 应用requestAnimationFrame的示例上面通过几个示例来演示如何应用requestAnimationFrame来实现动画和渲染成果。 4.1 实现平滑的滚动成果上面的示例代码演示了如何应用requestAnimationFrame实现平滑的滚动成果: function smoothScrollTo(targetY, duration) { const startY = window.pageYOffset; const distance = targetY - startY; const startTime = performance.now(); function step(currentTime) { const elapsedTime = currentTime - startTime; const progress = Math.min(elapsedTime / duration, 1); const ease = easingFunction(progress); window.scrollTo(0, startY + distance * ease); if (elapsedTime < duration) { requestAnimationFrame(step); } } requestAnimationFrame(step);}function easingFunction(t) { return t * t * t;}// 应用示例const button = document.querySelector('#scrollButton');button.addEventListener('click', () => { smoothScrollTo(1000, 1000);});在上述代码中,咱们定义了一个smoothScrollTo函数,用于实现平滑的滚动成果。该函数接管指标地位targetY和滚动的持续时间duration作为参数。在函数外部,咱们获取以后的滚动地位startY和指标地位与起始地位之间的间隔distance。而后,咱们应用performance.now()获取以后的工夫戳startTime,并定义一个step函数用于更新滚动地位。在step函数中,咱们依据工夫的流逝计算出进度progress,并应用缓动函数easingFunction来调整进度。最初,咱们应用 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程MutationObserver监测DOM变化的强大工具

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接MutationObserver:监测DOM变动的弱小工具引言在Web开发中,操作和监测DOM元素的变动是一项常见的工作。MutationObserver是JavaScript提供的一个弱小的API,用于异步监测DOM树的变动,并在发生变化时执行相应的操作。本文将具体介绍MutationObserver的属性、利用场景以及应用示例,帮忙读者充沛了解和利用这一弱小的工具。 1. MutationObserver简介MutationObserver是一个JavaScript的API,用于监测DOM树的变动。它提供了一种异步的形式来监听DOM元素的减少、删除、属性变动等操作,以及文本节点的批改。通过MutationObserver,开发者能够实时地捕捉到DOM的变动,并做出相应的响应。 MutationObserver是在2012年引入的,目前被广泛支持的浏览器(包含Chrome、Firefox、Safari、Edge等)都提供了对MutationObserver的反对。 2. MutationObserver的属性MutationObserver提供了一些属性,用于配置和管制观察器的行为。上面是一些罕用的属性: attributes:是否监测元素的属性变动。attributeOldValue:是否在属性变动时记录旧值。attributeFilter:指定要监测的属性列表。childList:是否监测子元素的增加或移除。subtree:是否监测后辈元素的变动。characterData:是否监测文本节点的内容变动。characterDataOldValue:是否在文本节点内容变动时记录旧值。通过这些属性,能够灵便地配置MutationObserver的察看行为,以满足不同的需要。 3. MutationObserver的利用场景MutationObserver在许多场景下都能施展重要作用。上面是一些常见的利用场景: 3.1 动静内容加载当页面中的内容是通过异步加载或动静生成时,能够应用MutationObserver来监测内容的变动,并在变动产生后进行相应的解决,如更新页面布局、增加事件监听器等。例如,在有限滚动加载的场景中,当新的内容被加载到页面时,能够应用MutationObserver来主动监听内容的变动,并在变动产生后动静增加相应的元素或事件。 3.2 表单验证当须要实时验证用户输出时,能够应用MutationObserver来监测表单元素的变动,以及对应的属性变动,如值的变动、禁用状态的变动等。这样能够及时地对用户的输出进行验证和反馈。例如,在一个表单中,当用户输出时,能够应用MutationObserver来监测输入框的值变动,并在值变动后进行实时的表单验证。 3. 响应式布局当页面布局须要依据DOM变动自适应调整时,能够应用MutationObserver来监测相干元素的变动,并依据变动动静地调整页面布局。例如,在响应式网页设计中,当窗口大小发生变化或元素被增加或移除时,能够应用MutationObserver来监听相干元素的变动,并依据变动从新计算和调整页面布局,以适应不同的设施和屏幕尺寸。 3.4 自定义组件开发在自定义组件的开发中,MutationObserver能够用于监听组件外部的DOM变动,以及对应的属性变动。这样能够在组件外部做出相应的解决,如更新组件的状态、从新渲染组件等。例如,当一个自定义组件中的某个子元素被增加或移除时,能够应用MutationObserver来监听这些变动,并在变动产生后更新组件的状态或从新渲染组件。 4. 应用MutationObserver的示例上面通过几个示例来演示如何应用MutationObserver进行DOM变动的监测。 4.1 监测元素属性变动上面的示例代码演示了如何应用MutationObserver监测元素的属性变动,并在变动产生后进行相应的解决: // 指标元素const targetElement = document.querySelector('#target');// 创立一个MutationObserver实例const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes') { console.log(`属性 ${mutation.attributeName} 发生变化`); // 执行相应的解决逻辑 } });});// 配置观察器const config = { attributes: true,};// 启动观察器observer.observe(targetElement, config);在上述代码中,咱们首先抉择了一个指标元素,而后创立了一个MutationObserver实例。接下来,咱们配置了观察器,指定咱们要监测的变动类型为属性变动。最初,咱们通过调用observe办法,将观察器绑定到指标元素上。 当指标元素的属性发生变化时,MutationObserver的回调函数将被调用,并传递一个mutations参数,该参数蕴含了所有产生的变动。在回调函数中,咱们能够依据变动的类型(mutation.type)来判断具体的变动类型,并执行相应的解决逻辑。 4.2 监测子元素的增加或移除上面的示例代码演示了如何应用MutationObserver监测子元素的增加或移除,并在变动产生后进行相应的解决: // 指标元素const targetElement = document.querySelector('#target');// 创立一个MutationObserver实例const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList') { mutation.addedNodes.forEach((addedNode) => { console.log(`增加了子元素:${addedNode.nodeName}`); // 执行相应的解决逻辑 }); mutation.removedNodes.forEach((removedNode) => { console.log(`移除了子元素:${removedNode.nodeName}`); // 执行相应的解决逻辑 }); } });});// 配置观察器const config = { childList: true,};// 启动观察器observer.observe(targetElement, config);在上述代码中,咱们创立了一个MutationObserver实例,并将观察器配置为监测子元素的增加或移除。当指标元素的子元素产生增加或移除操作时,MutationObserver的回调函数将被调用,并传递一个mutations参数,该参数蕴含了所有产生的变动。在回调函数中,咱们能够依据变动的类型(mutation.type)为childList来判断子元素的增加或移除操作,并执行相应的解决逻辑。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程实现符合PromiseA规范的Promise

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接实现合乎Promise/A+标准的Promise介绍:Promise是JavaScript中解决异步操作的重要工具之一。Promise/A+标准是一种对于Promise实现的规范,它定义了Promise的行为和办法。本文将具体介绍如何实现Promise/A+标准,让你理解Promise的工作原理并可能本人实现一个符合规范的Promise。 Promise/A+标准简介1. Promise的三种状态:pending(进行中):Promise的初始状态,示意异步操作正在执行。fulfilled(已实现):异步操作胜利实现,并返回一个值,称为解决值(fulfillment value)。rejected(已回绝):异步操作失败或被回绝,并返回一个起因(reason),通常是一个谬误对象。2. 状态转换:Promise的状态只能从pending转变为fulfilled或rejected,一旦转变就不可逆转。状态转换是由异步操作的后果决定的。如果异步操作胜利实现,Promise的状态会转变为fulfilled;如果异步操作失败或被回绝,Promise的状态会转变为rejected。3. Promise的根本办法:then办法:用于注册异步操作胜利实现时的回调函数,并返回一个新的Promise对象。它承受两个参数:onFulfilled(可选,异步操作胜利时的回调函数)和onRejected(可选,异步操作失败时的回调函数)。catch办法:用于注册异步操作失败时的回调函数,并返回一个新的Promise对象。它是then办法的一个非凡模式,仅用于捕捉异样。finally办法:无论异步操作胜利或失败,都会执行的回调函数,并返回一个新的Promise对象。它在Promise链中的最初执行,并且不接管任何参数。4. 谬误冒泡和异样传递:Promise/A+标准要求Promise的谬误可能被适当地捕捉和解决。当一个Promise产生谬误时,它会向下流传,直到找到最近的谬误处理函数为止。在Promise链中的任何一个Promise产生谬误,都会导致整个链上的谬误处理函数被调用,以便进行错误处理和复原。遵循Promise/A+标准的实现应该具备上述个性,以确保统一的Promise行为和接口。这样,开发者能够编写通用的异步代码,而无需放心特定Promise实现的差异性。 实现Promise当从零开始实现 Promise/A+ 标准的 Promise,咱们须要逐渐构建 Promise 的外围性能,包含状态治理、状态转换、回调解决和错误处理。 步骤 1: 创立 Promise 构造函数首先,咱们须要创立一个 Promise 构造函数,它承受一个执行器函数作为参数。执行器函数承受两个参数,即 resolve 和 reject 函数,用于管制 Promise 的状态转换。 function MyPromise(executor) { // TODO: 实现构造函数}步骤 2: 初始化 Promise 状态和回调在构造函数中,咱们须要初始化 Promise 的状态和回调数组。状态能够应用一个变量来示意,初始值为 'pending'。回调数组用于存储注册的胜利和失败回调函数。 function MyPromise(executor) { var self = this; self.state = 'pending'; self.value = undefined; self.reason = undefined; self.onFulfilledCallbacks = []; self.onRejectedCallbacks = []; // TODO: 实现构造函数的其余部分}步骤 3: 实现 resolve 和 reject 函数咱们须要实现 resolve 和 reject 函数,用于将 Promise 的状态从 'pending' 转换为 'fulfilled' 或 'rejected'。resolve 函数将传递一个值来兑现 Promise,而 reject 函数将传递一个起因来回绝 Promise。 ...

July 11, 2023 · 5 min · jiezi

关于前端:现代JavaScript高级教程JS中的异步编程与Promise

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JS中的异步编程与Promise一、JavaScript的异步编步机制在理解JavaScript的异步机制之前,咱们首先须要了解JavaScript是一种单线程语言。单线程就意味着所有的工作须要依照程序一次执行,如果前一个工作没有实现,后一个工作就无奈开始。这个个性在执行大量或耗时工作时可能会导致阻塞或者界面卡死,这显然是不可取的。 为了解决这个问题,JavaScript引入了异步编程的机制。简略地说,异步就是你当初收回了一个“命令”,然而并不期待这个“命令”实现,而是继续执行下一个“命令”。只有在“听到”之前的那个“命令”实现了的音讯时,才会回过头来解决这个“命令”的后果。这就是所谓的异步编程。 二、事件循环(Event Loop)和工作队列(Task Queue)这种异步的机制是如何实现的呢?关键在于事件循环(Event Loop)和工作队列(Task Queue)。 事件循环是 JavaScript 外部的一个处理过程,零碎会在此处一直地循环期待,查看工作队列中是否有工作,如果有,就解决它。 而工作队列,就是一个存储待处理工作的队列,当咱们应用 setTimeout、setInterval、ajax等API时,实际上是向工作队列中增加了一个工作。 当主线程闲暇时(也就是同步工作都执行结束),便会去看工作队列里有没有工作,如果有,便将其取出执行;没有的话,则持续期待。 这个模型能够简略地用上面的代码示意: while (true) { let task = taskQueue.pop(); execute(task);}三、宏工作和微工作在工作队列中,工作被分为两类:宏工作(MacroTask)和微工作(MicroTask)。两者的区别在于,宏工作在下一轮事件循环开始时执行,微工作在本轮事件循环完结时执行。这意味着微工作的优先级高于宏工作。 常见的宏工作有:script全文(能够看作一种宏工作)、setTimeout、setInterval、setImmediate(Node.js 环境)、I/O、UI渲染。 常见的微工作有:Promise、process.nextTick(Node.js环境)、MutationObserver(html5新个性)。 事件循环的程序,决定了 JavaScript 代码的执行程序。过程如下: 执行同步代码,这属于宏工作执行栈为空,查问是否有微工作须要执行执行所有微工作必要的话渲染UI而后开始下一轮 Event loop,执行宏工作中的异步代码代码示例如下: console.log('script start'); // 宏工作setTimeout(function() { console.log('setTimeout'); // 宏工作}, 0);Promise.resolve().then(function() { console.log('promise1'); // 微工作}).then(function() { console.log('promise2'); // 微工作});console.log('script end'); // 宏工作输入程序为:script start -> script end -> promise1 -> promise2 -> setTimeout。这是因为JavaScript执行机制决定了微工作比宏工作优先执行。 四、requestAnimationFramerequestAnimationFrame是一个优化动画成果的函数,也有它在事件循环中的地位。 requestAnimationFrame 的调用是有频率限度的,在大多数浏览器里,这个频率是60Hz,也就是说,每一次刷新距离为1000/60≈16.7ms。requestAnimationFrame 的执行机会是在下一次重绘之前,而不是立刻执行。 requestAnimationFrame 的长处是由零碎来决定回调函数的执行机会。如果零碎忙到肯定水平,可能会两次“刷新”之间屡次执行回调函数,这时就能够省略掉一些回调函数的执行。这种机制能够无效节俭 CPU 开销,进步零碎的性能。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程JavaScript-Error-类-异常处理与错误管理

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JavaScript Error 类: 异样解决与谬误治理引言在 JavaScript 开发中,处理错误和异样是十分重要的。Error 类是 JavaScript 内置的谬误对象,它提供了一种规范的形式来示意和解决各种类型的谬误。本文将具体介绍 JavaScript Error 类的属性和 API,探讨其利用场景,并提供一些代码示例和参考资料。 1. Error 类简介Error 类是 JavaScript 提供的内置类之一,它用于示意各种类型的谬误。JavaScript 中的谬误能够分为两类: 内置谬误:由 JavaScript 引擎或运行环境提供的谬误,例如语法错误、类型谬误等。自定义谬误:由开发人员本人创立的谬误,用于示意特定的业务逻辑或程序谬误。Error 类是所有内置谬误的基类,其余内置谬误类(如 SyntaxError、TypeError 等)都继承自 Error 类。自定义谬误也能够继承 Error 类来实现自定义的谬误类型。 2. Error 类属性Error 类具备以下罕用属性: name:示意谬误的名称,通常为字符串。message:示意谬误的形容信息,通常为字符串。stack:示意谬误产生时的堆栈信息,通常为字符串。只在某些环境下可用。这些属性提供了对于谬误的根本信息,能够帮忙开发人员定位和调试谬误。 3. Error 类的 APIError 类提供了一些罕用的办法和属性来解决和治理谬误。上面是一些罕用的 API: Error.prototype.toString():返回示意谬误的字符串,通常为谬误的名称和形容信息的组合。Error.captureStackTrace():用于捕捉谬误产生时的堆栈信息。Error.stackTraceLimit:管制堆栈信息的最大限度。除了这些罕用的 API,Error 类还提供了其余一些办法和属性,用于自定义谬误的行为和解决形式。 4. Error 类的利用场景Error 类在 JavaScript 开发中有宽泛的利用场景,以下是一些常见的利用场景: 错误处理:通过抛出和捕捉 Error 类的实例,能够在程序中捕捉和解决各种类型的谬误。自定义谬误:开发人员能够创立自定义的谬误类型,用于示意特定的业务逻辑或程序谬误。调试和谬误追踪:Error 类提供了堆栈信息,能够帮忙开发人员定位和调试谬误。在理论开发中,咱们通常应用 try-catch 语句块来捕捉和处理错误。以下是一个示例: try { // 可能会产生谬误的代码 throw new Error('Something went wrong');} catch (error) { // 错误处理逻辑 console.error(error.name, error.message);}下面的代码中,咱们应用 throw 关键字抛出一个 Error 类的实例,在 catch 语句块中捕捉并解决该谬误。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程正则表达式的常见问题与练习

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接正则表达式的常见问题与练习正则表达式是面试中常常被提及的主题之一,但很多人在面试中对于正则表达式的问题经常感到困惑。在本节中,我将通过一些常见问题和练习题目来帮忙你更好地了解和把握正则表达式的技巧。 问题一:JavaScript 中的字符串与正则表达式操作在 JavaScript 中,咱们能够应用三个办法来操作字符串和正则表达式:test、exec 和 match。上面是它们的具体用法及括号在这些办法中的作用。 RegExp.prototype.test(): test 是 JavaScript 中正则表达式对象的一个办法,用于检测正则表达式对象与传入的字符串是否匹配。如果匹配,则返回 true,否则返回 false。应用办法如下: regexObj.test(str);示例: /Jack/.test('ack'); // false在 test 办法中,括号只起到分组的作用,例如: /123{2}/.test('123123'); // false/(123){2}/.test('123123'); // trueString.prototype.match(): match 是字符串的办法,它承受一个正则表达式作为参数,并返回字符串中与正则表达式匹配的后果。在 match 办法中,括号的作用有两个: 分组捕捉。捕捉的意思是将用户指定的匹配到的子字符串暂存并返回给用户。当传入的正则表达式没有应用 g 标记时,返回一个数组。数组的第一个值为第一个残缺匹配,后续的值别离为括号捕捉的所有值,并且数组还蕴含以下三个属性: groups:命名捕捉组index:匹配后果的开始下标input:传入的原始字符串示例: const result1 = '123123'.match(/123{2}/); // nullconst result2 = '123123'.match(/(123){2}/); // ["123123", "123", index: 0, input: "123123", groups: undefined]console.log(result2.index); // 0console.log(result2.input); // 123123console.log(result2.groups); // undefined当传入的正则表达式有 g 标记时,将返回所有与正则表达式匹配的后果,疏忽捕捉。 RegExp.prototype.exec(): exec 是正则表达式的办法,它承受一个字符串作为参数,并返回与正则表达式匹配的后果。返回后果是一个数组,其中蕴含了匹配到的信息。在 exec 办法中,括号的作用同样是分组和捕捉。 当传入的正则表达式没有应用 g 标记时,每次调用 exec 办法都会返回第一个匹配后果的信息数组,包含匹配的字符串、分组捕捉的值以及其余属性。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程Date类日期和时间处理

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接Date类:日期和工夫解决引言在JavaScript中,Date类是用于解决日期和工夫的内置类。它提供了一系列属性和办法,使咱们可能操作和治理日期、工夫、时区等相干信息。本文将具体介绍Date类的属性、罕用办法以及利用场景,并提供相应的代码示例。 1. Date类的属性Date类具备以下罕用属性: Date.prototype.constructor:返回创建对象实例的构造函数。对于Date类实例,该属性始终指向Date构造函数。Date.prototype.toString():返回一个示意日期和工夫的字符串,通常以本地工夫格局显示。Date.prototype.toISOString():返回一个合乎ISO 8601规范的日期和工夫字符串,格局为YYYY-MM-DDTHH:mm:ss.sssZ。Date.prototype.valueOf():返回一个示意日期对象的原始值的数值,即自1970年1月1日午夜(格林威治工夫)以来通过的毫秒数。2. Date类的罕用办法2.1 日期和工夫获取办法Date.prototype.getFullYear():获取年份(四位数)。Date.prototype.getMonth():获取月份,返回值范畴为0(一月)到11(十二月)。Date.prototype.getDate():获取日期,返回值范畴为1到31。Date.prototype.getHours():获取小时数,返回值范畴为0到23。Date.prototype.getMinutes():获取分钟数,返回值范畴为0到59。Date.prototype.getSeconds():获取秒数,返回值范畴为0到59。Date.prototype.getMilliseconds():获取毫秒数,返回值范畴为0到999。2.2 日期和工夫设置办法Date.prototype.setFullYear(year[, month[, day]]):设置年份。Date.prototype.setMonth(month[, day]):设置月份。Date.prototype.setDate(day):设置日期。Date.prototype.setHours(hour[, min[, sec[, ms]]]):设置小时数。Date.prototype.setMinutes(min[, sec[, ms]]):设置分钟数。Date.prototype.setSeconds(sec[, ms]):设置秒数。Date.prototype.setMilliseconds(ms):设置毫秒数。2.3 格式化办法Date.prototype.toLocaleDateString():返回一个示意日期局部的字符串,依据本地工夫格式化。Date.prototype.toLocaleTimeString():返回一个示意工夫局部的字符串,依据本地工夫格式化。Date.prototype.toLocaleString():返回一个示意日期和工夫的字符串,依据本地工夫格式化。2.4 日期和工夫计算方法Date.prototype.getTime():返回一个示意日期对象的工夫值,即自1970年1月1日午夜(格林威治工夫)以来通过的毫秒数。Date.prototype.setTime(timeValue):设置日期对象的工夫值。Date.prototype.getTimezoneOffset():返回以后零碎时区与UTC之间的时间差,以分钟为单位。 Date.prototype.addDays(days):在以后日期根底上减少指定天数。Date.prototype.addMonths(months):在以后日期根底上减少指定月份数。Date.prototype.addYears(years):在以后日期根底上减少指定年份数。3. Date类的利用场景Date类在JavaScript中广泛应用于以下场景: 日期和工夫解决:Date类提供了丰盛的办法来解决日期和工夫,包含日期格式化、日期比拟、日期计算等。这在开发中常常须要对日期和工夫进行操作的场景中十分有用,如日历利用、倒计时、时间轴等。时区解决:Date类反对获取以后零碎时区与UTC之间的时间差,以及设置特定时区的日期和工夫。这对于全球化的利用、跨时区的事件调度、时区转换等十分重要。日期和工夫展现:通过Date类提供的办法,咱们能够依据本地工夫格局将日期和工夫展现给用户。这在用户界面的日期抉择、音讯工夫显示等场景中十分常见。日期的存储和传输:在与服务器进行数据交互时,经常须要将日期数据存储或传输。Date类提供了获取日期的工夫值、转换为ISO字符串等办法,不便数据的存储和传输。 Date类:日期和工夫解决4. 罕用的Date办法实现上面是一些罕用的Date办法的实现代码示例,以展现它们的根本用法: 4.1 格式化日期和工夫4.1.1 实现format办法Date.prototype.format = function(format) { const year = this.getFullYear(); const month = String(this.getMonth() + 1).padStart(2, '0'); const day = String(this.getDate()).padStart(2, '0'); const hours = String(this.getHours()).padStart(2, '0'); const minutes = String(this.getMinutes()).padStart(2, '0'); const seconds = String(this.getSeconds()).padStart(2, '0'); format = format.replace('YYYY', year); format = format.replace('MM', month); format = format.replace('DD', day); format = format.replace('HH', hours); format = format.replace('mm', minutes); format = format.replace('ss', seconds); return format;};// 应用示例const date = new Date();const formattedDate = date.format('YYYY-MM-DD HH:mm:ss');console.log(formattedDate);4.1.2 实现toISODate办法Date.prototype.toISODate = function() { const year = this.getFullYear(); const month = String(this.getMonth() + 1).padStart(2, '0'); const day = String(this.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`;};// 应用示例const date = new Date();const isoDate = date.toISODate();console.log(isoDate);4.2 计算两个日期之间的天数差Date.prototype.getDaysDiff = function(otherDate) { const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数 const diffInTime = Math.abs(this - otherDate); const diffInDays = Math.round(diffInTime / oneDay); return diffInDays;};// 应用示例const date1 = new Date('2022-01-01');const date2 = new Date('2022-01-10');const daysDiff = date1.getDaysDiff(date2);console.log(daysDiff); // 输入 94.3 获取以后月份的第一天和最初一天Date.prototype.getFirstDayOfMonth = function() { const year = this.getFullYear(); const month = this.getMonth(); return new Date(year, month, 1);};Date.prototype.getLastDayOfMonth = function() { const year = this.getFullYear(); const month = this.getMonth() + 1; return new Date(year, month, 0);};// 应用示例const date = new Date();const firstDayOfMonth = date.getFirstDayOfMonth();const lastDayOfMonth = date.getLastDayOfMonth();console.log(firstDayOfMonth);console.log(lastDayOfMonth);总结本文介绍了Date类的属性、利用场景,并提供了一些罕用的Date办法的实现代码示例。Date类在JavaScript中用于解决日期和工夫相干的操作十分重要,把握其根本用法可能帮忙咱们更好地解决和治理日期和工夫。通过逐渐学习和实际,咱们能够在理论我的项目中灵活运用Date类,满足各种日期和工夫解决的需要。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程JS-Shadow-DOM创建封装的组件和样式隔离

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JS Shadow DOM:创立封装的组件和款式隔离引言在古代的 Web 开发中,组件化和款式隔离是十分重要的概念。为了解决这些问题,Web 规范引入了 Shadow DOM 技术。Shadow DOM 容许开发者创立封装的组件,并将组件的款式和行为隔离在组件的 Shadow DOM 外部。本文将具体介绍 Shadow DOM 的属性和 API,并探讨其在理论开发中的利用场景。 1. 什么是 Shadow DOMShadow DOM 是一项 Web 规范,用于创立封装的组件并实现款式隔离。它容许将组件的 HTML 构造、款式和行为封装在一个独立的 DOM 树中,从而与主文档的 DOM 树互相隔离。通过这种形式,开发者能够创立具备独立款式和行为的组件,而不必放心与其余组件或主文档的款式抵触。 2. Shadow DOM APIShadow DOM 提供了一系列用于操作和治理 Shadow DOM 的 API。 2.1 增加 Shadow Root:attachShadow(options)attachShadow 办法用于将 Shadow DOM 附加到指定的元素上。它接管一个 options 参数,用于指定 Shadow DOM 的模式。 const hostElement = document.getElementById('host-element');const shadowRoot = hostElement.attachShadow({ mode: 'open' });2.2 获取 Shadow Root:shadowRootshadowRoot 属性返回与元素关联的 Shadow Root。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程前端跨页面通信实现页面间的数据传递与交互

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接前端跨页面通信:实现页面间的数据传递与交互引言在前端开发中,有时咱们须要在不同的页面之间进行数据传递和交互。这种场景下,前端跨页面通信就显得尤为重要。前端跨页面通信是指在不同的页面之间传递数据、发送音讯以及实现页面间的交互操作。本文将具体介绍前端跨页面通信的属性、利用场景以及实现办法,并提供一些代码示例和援用材料,帮忙读者深刻理解并利用这一重要的技术。 1. 前端跨页面通信的概述前端跨页面通信是指在不同的浏览器页面或标签页之间进行数据传递和交互的过程。在单页面利用(Single-Page Application)中,这种通信往往是在同一页面的不同组件之间进行的,而在多页面利用(Multi-Page Application)中,通信波及到不同的页面之间的数据传递和交互。 前端跨页面通信的目标是实现不同页面之间的信息共享和合作,使得用户在不同页面间的操作可能产生相应的成果和影响。通过跨页面通信,咱们能够实现以下性能: 在不同页面之间传递数据和状态。发送音讯和告诉。同步数据和状态的更新。实现页面间的合作和交互操作。理解前端跨页面通信的属性、利用场景和实现办法对于构建简单的前端利用和提供良好的用户体验至关重要。 2. 前端跨页面通信的属性前端跨页面通信具备以下几个重要的属性: 2.1 双向通信前端跨页面通信是双向的,即页面之间能够互相发送和接管音讯。不仅能够从一个页面向另一个页面发送数据和音讯,还能够接管来自其余页面的数据和音讯。这种双向通信使得页面之间能够实现实时的数据交互和状态同步。 2.2 异步通信前端跨页面通信是异步的,即数据和音讯的传递是非阻塞的。不同页面之间能够同时发送和接管音讯,不须要期待对方的响应。这种异步通信的个性使得页面间的交互可能更加晦涩和高效。 2.3 安全性前端跨页面通信的安全性是一个重要的思考因素。因为波及到不同页面之间的数据传递,咱们须要确保通信过程的安全性,避免歹意攻打和数据泄露 。在设计和实现跨页面通信时,须要留神采取平安的策略和机制,如数据加密、身份验证等。 2.4 可靠性前端跨页面通信须要具备肯定的可靠性,即保障音讯的精确传递和接管。在网络不稳固或通信中断的状况下,应该可能复原通信并确保数据的完整性。为了实现牢靠的跨页面通信,咱们能够应用适合的机制,如音讯确认、重试机制等。 3. 前端跨页面通信的利用场景前端跨页面通信能够利用于各种场景,满足不同的需要。上面介绍几个常见的利用场景: 3.1 多标签页间的数据共享在多标签页的利用中,不同的标签页可能须要共享一些数据或状态。通过跨页面通信,能够在不同的标签页之间传递数据,使得数据的更新可能在各个标签页中同步。 例如,一个电子商务网站中的购物车性能,用户能够在一个标签页中增加商品到购物车,而在另一个标签页中也可能实时看到购物车的变动。这就须要通过跨页面通信将购物车的数据在不同标签页之间进行同步。 3.2 页面间的音讯告诉和事件触发在页面间进行音讯告诉和事件触发是前端跨页面通信的常见利用场景之一。通过跨页面通信,能够向其余页面发送音讯,告诉它们产生了某个事件或状态的扭转。 例如,一个在线聊天利用中,当用户在一个页面发送音讯时,须要通过跨页面通信将音讯发送给其余页面,以实现实时的音讯同步和告诉。 3.3 页面间的数据传递和共享页面间的数据传递和共享是前端跨页面通信的外围利用场景之一。通过跨页面通信,能够在不同的页面之间传递数据,实现数据的共享和交互。 例如,一个表单提交页面和一个后果展现页面之间须要传递数据。能够通过跨页面通信将表单提交的数据传递给后果展现页面,以便展现提交后果。 3.4 协同编辑和实时合作前端跨页面通信还能够用于实现协同编辑和实时合作的性能。通过跨页面通信,多个用户能够同时编辑同一个文档或画布,并实时看到其余用户的编辑内容。 例如,一个协同编辑的文档利用中,多个用户能够同时编辑同一个文档,并实时看到其余用户的编辑操作。这就须要通过跨页面通信将用户的编辑内容进行同步和交互。 4. 前端跨页面通信的实现办法在前端中,有多种办法能够实现跨页面通信。上面介绍几种罕用的实现办法: 4.1 CookieCookie是一种在浏览器中存储数据的机制,能够通过设置Cookie的值在不同页面之间传递数据。通过设置雷同的Cookie名称和值,不同的页面能够读取和批改Cookie的值,实现跨页面数据的传递和共享。 应用Cookie进行跨页面通信的示例代码如下: // 在页面 A 中设置 Cookiedocument.cookie = "data=example";// 在页面 B 中读取 Cookieconst cookies = document.cookie.split("; ");for (let i = 0; i < cookies.length; i++) { const [name, value] = cookies[i].split("="); if (name === "data") { console.log(value); // 输入 "example" break; }}4.2 LocalStorage 和 SessionStorageLocalStorage和SessionStorage是浏览器提供的本地存储机制,能够在不同页面之间存储和读取数据。它们的区别在于数据的生命周期,LocalStorage中的数据在浏览器敞开后依然保留,而SessionStorage中的数据在会话完结后被革除。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程-JavaScript修饰器简化代码增强功能

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JavaScript润饰器:简化代码,加强性能引言在JavaScript中,润饰器(Decorator)是一种非凡的语法,用于批改类、办法或属性的行为。润饰器提供了一种简洁而灵便的形式来扩大和定制代码性能。本文将具体介绍JavaScript润饰器的概念、语法和利用场景,并提供相干的代码示例。 1. 润饰器简介润饰器是一种用于批改类、办法或属性的语法,它能够在不批改原始代码的状况下加强其性能。润饰器能够实现横切关注点(cross-cutting concerns)的性能,例如日志记录、性能剖析、缓存等。通过将这些性能与原始代码拆散,咱们能够更好地组织和保护代码,并实现更高的可重用性和可扩展性。 2. 润饰器语法润饰器应用@符号作为前缀,紧跟着润饰器函数或类。润饰器能够接管不同的参数,依据润饰的指标不同,参数也会有所区别。润饰器能够独自应用,也能够通过组合多个润饰器来实现更简单的性能。 上面是一个根本的润饰器语法示例: @decoratorclass MyClass { @propertyDecorator myProperty = 123; @methodDecorator myMethod() { // 代码逻辑 }}3. 类润饰器利用场景类润饰器用于批改类的行为和属性。它能够在类定义之前利用,以批改类的构造函数或原型。 常见的利用场景包含: 日志记录:在类的办法执行前后记录日志信息。验证和受权:对类的办法进行验证和受权操作。性能剖析:测量类的办法执行工夫,进行性能剖析。依赖注入:为类的构造函数注入依赖项。示例代码上面是一个应用类润饰器实现日志记录 的示例: function log(target) { const originalConstructor = target; function newConstructor(...args) { console.log(`Creating instance of ${originalConstructor.name}`); return new originalConstructor(...args); } return newConstructor;}@logclass MyClass { constructor(name) { this.name = name; }}const myObj = new MyClass("John");在下面的示例中,咱们定义了一个名为log的润饰器函数。该润饰器函数接管一个参数target,示意要润饰的类构造函数。在润饰器函数外部,咱们将原始的构造函数保留到originalConstructor中,并创立一个新的构造函数newConstructor,该构造函数在创立实例前打印日志信息。最初,咱们将新的构造函数返回作为润饰后的类构造函数。 4. 办法润饰器利用场景办法润饰器用于批改类的办法行为。它能够在办法定义之前利用,以批改办法的个性和行为。 常见的利用场景包含: 日志记录:在办法执行前后记录日志信息。验证和受权:对办法进行验证和受权操作。性能剖析:测量方法执行工夫,进行性能剖析。缓存:为办法增加缓存性能,进步性能。示例代码上面是一个应用办法润饰器实现日志记录的示例: function log(target, name, descriptor) { const originalMethod = descriptor.value; descriptor.value = function(...args) { console.log(`Executing method ${name}`); const result = originalMethod.apply(this, args); console.log(`Method ${name} executed`); return result; }; return descriptor;}class MyClass { @log myMethod() { // 代码逻辑 }}const myObj = new MyClass();myObj.myMethod();在下面的示例中,咱们定义了一个名为log的润饰器函数。该润饰器函数接管三个参数,别离是target(类的原型或构造函数)、name(办法名)和descriptor(办法的属性描述符)。在润饰器函数外部,咱们获取原始办法并将其保留到originalMethod中。而后,咱们批改descriptor.value,将其替换为一个新的函数,该函数在执行原始办法前后打印日志信息。最初,咱们返回批改后的属性描述符。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程深入理解JSONstringify

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接深刻了解JSON.stringify引言在 JavaScript 中,JSON.stringify() 是一个内置函数,用于将 JavaScript 对象转换为 JSON 字符串。JSON(JavaScript Object Notation)是一种轻量级的数据交换格局,宽泛用于前后端数据传输和存储。本文将具体介绍 JSON.stringify() 的属性、利用场景,并提供一个残缺而优雅的实现,解决循环援用、非凡类型(如日期和正则表达式)以及性能相干的问题。同时,咱们还将探讨注意事项和相干援用材料。 1. JSON.stringify() 属性JSON.stringify() 函数具备以下属性: replacerreplacer 是一个可选的参数,它能够是一个函数或一个数组。它用于指定须要序列化的对象的属性。当 replacer 是一个函数时,它将被利用于对象的每个属性,能够用来过滤、替换或转换属性的值。当 replacer 是一个数组时,只有数组中蕴含的属性才会被序列化。 示例: const obj = { name: 'John', age: 25, address: { city: 'New York', country: 'USA' }};const jsonString = JSON.stringify(obj, ['name', 'age']);console.log(jsonString);// 输入: {"name":"John","age":25}spacespace 是一个可选的参数,用于管制生成的 JSON 字符串的缩进和格式化。它能够是一个数字示意缩进的空格数,或者是一个字符串示意缩进的字符串。如果 space 是一个非负整数,则每一级缩进应用指定数量的空格;如果 space 是一个字符串,则应用该字符串作为缩进符号。 示例: const obj = { name: 'John', age: 25 };const jsonString = JSON.stringify(obj, null, 2);console.log(jsonString);// 输入:// {// "name": "John",// "age": 25// }toJSON如果要序列化的对象具备 toJSON() 办法,那么该办法将被调用,以便返回可序列化的值。toJSON() 办法能够在对象中定义,用于自定义对象在序列化过程中的行为。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程深入理解Proxy

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接深刻了解Proxy在古代JavaScript中,Proxy是一种十分有用的个性,它容许咱们在许多惯例操作中插入自定义行为。然而,因为其深度和复杂性,很多开发者可能会对如何应用它或它的工作原理感到困惑。在本篇文章中,咱们将具体探讨JavaScript Proxy,并通过代码示例演示其应用。 Proxy是什么?在JavaScript中,Proxy是一个非凡的“包装器”对象,它能够用于批改或扩大某些基本操作的行为,比方属性读取、函数调用等。这种批改或扩大的行为是通过所谓的"traps"实现的,这些"traps"定义了如何拦挡和扭转基本操作。 以下是一个简略的例子,显示了如何应用Proxy拦挡对象的属性读取操作: let target = { name: "target"};let proxy = new Proxy(target, { get: function(target, property) { return property in target ? target[property] : "Default"; }});console.log(proxy.name); // 输入 "target"console.log(proxy.unknown); // 输入 "Default"在下面的例子中,当咱们尝试从proxy读取不存在的属性时,咱们失去了"default",而不是通常的"undefined"。这是因为咱们的"get" trap拦挡了读取操作,并返回了默认值。 Proxy的用处Proxy有许多用处,上面是一些常见的例子: 数据校验Proxy能够用于校验设置对象属性的值: let validator = { set: function(target, property, value) { if (property === "age") { if (!Number.isInteger(value)) { throw new TypeError("The age is not an integer"); } if (value < 0 || value > 200) { throw new RangeError("The age is invalid"); } } target[property] = value; return true; }};let person = new Proxy({}, validator);person.age = 100; // 失常console.log(person.age); // 输入 100person.age = "young"; // 抛出 TypeError: The age is not an integerperson.age = 300; // 抛出 RangeError: The age is invalid数据绑定和察看Proxy能够用于实现数据绑定和察看(数据变动的监听): ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程Iterator-迭代器简化集合遍历的利器

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接Iterator 迭代器:简化汇合遍历的利器引言在 JavaScript 中,迭代器(Iterator)是一种用于遍历汇合的接口。迭代器提供了一种对立的形式来拜访汇合中的元素,无论汇合的类型和内部结构如何。通过应用迭代器,咱们能够轻松地遍历数组、对象、Map、Set 等各种数据结构,并进行相应的操作。本文将具体介绍迭代器的概念、属性、利用场景,并提供相干的代码示例。 1. 迭代器的概念迭代器是一种遍历汇合的接口,它提供了对立的形式来拜访汇合中的元素。迭代器对象是一个具备特定构造的对象,其中蕴含一个 next 办法,用于返回汇合中的下一个元素。 迭代器的工作原理如下: 创立一个迭代器对象,通常通过调用汇合对象的 Symbol.iterator 办法来获取迭代器对象。调用迭代器对象的 next 办法,每次调用都会返回一个蕴含 value 和 done 两个属性的对象。 value 示意汇合中的一个元素。done 示意迭代是否已实现,如果为 true,则示意迭代完结;如果为 false,则示意还有更多元素可供遍历。反复调用 next 办法,直到迭代完结。JavaScript 中的数组、对象、Map、Set 等数据结构都实现了迭代器接口,因而咱们能够应用迭代器来遍历它们的元素。 2. 迭代器的属性迭代器对象具备以下两个重要的属性: next() 办法:该办法返回一个蕴含 value 和 done 两个属性的对象。 value:示意汇合中的一个元素。done:示意迭代是否已实现,如果为 true,则示意迭代完结;如果为 false,则示意还有更多元素可供遍历。Symbol.iterator 办法:该办法返回迭代器对象本身,用于反对迭代器的迭代。3. 迭代器的利用场景迭代器在 JavaScript 中有许多利用场景,上面是一些常见的利用场景: 3.1 数组遍历应用迭代器能够轻松遍历数组的所有元素。通过调用数组对象的 Symbol.iterator 办法,能够获取一个迭代器对象,而后应用迭代器的 next 办法一一拜访数组的元素。 示例代码: const arr = [1, 2, 3, 4, 5];const iterator = arr[Symbol.iterator]();let result = iterator.next();while (!result.done) { console.log(result.value); result = iterator.next();}3.2 对象遍历应用迭代器能够遍历对象的所有属性。通过调用对象的 Symbol.iterator 办法,能够获取一个迭代器对象,而后应用迭代器的 next 办法一一拜访对象的属性。 ...

July 11, 2023 · 2 min · jiezi

关于前端:现代JavaScript高级教程JavaScript函数式编程

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JavaScript函数式编程引言函数式编程(Functional Programming)是一种编程范式,它将计算机程序视为数学函数的组合,强调函数的纯正性和不可变性。JavaScript作为一种多范式的语言,也反对函数式编程格调。本文将介绍JavaScript函数式编程的基本概念和特点,并通过代码示例来展现其理论利用。 1. 什么是函数式编程?函数式编程是一种基于数学函数的编程范式,它强调将计算过程看作是数学函数的组合。函数式编程的核心思想是将程序合成为一系列函数的调用,而不是通过批改共享状态来改变程序的执行。函数式编程强调函数的纯正性(Pureness)、不可变性(Immutability)和无副作用(No Side Effects)。 在JavaScript中,函数是一等公民,即函数能够作为值进行传递和操作。函数式编程利用这一个性,通过组合和操作函数来构建程序,而不是通过批改变量的值。 2. 纯函数和不可变性纯函数是函数式编程的外围概念之一,它具备以下特点: 函数的输入只由输出决定,不受内部状态的影响。函数对雷同的输出始终返回雷同的输入。函数没有副作用,即不批改内部状态。纯函数的益处在于可测试性、可缓存性和可组合性。因为纯函数没有副作用,它们在并行执行和调试时更容易解决。 不可变性是函数式编程的另一个重要概念,它指的是数据一旦创立就不能被批改。在JavaScript中,对象和数组是可变的,但咱们能够通过函数式编程的形式来实现不可变性。 const numbers = [1, 2, 3, 4, 5];// 应用不可变性的形式将数组元素加倍const doubledNumbers = numbers.map(num => num * 2);console.log(numbers); // 输入:[1, 2, 3, 4, 5]console.log(doubledNumbers); // 输入:[2, 4, 6, 8, 10]在上述示例中,通过应用map()办法和箭头函数,咱们创立了一个新的数组doubledNumbers,而不是间接批改原始的numbers数组。这种不可变性的操作确保了数据的纯正性,防止了副作用。 3. 高阶函数高阶函数是指承受一个或多个函数作为参数,并/或返回一个新的函数的函数。高阶函数是函数式编程的重要工具,它能够将函数作为数据进行操作和组合。 // 高阶函数示例:map()function map(fn, array) { const result = []; for (let i = 0; i < array.length; i++) { result.push(fn(array[i])); } return result;}// 应用高阶函数map()对数组元素进行加倍const numbers = [1, 2, 3, 4, 5];const doubledNumbers = map(num => num * 2, numbers);console.log(doubledNumbers); // 输入:[2, 4, 6, 8, 10]在上述示例中,咱们定义了一个高阶函数map(),它承受一个函数和一个数组作为参数,对数组的每个元素利用给定的函数,并返回一个新的数组。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程面向对象编程与Class

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接面向对象编程与Class引言随着JavaScript的倒退,ECMAScript 6(ES6)引入了许多新的语言个性和语法糖,其中包含了面向对象编程的Class(类)机制。Class提供了一种更简洁、更直观的形式来定义对象和操作对象的行为。本文将介绍ES6中Class的概念、语法和个性,并通过示例代码来阐明其理论利用。 1. 什么是面向对象编程?面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它将程序中的对象作为根本单元,通过封装、继承和多态等机制来组织和治理代码。面向对象编程将事实世界中的实体形象为代码中的对象,对象领有本人的状态(属性)和行为(办法),并与其余对象进行交互。 面向对象编程有以下几个外围概念: 封装(Encapsulation):将数据和操作数据的办法封装在一个对象中,使其成为一个独立的实体,内部无奈间接拜访对象的外部实现细节。继承(Inheritance):通过定义一个基类(父类),其余类能够继承该基类的属性和办法,并能够在此基础上进行扩大或笼罩。多态(Polymorphism):不同对象能够对雷同的办法做出不同的响应,即同一个办法能够依据调用对象的不同而具备不同的行为。面向对象编程的劣势包含代码的可重用性、可维护性、扩展性和灵活性等。 2. Class的基本概念在ES6之前,JavaScript中的对象和面向对象编程的概念绝对比拟含糊。ES6引入了Class机制,使得JavaScript能够更加直观地定义和应用类。Class是一种非凡的函数,通过Class关键字定义。Class中能够定义构造函数、属性和办法等。 一个简略的Class示例如下: class Rectangle { constructor(width, height) { this.width = width; this.height = height; } area() { return this.width * this.height; } perimeter() { return 2 * (this.width + this.height); }}在上述示例中,咱们定义了一个名为Rectangle的类, 它具备width和height两个属性,以及area()和perimeter()两个办法。通过Class定义的类能够通过实例化来创立具体的对象,并调用其属性和办法。 const rect = new Rectangle(5, 3);console.log(rect.area()); // 输入:15console.log(rect.perimeter()); // 输入:163. Class的语法ES6中Class的语法绝对简洁明了。一个Class能够蕴含构造函数、属性和办法等。上面介绍一些罕用的语法规定: 3.1 构造函数在Class中应用constructor关键字定义构造函数。构造函数用于创建对象时进行初始化操作,通过new关键字实例化类时会主动调用构造函数。 class Rectangle { constructor(width, height) { this.width = width; this.height = height; }}构造函数中的this关键字示意以后实例化的对象。 3.2 属性在Class中能够定义各种属性。属性能够间接定义在Class的外部,也能够在构造函数中通过this关键字进行定义。 class Rectangle { width = 0; // 间接定义属性 height = 0; constructor(width, height) { this.width = width; // 在构造函数中定义属性 this.height = height; }}3.3 办法在Class中定义的函数称为办法。能够间接在Class的外部定义方法,也能够应用ES6的简写模式。 ...

July 11, 2023 · 3 min · jiezi

关于前端:现代JavaScript高级教程深入理解JavaScript中的WeakMap和WeakSet

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接深刻了解JavaScript中的WeakMap和WeakSet在JavaScript的ES6版本中,引入了两种新的数据结构——WeakMap和WeakSet。与Map和Set相比,这两种数据结构有一些非凡的特点和用处,因而在某些场合下,它们是更好的抉择。本文将深入探讨WeakMap和WeakSet的个性和用处。 1. WeakMap和WeakSet概述在咱们深入研究这两种新的数据结构之前,首先来理解一下它们的根本个性。 1.1 WeakMapWeakMap是一种键值对的汇合,相似于Map。不过,WeakMap与Map有几个重要的区别: 在WeakMap中,只有对象能够作为键。换句话说,咱们不能应用根本类型(如数字,字符串,布尔值等)作为WeakMap的键。WeakMap的键是弱援用的。这意味着,如果一个对象只被WeakMap援用,那么这个对象能够被垃圾回收(GC)。当这个对象被垃圾回收后,它对应的键值对也会从WeakMap中主动移除。WeakMap不可遍历,也就是说,咱们不能应用像for...of这样的循环来遍历WeakMap。因为这些个性,WeakMap在解决内存透露问题和治理对象公有数据等场景中有着显著的劣势。 1.2 WeakSetWeakSet也是一种汇合,相似于Set。WeakSet与Set的次要区别包含: 在WeakSet中,只有对象能够作为值。也就是说,咱们不能将根本类型(如数字,字符串,布尔值等)增加到WeakSet中。WeakSet中的对象是弱援用的。如果一个对象只被WeakSet援用,那么这个对象能够被垃圾回收。当这个对象被垃圾回收后,它会主动从WeakSet中移除。WeakSet不可遍历,也就是说,咱们不能应用像for...of这样的循环来遍历WeakSet。WeakSet在解决对象的唯一性、内存透露等问题上有其独特的利用。 2. WeakMap深刻解析上面,咱们将更深刻地探讨WeakMap的个性和用法。 2.1 WeakMap的创立和应用咱们能够应用new WeakMap()来创立一个新的WeakMap。在创立了WeakMap之后,咱们能够应用set办法来增加新的键值对, 应用get办法来获取某个键对应的值,应用delete办法来移除某个键及其对应的值,应用has办法来查看WeakMap中是否存在某个键。 let weakMap = new WeakMap();let obj1 = {};let obj2 = {};// 增加键值对weakMap.set(obj1, 'Hello');weakMap.set(obj2, 'World');// 获取值console.log(weakMap.get(obj1)); // 输入: 'Hello'console.log(weakMap.get(obj2)); // 输入: 'World'// 查看键是否存在console.log(weakMap.has(obj1)); // 输入: trueconsole.log(weakMap.has(obj2)); // 输入: true// 删除键值对weakMap.delete(obj1);console.log(weakMap.has(obj1)); // 输入: false2.2 WeakMap和内存治理WeakMap最重要的个性就是其键对对象的弱援用。这意味着,如果一个对象只被WeakMap援用,那么这个对象能够被垃圾回收。这样就能够避免因为长时间持有对象援用导致的内存透露。 例如,如果咱们在Map中保留了一些对象的援用,即便这些对象在其余中央都曾经不再应用,然而因为它们仍被Map援用,所以它们不能被垃圾回收,这就可能导致内存透露。然而,如果咱们应用WeakMap来保留这些对象的援用,那么当这些对象在其余中央都不再应用时,它们就会被垃圾回收,从而避免了内存透露。 2.3 WeakMap和对象公有数据WeakMap还经常被用来保留对象的公有数据。这是因为WeakMap的键不可遍历,所以咱们能够利用这个个性来存储一些只有特定代码可能拜访的数据。 例如,咱们能够创立一个WeakMap,而后应用这个WeakMap来保留每个对象的公有数据,像这样: let privateData = new WeakMap();function MyClass() { privateData.set(this, { secret: 'my secret data', });}MyClass.prototype.getSecret = function() { return privateData.get(this).secret;};let obj = new MyClass();console.log(obj.getSecret()); // 输入: 'my secret data'在这个例子中,咱们创立了一个MyClass的类,每一个MyClass的实例都有一个公有数据secret。咱们应用WeakMap来保留这个公有数据。这样,咱们就能够在MyClass的办法中拜访这个公有数据,然而其余的代码无法访问它。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程JavaScript引擎的垃圾回收机制

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JavaScript引擎的垃圾回收机制1. 引言在编程语言中,内存治理是一项要害的工作,尤其对于构建大规模和性能敏感的应用程序来说尤为重要。然而,对于JavaScript这种动静语言来说,开发者通常不须要(也无奈)间接治理内存,这项工作次要由JavaScript引擎来实现。 这种主动治理的机制让开发者能够更专一于业务逻辑的实现,而不必放心内存透露或溢出等问题。但同时,作为开发者,理解JavaScript引擎如何治理内存,如何进行垃圾回收(Garbage Collection,简称GC),也是很有价值的。这种了解能够帮忙咱们编写出更高效、更具性能的代码,防止可能导致内存问题的代码模式。 2. JavaScript内存生命周期在探讨垃圾回收之前,咱们首先须要理解一下JavaScript的内存生命周期,这个过程通常分为三个阶段: 分配内存:当申明变量、增加属性、或者调用函数等操作时,JavaScript引擎会分配内存来存储值。例如,当你写let a = 1时,JavaScript引擎会为变量a调配一块内存来存储值1。应用内存:在调配了内存之后,咱们能够通过读写操作来应用这块内存。例如,咱们能够读取变量a的值,或者扭转它的值。开释内存:当内存不再被须要时(例如,变量曾经来到了它的作用域),这块内存须要被开释,以便为新的内存调配做出空间。这个过程就是垃圾回收。3. 垃圾回收垃圾回收是主动实现的。垃圾收集器会周期性地(或在特定触发条件下)运行,找出不再应用的变量,而后开释其占用的内存。然而,如何确定哪些内存“不再须要”呢?这其实是一个简单的问题,因为某些内存可能依然被间接援用,或者可能在未来须要。因而,垃圾收集器必须应用一种算法来确定哪些内存能够平安地开释。接下来咱们将具体介绍两种常见的垃圾回收算法:标记-革除算法和援用计数算法。 3.1. 标记-革除算法这是JavaScript中最罕用的垃圾回收算法。它的工作原理大抵能够分为两个阶段:标记和革除。 在标记阶段,垃圾回收器从一组“根”(root)对象开始,遍历所有从这些根对象可达的对象。可达的对象包含间接援用的对象,以及通过其余可达对象间接援用的对象。所有可达的对象都被标记为“流动的”或“非垃圾的”。 而后,在革除阶段,垃圾回收器会遍历所有的堆内存,革除未被标记的对象。这些未被标记的对象就是咱们所说的“垃圾”,它们无奈从根对象拜访到,因而咱们能够平安地假如它们不会再被应用程序应用。 function test() { var x = 123; var y = { a: 1, b: 2 }; // 当函数执行完结时,x 和 y 就来到了环境}test();// 当初 x 和 y 都是非环境变量,它们占用的内存就能够被垃圾回收器回收3.2. 援用计数算法援用计数是另一种垃圾回收策略。这种策略的根本思维是跟踪每个对象被援用的次数。当申明一个变量并将一个援用类型值赋给该变量时,这个援用类型值的援用次数就是1。如果同一个援用值被赋给另一个变量,援用次数减少1。相同,如果对该值的援用被删除,援用次数缩小1。当这个援用次数变成0时,就示意没有任何中央再援用这个值了,因而该值能够被视为“垃圾”并被收集。 然而,援用计数算法有一个驰名的问题,那就是循环援用。如果两个对象互相援用,即便它们没有被其余任何对象援用,它们的援用次数也不会是0,因而它们不会被回收,这会导致内存透露。为了解决这个问题,古代JavaScript引擎通常会联合应用标记-革除和援用计数两种算法。 function cycleReference() { var obj1 = {}; var obj2 = {}; obj1.prop = obj2; obj2.prop = obj1;}cycleReference();// 在函数执行完结后,obj1 和 obj2 依然互相援用,但曾经来到了环境,无奈被援用计数器捕捉4. JavaScript引擎的垃圾回收优化策略古代JavaScript引擎不仅实现了上述的根底垃圾回收算法,而且引入了一些优化策略,以进步垃圾回收的效率并减小对性能的影响。 4.1. 分代收集大部分的JavaScript对象在创立后很快就会死亡,而那些能活下来的对象,通常能活很久。这给了JavaScript引擎一个优化垃圾收集的思路。它把内存堆分为两个 区域:新生代和老生代。新生代寄存的是生存工夫短的对象,老生代寄存的是生存工夫长的对象。 对新生代的垃圾回收采纳Scavenge算法,它将新生代的空间一分为二,一个为应用空间(From),一个为闲暇空间(To)。新对象总是被调配到From空间,当From空间快被应用完时,就会触发垃圾回收过程。回收过程中,存活的对象将会被复制到To空间,同时From和To空间的角色会对调,也就是原来的To空间变成新的From空间。这个过程称为新生代的降职策略。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程JavaScript引擎的工作原理代码解析与执行

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接JavaScript引擎的工作原理:代码解析与执行引言JavaScript是一种脚本语言,罕用于前端开发和后端服务器开发。在浏览器环境中,JavaScript的执行是由JavaScript引擎负责的。理解JavaScript引擎的工作原理,对于了解代码的执行过程、优化性能以及解决一些常见问题都十分有帮忙。本文将深入探讨JavaScript引擎是如何解析和执行代码的,以及相干的优化技术和调试工具。 1. JavaScript引擎简介JavaScript引擎是一种解释和执行JavaScript代码的软件或硬件组件。它负责将JavaScript代码转换为可执行的指令,并在计算机或设施上执行这些指令。每个浏览器都有本人的JavaScript引擎,用于在浏览器中执行JavaScript代码。常见的JavaScript引擎包含: V8引擎:由Google开发,用于Google Chrome浏览器和Node.js服务器环境。SpiderMonkey引擎:由Mozilla开发,用于Mozilla Firefox浏览器。JavaScriptCore引擎:由苹果公司开发,用于Safari浏览器。Chakra引擎:由微软开发,用于Microsoft Edge浏览器。每个引擎都有本人的实现形式和优化技术,但它们都遵循相似的基本原理和执行流程。 2. JavaScript代码的执行过程JavaScript代码的执行过程能够分为三个阶段:解析(Parsing)、编译(Compilation)和执行(Execution)。让咱们逐渐深刻理解每个阶段的工作原理。 2.1 解析(Parsing)解析是JavaScript引擎的第一个阶段,它将源代码转换为形象语法树(Abstract Syntax Tree,简称AST)。解析器(Parser)负责执行解析过程。解析器会依照JavaScript语法规定一一解析源代码的字符,并将其转换为形象语法树的节点。 解析器的次要工作包含: 词法剖析:将源代码宰割成一个个的标记(Tokens),如关键字、变量名、操作符等。语法分析:依据语法规定将标记转换为形象语法树的节点。以下是一个示例代码的解析过程: function greet(name) { console.log("Hello, " + name + "!");}greet("John");在解析过程中,解析器会辨认出关键字function、console等,变量名greet、name等,操作符+等,而后将其转换为形象语法树的节点。 2.2 编译(Compilation)编译是JavaScript引擎的第二个阶段,它将形象语法树转换为可执行的字节码或机器码。编译器(Compiler)负责执行编译过程。编译器会遍历形象语法树的节点,并生成对应的字节码或机器码。 编译器的次要工作包含: 优化:对形象语法树进行优化,如打消冗余代码、提取常量等。生成字节码或机器码:将优化后的形象语法树转换为可执行的字节码或机器码。以下是示例代码的编译过程: function greet(name) { console.log("Hello, " + name + "!");}greet("John");在编译过程中,编译器会对形象语法树进行优化,并将其转换为对应的字节码或机器码,以便后续的执行阶段应用。 2.3 执行(Execution)执行是JavaScript引擎的最初一个阶段,它执行编译生成的字节码或机器码,并产生相应的输入。执行引擎(Execution Engine)负责执行过程。执行引擎会逐行执行字节码或机器码,并将后果输入到控制台或更新浏览器中的页面。 执行引擎的次要工作包含: 解释执行:逐行执行字节码或机器码,并依据操作码执行相应的操作。解决数据:执行过程中解决变量、对象、函数等的创立、批改和销毁。解决控制流:依据条件执行、循环执行等管制流程。以下是示例代码的执行过程: function greet(name) { console.log("Hello, " + name + "!");}greet("John");在执行过程中,执行引擎会依照字节码或机器码的指令逐行执行代码,执行函数调用、变量赋值等操作,并输入后果到控制台。 3. JavaScript代码的优化JavaScript引擎在编译阶段和执行阶段都进行了许多优化,以进步代码的执行效率和性能。以下是一些常见的优化技术: 3.1 JIT(即时编译)JIT(Just-In-Time)编译是一种动静编译技术,在执行阶段将热点代码(被频繁执行的代码)编译为机器码,以进步代码的执行速度。JIT编译器会监控代码的执行状况,当某个代码块被屡次执行时,会将其编译为机器码,并在后续的执行中间接应用机器码执行,防止了解释执行的开销。 3.2 内联缓存(Inline Caching)内联缓存是一种缓存技术,用于优化属性拜访和办法调用的性能。当代码中存在频繁的属性拜访和办法调用时,引擎会将其后果缓存起来,以防止反复的查找和调用过程,进步拜访和调用的速度。 3.3 暗藏类(Hidden Classes)暗藏类是一种用于优化对象属性拜访的技术。JavaScript是一种动静类型语言,对象的属性和办法能够动静增加和删除。为了进步属性拜访的速度,引擎会依据对象的属性拜访程序和类型创立暗藏类,并通过暗藏类来快速访问属性。 3.4 内存治理优化JavaScript引擎还进行了许多内存治理优化,如垃圾回收机制、对象调配策略等,以进步内存的应用效率和垃圾回收的性能。 4. JavaScript调试工具在开发JavaScript应用程序时,调试是一项重要的工作。以下是一些罕用的JavaScript调试工具: 浏览器开发者工具:古代浏览器都提供了内置的开发者工具,包含调试器、性能分析器、堆栈追踪等性能,可用于调试JavaScript代码。Node.js调试工具:Node.js提供了内置的调试工具,如inspect命令和Chrome DevTools集成等,可用于调试Node.js应用程序。第三方调试器:还有许多第三方调试器可供选择,如VS Code的调试性能、Chrome DevTools Protocol、WebStorm等。通过应用这些调试工具,开发人员能够在开发过程中查看代码的执行过程、变量的值、堆栈的状态等,帮忙排查谬误并优化代码。 ...

July 11, 2023 · 1 min · jiezi

关于前端:现代JavaScript高级教程前端模块化

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接前端模块化引言前端开发中,代码的组织和治理始终是开发者面临的一大挑战。随着Web利用日益简单,对代码构造和组织的需要也更为显著。这种背景下,模块化编程应运而生,开发者们能够将简单的代码拆分为可治理和可重用的模块。在本文中,咱们将通过理论代码示例,来摸索前端模块化的倒退历程及各种模块化计划的实现原理。 前端模块化的倒退历程1.全局函数式编程在晚期的Web开发中,通常应用全局范畴内申明函数和变量的形式来组织代码。例如: var module1Data = 'module1 data';function module1Func(){ console.log(module1Data);}这种形式存在的问题次要有命名抵触、函数间依赖关系不显著、保护艰难等。 2.命名空间模式随着对代码组织形式的需要减少,开发者开始通过定义全局对象,将所有函数和变量封装在这个对象中,也就是命名空间模式。 var myApp = { module1Data: 'module1 data', module1Func: function(){ console.log(this.module1Data); }};这种形式解决了全局命名抵触的问题,然而模块间的依赖关系仍旧不显著,同时所有依赖都须要在命名空间对象中手动治理。 3.CommonJSCommonJS模块标准是Node.js采纳的标准,应用require函数加载模块,通过module.exports导出模块。 // a.jsmodule.exports = 'Hello world';// b.jsvar a = require('./a');console.log(a); // 输入 'Hello world'CommonJS应用同步加载形式,实用于服务器端,但因为网络申请的异步个性,不适宜在浏览器环境应用。 require函数require函数的次要工作是依据模块的文件门路读取模块文件,而后执行模块代码,最初返回模块的exports对象。 require函数的实现代码大抵如下: function require(modulePath){ // 读取模块代码 const code = fs.readFileSync(modulePath); // 包装模块代码 const wrapper = Function('exports', 'require', 'module', '__filename', '__dirname', `${code}\n return module.exports;`); const exports = {}; const module = { exports }; // 执行模块代码 wrapper(exports, require, module); // 返回模块的exports对象 return module.exports;}其中,wrapper函数的参数exports和module就是模块的exports和module对象,这样咱们就能够在模块中通过exports和module.exports来导出模块。 ...

July 11, 2023 · 1 min · jiezi

关于前端:每日一个组件如何从0到1实现一个折叠组件

点击在线浏览,体验更好链接古代JavaScript高级小册链接深入浅出Dart链接古代TypeScript高级小册链接jcode 咱们先从最根本的实现开始,而后逐渐增加更多的性能,如手风琴模式、自定义箭头、禁用状态、暗藏时是否渲染DOM构造 组件接口定义Collapse属性阐明类型默认值accordion是否开启手风琴模式booleanfalseactiveKey以后开展面板的 key手风琴模式:string \null 非手风琴模式:string[]-arrow自定义箭头,如果是 ReactNode,那么 antd-mobile 会主动为你减少旋转动画成果ReactNode \((active: boolean) => React.ReactNode)-defaultActiveKey默认开展面板的 key手风琴模式:string \null 非手风琴模式:string[]-onChange切换面板时触发手风琴模式:(activeKey: string \null) => void 非手风琴模式:(activeKey: string[]) => void-Collapse.Panel属性阐明类型默认值arrow自定义箭头ReactNode \((active: boolean) => React.ReactNode)-destroyOnClose不可见时卸载内容booleanfalsedisabled是否为禁用状态booleanfalseforceRender被暗藏时是否渲染 DOM 构造booleanfalsekey惟一标识符string-onClick标题栏的点击事件(event: React.MouseEvent<Element, MouseEvent>) => void-title标题栏左侧内容ReactNode-创立根底Collapse组件咱们创立一个根底的Collapse组件。这个组件须要有一个状态来追踪它是否被开展 import React, { useState } from 'react';const Collapse = ({ children }) => { const [isOpen, setIsOpen] = useState(false); return ( <div> <button onClick={() => setIsOpen(!isOpen)}> {isOpen ? 'Collapse' : 'Expand'} </button> {isOpen && <div>{children}</div>} </div> );};export default Collapse;拓展Collapse组件其它属性accordion:如果设置为true,咱们将启用手风琴模式。在这种模式下,只有一个面板能够被开展。当一个新的面板被开展时,之前开展的面板将被敞开。activeKey:这是以后开展面板的key。如果咱们处于手风琴模式,这将是一个字符串或null。如果咱们不在手风琴模式,这将是一个字符串数组。arrow:这是一个自定义的箭头。如果这是一个React节点,antd-mobile将主动为你增加旋转动画成果。如果这是一个函数,它将接管一个参数,示意面板是否被开展,并返回一个React节点。defaultActiveKey:这是默认开展面板的key。它的类型与activeKey雷同。onChange:这是一个函数,它在面板切换时被触发。它接管一个参数,示意以后开展面板的key。它的类型与activeKey雷同。import React, { useState, useEffect } from 'react';const Collapse = ({ children, forceRender, accordion, activeKey, arrow, defaultActiveKey, onChange }) => { const [isOpen, setIsOpen] = useState(false); const [currentActiveKey, setCurrentActiveKey] = useState(defaultActiveKey); useEffect(() => { setCurrentActiveKey(activeKey); }, [activeKey]); const handleClick = () => { setIsOpen(!isOpen); if (accordion) { setCurrentActiveKey(isOpen ? null : activeKey); } onChange && onChange(isOpen ? null : activeKey); }; const renderArrow = () => { if (typeof arrow === 'function') { return arrow(isOpen); } return arrow; }; return ( <div> <button onClick={handleClick}> {isOpen ? 'Collapse' : 'Expand'} {renderArrow()} </button> <div style={{ display: isOpen || forceRender ? 'block' : 'none' }}> {children} </div> </div> );};export default Collapse;实现Panel咱们创立一个名为Collapse.Panel的子组件来反对这些新的属性。这个子组件将作为Collapse组件的一部分,用于示意一个可折叠的面板。 ...

July 11, 2023 · 3 min · jiezi

关于前端:Vue组件禁止浏览器记住密码-自动填写密码

禁止浏览器记住明码、主动填写明码,反对明文暗文显示明码 应用办法:父组件中引入handPwd.vue组件 父组件应用: <el-form ref="form" :model="form" :rules="rules" > <el-form-item label="明码" key="password" prop="password"> <hand-password ref="handPassword" inputId="handPassword-password" @inputPwd="inputPassword" :needValidatePwd="false" ></hand-password> <!-- <el-input type="password" v-model="form.password" placeholder="明码" clearable ></el-input> --> </el-form-item> </el-form>import handPassword from '@/components/common/handPassword.vue'components: { handPassword },data(){ return { form:{ password:'' }, rules:{ password: [ { required: true, message: '明码不能为空', trigger: 'blur' }, { pattern: /^[^\s\u4e00-\u9fa5]+$/, message: '不容许输出空格、中文等特殊符号' } ] } }},methods:{ inputPassword(val) { this.form.password = val this.$refs.form.validateField('password') }}handPwd.vue<template> <div> <div :class="['el-input', 'el-input--suffix', prefixIconName != '' ? 'el-input--prefix' : '']"> <!-- 判断account是否为admin,是为了给开发留个后门,方便使用浏览器记住明码哈哈 --> <!-- 禁止复制、粘贴、剪切 --> <input :type="account == 'admin' ? 'password' : 'text'" autocomplete="off" :id="inputId" v-model="secretPwd" @input="inputPassword" @copy.prevent="() => {}" @paste.prevent="() => {}" @cut.prevent="() => {}" :placeholder="placeholder" :maxlength="maxLength" class="el-input__inner" :style="{ 'padding-right': clearPwd != '' ? '56px' : '30px' }" /> <span v-show="prefixIconName != ''" class="el-input__prefix" ><i :class="prefixIconName"></i ></span> <span class="el-input__suffix"> <span class="el-input__suffix-inner"> <i v-show="secretPwd !== ''" @click="inputPassword({ target: { value: '' } })" class="el-input__icon el-icon-circle-close" style="cursor: pointer;vertical-align: middle;" ></i> <svg-icon v-if="showPwd" @click="handleShowPwd" iconClass="明文" class="el-input__icon el-icon-view" style="cursor: pointer;height: 32px;font-size: 12px;color: #C0C4CC;vertical-align: middle;margin-right: 6px;" /> <svg-icon v-else @click="handleShowPwd" iconClass="暗文" class="el-input__icon el-icon-view" style="cursor: pointer;height: 32px;font-size: 12px;color: #C0C4CC;vertical-align: middle;margin-right: 6px;" /> </span ></span> </div> <div v-show="errorPwd" class="el-form-item__error"> 明码不能为空 </div> </div></template><script>/** * 手写明码,不反对右键菜单、复制、黏贴、剪切 */export default { name: 'handPassword', props: { // 输入框的id inputId: { type: String, default: 'passwordInput' }, // 后门:用户名称,不便开发应用浏览器记住明码 account: { type: String, default: '' }, // 须要应用子组件的校验,个别不应用 needValidatePwd: { type: Boolean, default: false }, // 输入框的暗正文 placeholder: { type: String, default: '请输出明码' }, // 输入框的最大输出长度 maxLength: { type: Number, default: 100 }, // 输入框头部图标类名 prefixIconName: { type: String, default: '' }, // 初始化明码值,个别用于编辑表单 originPwd: { type: String, default: '' } }, data() { return { secretPwd: '', //暗文明码 clearPwd: '', //明文明码 showPwd: false, //是否显示明文 errorPwd: false //是否明码谬误 } }, watch: { /** * 监听初始化明码,将明文和暗文明码别离初始化 */ originPwd: { handler(val) { this.clearPwd = val this.secretPwd = '●'.repeat(val.length) }, immediate: true } }, created() { /** * 禁止浏览器右键,因为右键菜单里有撤销、重写、黏贴、复制 */ window.oncontextmenu = function(e) { e.preventDefault() } }, methods: { /** * 重置办法,个别是给父组件调用 */ reset() { this.showPwd = false this.errorPwd = false }, /** * 查看明码 */ checkPassword() { if (this.needValidatePwd) { if (this.clearPwd === '') { this.errorPwd = true } else { this.errorPwd = false } } }, /** * 点击明码框后的小眼睛,切换明文或暗文 */ handleShowPwd() { if (this.showPwd) { this.secretPwd = '●'.repeat(this.secretPwd.length) } else { this.secretPwd = JSON.parse(JSON.stringify(this.clearPwd)) } this.showPwd = !this.showPwd }, /** * 输出明码 */ inputPassword(val) { const inputVal = val.target.value //原生input须要取target.value // 如果明文展现或者只输出了一个字符,比较简单,间接复制 if (this.showPwd || inputVal.indexOf('●') === -1) { if (this.showPwd) { this.secretPwd = inputVal } else { this.secretPwd = '●'.repeat(inputVal.length) } this.clearPwd = inputVal } else { const planeTextLen = this.clearPwd.length, //明文长度 cipherTextLen = inputVal.length, //暗文长度 selectionEnd = document.getElementById(this.inputId).selectionEnd // 获取光标地位 const realArr = this.clearPwd.split(''), // 实在明码数组 coverArr = inputVal.split('') // 文本框显示明码数组 let index = -1 // 新输出的字符地位 let lastChar = '' // 新输出的字符 // 找到新输出的字符及地位 coverArr.forEach((el, idx) => { if (/[^●]/g.test(el)) { index = idx lastChar += el } }) if (planeTextLen < cipherTextLen) { // 新增 realArr.splice(index, 0, lastChar) } else if (cipherTextLen <= planeTextLen && index !== -1) { //替换 realArr.splice(index, planeTextLen - (cipherTextLen - 1), lastChar) } else { // 删除 realArr.splice(selectionEnd, planeTextLen - cipherTextLen) } this.clearPwd = realArr.join('') this.secretPwd = '●'.repeat(this.secretPwd.length) // 还原光标地位 this.$nextTick(() => { document.getElementById(this.inputId).selectionEnd = selectionEnd }) } this.checkPassword() // 告知父组件明文明码 this.$emit('inputPwd', this.clearPwd) } }}</script>

July 11, 2023 · 3 min · jiezi

关于前端:基于WebGL智慧养老院三维可视化云平台

前言我国曾经迈入老龄化社会,老龄化社会中养老未然成为社会广泛关注的焦点,智慧养老成为将来趋势。 建设背景社会因素养老床位数量也增长至2020年的821万张.每千名老人领有养老床位增长至35张,绝对于先进国家的50-7O张仍有较大差距。目前养老床位供需还处于紧张状态。“十四五”民政事业倒退的布局第一次在五年布局中提出健全建设经营治理政策.倒退家庭养老床位,让更多的老年人养老不离家,在家里就能享受家庭养老床位,让家庭养老床位成为居家养老服务的一种重要模式,促成居家社区机构相协调。 政策因素随着中国人口老龄化问题日益严重,中国养老行业越发的受到重视,我国老龄化倒退减速、养老市场需求的迅猛增长,智慧衰弱养老需要日益突出。近些年,政府相继公布了政策搀扶养老行业,帮忙中国老年人可能幸福,满足的安度晚年。 零碎概述智慧养老院是利用物联网、云计算、大数据、智能硬件等新一代信息技术产品,以养老院理论治理和服务需要为出发点,建设一套成熟欠缺的智能化管理系统。零碎涵盖院内信息管理、老人平安监护、日常照护、以及经营剖析等功能模块。买通家庭、社区、养老院、第三方服务商、医疗机构、监管机构等各类参与者的一体化养老服务和监管体系。确保管理人员可能随时把握院里的状况,排除危险,晋升能效。 三维场景搭建 通过 Sovit3D 构建 Web 养老院数字孪生治理平台。以整个养老院为底本,利用数字孪生技术对养老院修建、设施、人员、环境等进行 1:1 三维实景展现,实在修建及散布,打造三维仿真三维场景。 综合看板模块 反对基于地理信息系统,对养老院的地位、房间散布、边界进行监测,整合养老院现有数据资源,对在院人员的身材、设施的运行、物资的储备、院区的环境等各畛域的状况进行综合监测剖析,辅助管理者全面院区运行态势。人员管理系统依靠智能穿戴设施实时把握在院人员地位、轨迹信息、身体状况等状况,实现视频联动追踪监督,防止人员进入非法受控区域或呈现忽然事件。 设施管理系统 对设施运行环境、运行状态等进行实时监测,反对设施运行异样实时告警,可点击查看设施的详细信息、培修记录、视频监控画面、告警详情等,辅助管理者直观把握设施运行状态。 安防管理系统 反对集成院区平安防备管理系统数据,提供平安态势监测一张图,反对对院区重点部位、人员、车辆、告警事件等因素进行实时监测,安防报警事件疾速显示、定位,实时调取事件周边监控视频,辅助管理者无效晋升院区平安管控效劳。 能耗管理系统 反对整合院区内能耗数据,对院区供暖、供排水、能源能耗、供电等各个子系统运行态势进行实时监控。 视频监控零碎 反对无缝交融视频监控性能,对院区及周边开展安防动静监测,并且和火灾报警、门禁系统、人员治理等零碎进行联动,进行精准的定位视频摄像头查看,反对多摄像头窗口的并行查看。 消防管理系统 通过API接口,接入消防系统,实时对烟感、探头、喷淋喷头等设施进行监管,当产生异样(火灾、爆炸、气体扩散等)异样情况时,可联动事变左近摄像头弹窗,显示实时监控画面。 …… (以上性能仅供参考,更多零碎性能以理论需要为准) 开发技术以养老院全貌照片为底本,通过数字孪生技术建设3D模型,高度还原院区实在三维场景,对院区的设施、人员、修建、环境、安防等因素进行实时监控。进行数据与三维场景的联动和数据交互展现,买通了数据壁垒,实现数据共享,通过3D界面、数据可视化大屏界面,灵便、高效、牢靠的实现对院区人员的实时监测,让生产管制与数字化深度交融,实现近程产线运行治理、可视化治理集中化,不便各部门高效协同。从而达到数据层面人、机、料、法、环的互联互通,一屏高效治理厂区生产制作。 建设价值智慧养老院可视化管理系统联合古代数字技术打造出优质服务模式,基于物联网、云计算、人工智能等先进技术,实现多元疾速响应、多角度预警。可为老年人提供更精准的能力评估、照护打算、紧急救助等服务,实时更新老人的衰弱数据,晋升照护过程的舒适性。真正实现“全程可观、全程可查”。 总结智慧养老院数字孪生可视化零碎是智能化养老服务的将来趋势,它能够为老年人提供更便捷、更智能的养老服务。

July 11, 2023 · 1 min · jiezi

关于前端:细节决定成败聊聊JS的类型下

讲完了根本类型,咱们来介绍一个景象:类型转换。 因为 JS 是弱类型语言,所以类型转换产生十分频繁,大部分咱们相熟的运算都会先进行类型转换。大部分类型转换合乎人类的直觉,然而如果咱们不去了解类型转换的严格定义,很容易造成一些代码中的判断失误。其中最为臭名远扬的是 JavaScript 中的“ == ”运算,因为试图实现跨类型的比拟,它的规定简单到简直没人能够记住。这里咱们当然也不打算解说 == 的规定,它属于设计失误,并非语言中有价值的局部,很多实际中举荐禁止应用“ ==”,而要求程序员进行显式地类型转换后,用 === 比拟。其它运算,如加减乘除大于小于,也都会波及类型转换。 幸好的是,实际上大部分类型转换规定是非常简单的,如下表所示: 在这个外面,较为简单的局部是 Number 和 String 之间的转换,以及对象跟根本类型之间的转换。咱们别离来看一看这几种转换的规定。 StringToNumber字符串到数字的类型转换,存在一个语法结构,类型转换反对十进制、二进制、八进制和十六进制,比方: 30;0b111;0o13;0xFF。此外,JavaScript 反对的字符串语法还包含正负号迷信计数法,能够应用大写或者小写的 e 来示意: 1e3;-1e-2。须要留神的是,parseInt 和 parseFloat 并不应用这个转换,所以反对的语法跟这里不尽相同。 在不传入第二个参数的状况下,parseInt 只反对 16 进制前缀“0x”,而且会疏忽非数字字符,也不反对迷信计数法。 在一些古老的浏览器环境中,parseInt 还反对 0 结尾的数字作为 8 进制前缀,这是很多谬误的起源。所以在任何环境下,都倡议传入 parseInt 的第二个参数,而 parseFloat 则间接把原字符串作为十进制来解析,它不会引入任何的其余进制。 少数状况下,Number 是比 parseInt 和 parseFloat 更好的抉择。 NumberToString在较小的范畴内,数字到字符串的转换是完全符合你直觉的十进制示意。当 Number 绝对值较大或者较小时,字符串示意则是应用迷信计数法示意的。这个算法细节繁多,咱们从理性的角度意识,它其实就是保障了产生的字符串不会过长。 具体的算法,你能够去参考 JavaScript 的语言规范。因为这个局部内容,我感觉在日常开发中很少用到,所以这里我就不去具体地解说了。装箱转换每一种根本类型 Number、String、Boolean、Symbol 在对象中都有对应的类,所谓装箱转换,正是把根本类型转换为对应的对象,它是类型转换中一种相当重要的品种。 前文提到,全局的 Symbol 函数无奈应用 new 来调用,但咱们仍能够利用装箱机制来失去一个 Symbol 对象,咱们能够利用一个函数的 call 办法来强制产生装箱。 咱们定义一个函数,函数外面只有 return this,而后咱们调用函数的 call 办法到一个 Symbol 类型的值上,这样就会产生一个 symbolObject。 ...

July 11, 2023 · 2 min · jiezi

关于前端:分析-jsjiamiv6-代码混淆和加密技术特点优点和缺点

当波及到 JavaScript 代码混同和加密技术时,开发人员经常寻求办法来爱护他们的代码免受逆向工程和未受权拜访的威逼。这种技术能够减少代码的复杂性,使其难以了解和批改,同时也能够暗藏要害信息和爱护数据的安全性。本文将探讨 JavaScript 代码混同和加密的一些常见技术、特点以及优缺点。咱们将介绍哈希函数、对称加密、非对称加密、混同和压缩等技术,并剖析它们的长处和毛病。同时,咱们还将提供相干的案例代码,以便更好地了解这些技术的利用。无论你是想增强代码安全性,还是对 JavaScript 加密技术感兴趣,本文都将为你提供一些有用的见解。 特点: 变量混同和字符串反转:变量 _0xodU 的值通过字符串反转失去,以减少代码的可读性和了解难度。字符串数组存储数据:应用数组 _0xodU_ 存储了多个字符串元素,这些元素可能用于后续的解密操作。位运算和字符串操作:函数 _0x3921c1 蕴含了位运算和字符串操作,用于对数组元素进行解决和计算。长处: 混同代码:通过变量混同和字符串反转,使代码更难以了解和逆向工程。暗藏要害信息:实在的变量名和字符串被暗藏在混同的变量和数组中,减少了代码的保密性。毛病: 升高可读性:混同和加密操作使代码变得艰涩难懂,减少了保护和调试的艰难。容易被破解:这种简略的混同和加密技术绝对容易被有教训的攻击者逆向工程和解密。不提供真正的安全性:这段代码仅仅是对代码进行了简略的混同和加密,无奈提供弱小的安全性保障。以下是对给出代码的简化案例: var _0xodU = 'jsjiami.com.v6';function _0xodU_() { return [_0xodU];}var encryptedData = _0xodU_();console.log(encryptedData);在这个简化的例子中,变量 _0xodU 存储了一个字符串值。函数 _0xodU_ 返回一个蕴含一个元素的数组,数组的元素就是 _0xodU 的值。最初,将加密后的数据存储在 encryptedData 变量中,并将其输入到控制台。 请留神,这只是一个简化的例子,实在的代码可能会蕴含更多简单的混同和加密操作。这段代码的安全性和适用性取决于具体的加密算法和密钥治理形式,以及是否提供了解密的相干代码。在理论利用中,倡议应用更弱小和成熟的加密算法和库来确保数据的安全性。 如果您对文章内容有不同认识,或者疑难,欢送到评论区留言,或者私信我、到咱们的官网找客服号都能够。如遇本人js加密源码加密后没备份,能够找咱们解决解出复原源码,任何加密都能够

July 11, 2023 · 1 min · jiezi

关于前端:支持源码的低代码核心工具逻辑引擎

在古代企业治理中,决策扮演着至关重要的角色。然而,随着业务规模的扩充和数据量的减少,人工决策变得越来越艰难和耗时,而且容易受到主观因素的影响。逻辑引擎的呈现为企业提供了一种高效、精确的决策推理工具,可能以逻辑形式解决和剖析大规模数据,并在简单条件下制订最佳决策计划。置信关注低代码的小伙伴们肯定也十分关注逻辑引擎的能力,本文将介绍逻辑引擎的原理及劣势等等。 逻辑引擎作为低代码平台的外围组件之一,它负责解决和执行应用程序中的逻辑规定和业务逻辑。它能够了解和执行开发者定义的条件、流程和动作,从而控制应用程序的行为和响应。 通过逻辑引擎,开发人员应用可视化工具或简略的表达式语言来定义应用程序的逻辑,从而代替大量代码的编写。通常提供了丰盛的内置函数和操作符,使开发人员可能疾速实现简单的逻辑和业务规定,开发人员能够利用这些性能来疾速构建应用程序。同时,逻辑引擎提供了一种可视化的形式来定义和管理应用程序的逻辑规定,使得逻辑的批改和保护变得更加容易。开发人员能够通过简略的拖拽和配置操作来批改逻辑规定,而不须要批改大量的代码,这进步了应用程序的灵活性和可维护性。 最初,在实时反馈和调试性能层面,咱们能够及时的检测和修复逻辑谬误。帮忙咱们更早地发现和解决问题,进步开发的效率和品质。 咱们以以后十分沉闷的反对私有化部署、反对源码级交付的JVS逻辑引擎来开展看看:1、可视化配置界面。引擎提供了简略易用且功能丰富的可视化配置界面,不便用户对业务逻辑配置和管理应用程序。 2、数据模型和存储逻辑引擎须要反对定义和治理数据模型,以便可能解决和存储输出数据和输入后果,能够便捷的疾速的操作数据处理的相干组件。 3、条件和规定编辑器逻辑引擎应该提供易于应用的动静条件和规定编辑器,使得用户能够不便地定义和批改规定和条件,以满足不同的业务需要。 4、反对多种业务模式流转须要反对定义业务流转的过程、分支、循环等多种形式,以反对各种简单业务场景。 分支条件在应用时,能够通过入参、动静变量等多种数据,联结零碎外部提供的多种函数实现各种动静判断条件。 反对循环的解决模式: 5、异样解决和谬误日志记录逻辑引擎须要提供异样解决和谬误日志记录机制,以便及时发现和解决问题,保证系统的稳定性和可靠性。 6、组件扩大能力与内部零碎对接能力逻辑引擎提供了可扩大的组件能力,并且能够对外提供API接口,也能够将API的接口疾速封装。能够给其余利用或者程序提供API 能够调用其余程序的API服务,只须要做简略的扩大集成 7、反对在线调试与历史数据回放,在应用调试的时,可便捷的调试逻辑的正确性。 逻辑引擎在低代码开发中扮演着十分重要的角色,它能够简化开发过程、进步开发效率、反对可维护性和灵活性,并提供实时反馈和调试能力。JVS逻辑引擎不仅能够独立私有化部署,还能够采纳源代码集成到现有的业务框架中,它能够帮忙咱们更好地了解和解决各种问题,从而进步咱们的决策效率和准确性。快来私有化部署体验吧:https://gitee.com/software-minister/jvs-docker-compose

July 11, 2023 · 1 min · jiezi

关于前端:做一个游戏小项目有多简单

意识一个敌人,学了很多年的 python, 还停留在 helloworld 阶段,每次拿起又放下,是不是很相熟?每天都在想,我要学编程,我要学编程,然而又不晓得从何学起,学了一点又不晓得怎么用,这样的周而复始,最初就放弃了。其实任何常识的学习肯定是源于心田的实在的喜爱,带给你正向的激情和打动。才会让你始终坚持下去。不论 debugger 多少次,bug 多少次,都不会放弃。<!-- more --> 很多人对编程,代码有着天然的畏惧,其实编程是一件很乏味的事件,只有你找到了适宜本人的形式,你就会爱上它。 作为前端开发者,你无妨尝试着用前端技术开发一个小型的游戏我的项目来晋升本人的技能和乐趣。 Pacman比方这款游戏,基于HTML5的吃豆人游戏(本游戏由 passer-by.com 制作),你能够在这里玩到:https://passer-by.com/pacman/ 你能够看到这款游戏,仅仅用了html5,js来实现的。内置了12个关卡,游戏还是非常晦涩的。有趣味能够一边玩一玩,看看源码。 源码在此:https://github.com/mumuy/pacman Snake Game当年这款游戏多火啊,很多手机都内置了这款贪吃蛇游戏,嗯那还是诺基亚手机的时代。同样的html5+js 就能够实现这款游戏。 玩一玩:https://rabiroshan.github.io/snake_game/ 源码在此:https://github.com/RabiRoshan/snake_game 俄罗斯方块《俄罗斯方块》(Tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫于1984年6月创造的休闲游戏。 游戏框架应用的是 React + Redux,其中再退出了 Immutable,以及一些 ES6 的语法。 玩一玩:https://chvin.github.io/react-tetris/源码:https://github.com/chvin/react-tetris 2048 2048是前几年风行的一款益智类单机游戏, 游戏的规定非常简略,合并打消,看你能活多久。 玩一玩:https://play2048.co/源码:https://github.com/gabrielecirulli/2048 明天介绍都的二维小游戏,如果你感兴趣,能够本人尝试着开发一个,这样你会发现,原来编程是这么乏味的一件事件。喜爱请点个赞。前期会给大家介绍3d游戏开发,敬请期待。 公号同步更新,欢送关注

July 11, 2023 · 1 min · jiezi

关于前端:基于分步表单的实践探索

咱们是袋鼠云数栈 UED 团队,致力于打造优良的一站式数据中台产品。咱们始终保持工匠精力,摸索前端路线,为社区积攒并流传教训价值。。 本文作者:修能 以下内容充斥个人观点。◡ ヽ(`´)ノ ┻━┻ 前言基于散布表单的需要,在中后盾治理中是一个十分常见的需要,通常具备如下布局: 其中,自定义需要度从高到低为,注释 > 按钮区 > 步骤条。 尽管布局相似,然而实现的形式却是天差地别,这里就探索一下到底怎么样实现能够兼具代码的可维护性和可读性呢? 指出问题Container咱们这里,以「指标-数据模型」的代码为例。 首先先来看看数据模型这里的代码是如何实现的? export default () => { ... return ( <> <header> <Steps current={current}> {['tab1', 'tab2', 'tab3', 'tab4', 'tab5'].map( (title, index) => ( <Step key={index} title={title} /> ) )} </Steps> </header> <Spin> {stepRender(current, { childRef, modelDetail, globalStep: globalStep.current, mode, isModelTypeDisabled, setModelDetail, setDisabled, onModelNameChange: handleModelNameChange, })} <Modal>...</Modal> </Spin> <footer> {current === EnumModifyStep.tab1 ? ( <Button onClick={() => router.push('/url')} > 勾销 </Button> ) : null} ... </footer> </> )}这是数据模型编辑页面 Steps所在的容器组件的 DOM 局部的代码。 ...

July 11, 2023 · 3 min · jiezi

关于前端:为什么React一年不发新版了

大家好,我卡颂。 遐想前几年,不论是React还是Vue,都在疾速迭代版本,以至于很多同学埋怨学不动了。 而当初,React曾经一年没更新稳固release了。 甚至有人认为,这就是前端已死最间接的证据: 那么,React最近一年为什么不发版了呢?是因为前端框架畛域曾经没有新活儿可整了么?React v19是不是遥遥无期了? 欢送围观朋友圈、退出人类高质量前端交换群,带飞 最近一年React沉闷吗?不想看长文章的同学,这里一句话总结本文观点: React之所以一年没发版,并不是因为无活可整,而是在实现框架从UI库到元框架的转型首先,咱们来看看,最近这一年React的更新活跃度是否升高? 从代码push量来看,最近一年甚至比release产出较多的前几年更沉闷: 既然更沉闷,那React这段时间到底在做什么呢?从代码增删行数能够一窥端倪,其中: 绿色柱状代表代码减少行数红色柱状代表代码缩小行数红色折线代表代码行数总体趋势 从代码量变动来看,React历史上大体分为四个期间: 13年开源,到17年之前的性能迭代期继续到18年的重构期(重构React Fiber架构)18~22年基于Fiber架构的新性能迭代期22年至今的重构期性能迭代期与重构期的区别在于: 前者次要是在稳固的架构上迭代新个性后者个别重构底层架构的同时,重构老个性激烈的代码量稳定通常产生在重构期。比方,在最近的重构期内,PR #25774删除了3w行代码。 这个PR次要扭转React对于同一个子包,同时领有.new、.old两个文件的开发模式最近一年React都在干啥?明确了React最近一年处于重构期。那么,到底是重构什么呢? 答案是 —— 将RSC(React Server Component,服务端组件)接入以后React体系内。 有同学会问:RSC只是个相似SSR的个性,为什么要实现他还波及重构? 这是因为RSC不仅是一个个性,更是React将来次要的倒退方向,其意义不亚于Hooks。所以,围绕RSC的迭代波及大量代码的重构。比方: SSR相干代码须要批改SSR代码批改导致Suspense组件代码批改Suspense的批改又牵扯到useEffect回调触发机会的变动能够说是牵一发而动全身了。 RSC为什么重要为什么RSC对React这么重要?要答复这个问题,得从开源我的项目的倒退聊起。 开源我的项目要想获得成功,肯定须要满足指标用户(开发者)的需要。 晚期,React作为前端框架,满足了UI开发的需要。在此期间,React团队的迭代方向次要是: 摸索更清晰的开发范式(公布了Error Boundray、Suspense、Hooks)修补代码(公布新的Context实现)优化开发体验(公布CRA)底层优化(重构Fiber架构)能够发现,这些迭代内容中大部分(除了底层优化)都是间接面向一般开发者的,所以React文档(文档也是面向开发者的)中都有体现,开发者通过文档能直观的感触到React一直迭代。 随着前端畛域的倒退,逐步涌现出各种业务开发的最佳实际,比方: 状态治理的最佳实际路由的最佳实际SSR的最佳实际一些框架开始整合这些最佳实际(比方Next.js、Remix,或者国内的Umijs...) 到了这一时期,开发者更多是通过应用这些框架间接应用React。 感触到这一变动后,React团队的倒退方向逐步变动 —— 从面向开发者的前端框架变为面向下层框架的元框架。 倒退方向变动最显著的体现是 —— 文档中新出的个性一般开发者很少会用到,比方: useTransitionuseIduseMutableSource这些个性都是作为元框架,给下层框架(或库)应用的。 上述个性尽管一般开发者很少用到,但至多文档中提及了。但随着React一直向元框架方向倒退,即便出了新个性,文档中曾经不再提及了。比方: useOptimisticuseFormStatus上述两个Hook想必大部分同学都没听过。他们是React源码中切实存在的Hook。但因为是元框架理念下的产物,所以React文档并未提及。相同,Next.js文档中能够看到应用介绍。 总结React之所以曾经一年没有公布稳固release,是因为倒退方向曾经从面向开发者转型为面向下层框架。 在此期间的更新都是面向下层框架,所以开发者很难感知到React的变动。 但这并不能阐明React进行迭代了,也不能据此认为前端倒退的停滞。 如果肯定要定量察看React最近一年的倒退,间隔React v19里程碑,曾经大体过半了:

July 11, 2023 · 1 min · jiezi