关于javascript:带你揭开神秘的javascript-AST面纱之AST-基础与功能

作者:京东科技 周亮堂 AST 根底与性能在前端外面有一个很重要的概念,也是最原子化的内容,就是 AST ,简直所有的框架,都是基于 AST 进行革新运行,比方:React / Vue /Taro 等等。 多端的运行应用,都离不开 AST 这个概念。 在大家了解相干原理和背景后,咱们能够通过手写简略的编译器,简略实现一个 Javascript 的代码编译器,编译后在浏览器端失常运行。 创立数字小明,等于六加一。创立数字小亮,等于七减二。输入,小明乘小亮。通过实现一个自定义的编译器,咱们发现咱们本人也能写出很多新的框架。最终目标都是通过编译转换,翻译为浏览器辨认的 Javascript + CSS + HTML。 没错!翻译翻译~ 当然咱们也能够以这个为根底,去实现跨端的框架,间接翻译为机器码,跑到各种硬件上。当然一个人必定比拟艰难,你会遇到各种各样的问题须要解决,不过没关系,只有你有好的想法,拉上一群人,你就能实现。 大家记得点赞,评论,珍藏,一键三连啊~ 分析器说到这个代码语义化操作前,咱们先说说分析器,其实就是编译原理。当你写了一段代码,要想让机器晓得,你写了啥。 那机器必定是要开始扫描,扫描每一个关键词,每一个符号,咱们将进行词法剖析的程序或者函数叫作词法分析器(Lexical analyzer),通过它的扫描能够将字符序列转换为单词(Token)序列的过程。 扫描到了关键词,咱们怎么能力把它依照规定,转换为机器意识的特定规定呢?比方你扫描到: const a = 1机器怎么晓得要创立一个 变量a并且等于1呢? 所以,这时候就引入一个概念:语法分析器(Syntactic analysis,Parser)。通过语法分析器,一直的调用词法分析器,进行语法查看、并构建由输出的单词组成的数据结构(个别是语法分析树、形象语法树等层次化的数据结构)。 在JS的世界里,这个扫描后失去的数据结构形象语法树 【AST】。可能很多人听过这个概念,然而具体没有深刻理解。机缘巧合,刚好我须要用到这个玩意,明天就简略聊聊。 形象语法树 ASTAST是Abstract Syntax Tree的缩写,也就是:形象语法树。在代码的世界里,它叫这个。在语言的世界外面,他叫语法分析树。 语言世界,举个栗子: 我写文章。语法分析树: 主语:我,人称代词。 谓语:写,动词。 宾语:文章,名词。 长一点的可能会有:主谓宾定状补。是不是发现好相熟,想当年大家学语文和英语,那是肯定要进行语法分析,不便你了解句子要表白的含意。 PS:对我来说,语法老难了!!!哈哈哈,大家是不是找到感觉了~ 接下来咱们讲讲代码外面的形象语法树。 const me = "我"function write() { console.log("文章")}那咱们用来进行语法分析,可能失去什么内容了?这时候咱们能够借助已有的工具,将他们进行剖析,进行一个高级入门。 其实咱们也能够齐全本人进行剖析,不过这样就不容易入门,定义的语法规定很多,如果只是看,很容易就被劝退了。而通过辅助工具,咱们能够很快承受相干的概念。 罕用的工具有很多,比方:Recast 、Babel、Acorn 等等 也能够应用在线 AST 解析:AST Explorer,左上角菜单能够切换到各种解析工具,并且反对各类编程语言的解析,弱小好用,能够用来学习,帮忙你了解 AST。 ...

April 10, 2023 · 2 min · jiezi

关于javascript:vuepluginhiprint使用进阶篇

置信你看了 【vue-plugin-hiprint】应用-入门篇 曾经晓得了如何引入及构建设计器了。本进阶篇教大家如何进一步的构建设计器,包含第二种构建可拖拽元素(provider)、vue3组合式函数、罕用API及如何查看可用API等。源码链接: https://github.com/CcSimple/vue-plugin-hiprint-start 1.编写 provider 并 构建这里将创立两个provider文件,用于演示如何在两个不同容器中去构建可拖拽元素。 1.1 创立 provider首先创立provider,间接上代码: // provider1.jsimport { hiprint } from "vue-plugin-hiprint";export const provider1 = function (options) { console.log(options); var addElementTypes = function (context) { context.removePrintElementTypes("providerModule1"); context.addPrintElementTypes("providerModule1", [ new hiprint.PrintElementTypeGroup("惯例", [ // 留神这里,应用了传入的 options.config options.config, { tid: "providerModule1.header", title: "单据表头", data: "单据表头", type: "text", options: { testData: "单据表头", height: 17, fontSize: 16.5, fontWeight: "700", textAlign: "center", hideTitle: true, }, }, // 此处省略.... ]) }; return { addElementTypes: addElementTypes, };};代码过长,各位看源码吧~ ...

April 7, 2023 · 5 min · jiezi

关于javascript:华为云开源项目OpenTiny的TinyNG组件库应该如何使用

最近华为云出品了一个开源我的项目叫OpenTiny,其中蕴含两个前端组件库我的项目一个是TinyVue另一个是TinyNG组件库。TinyNG组件库是一个基于Angular框架的开源UI组件库,其中蕴含了丰盛的UI组件,如按钮、输入框、表格、对话框等,能够不便开发人员疾速构建Web利用界面。TinyNG组件库的设计格调简洁、易于应用,同时反对响应式设计,能够适配不同的设施尺寸。同时,它也反对自定义主题和国际化,满足不同我的项目的需要。我最近也是尝试应用了这个TinyNG组件库,上面也给大家说一下这个TinyNG组件库到底是怎么应用的。   应用TinyNG组件库的步骤如下: 下载并导入TinyNG组件库的CSS和JS文件到我的项目中。在HTML文件中引入相干的CSS和JS文件。在页面中应用组件库提供的组件和工具。例如,应用按钮组件: 当然,除了按钮组件,还有很多其余的组件和工具,能够依据理论需要应用。在应用时,能够参考TinyNG组件库的文档,文档中提供了具体的组件和工具的应用阐明和示例代码。 在应用了下OpenTiny我的项目中TinyNG组件库后,其实整体感觉还是十分不错的,组件也是十分丰盛,并且TinyNG这个我的项目的劣势还是比拟明确的: 1、 TinyNG组件库组件丰盛,已开源 70+ 根底组件,逐渐开源 100+ 组件。应用 CSS Var 自定义主题,免编译、反对JS热更新变量。所见即所得自定义主题配置,一键公布到 npmjs 2、 微组件个性:每个组件独立版本号治理,能够独自装置或降级一个组件。如果应用泛滥组件,仅降级一个组件,免去全量测试。 3、 采纳面向对象架构设计,代码反复率远低于谷歌等竞品一个数量级。与 Angular 放弃同步降级。 对于OpenTiny开源我的项目的TinyNG组件库,我也增加了小助手微信:opentiny-official,想要理解更多的话也能够增加下,有须要也能够一起交换前端技术,一起玩开源。 OpenTiny 官网:https://opentiny.design/ OpenTiny 代码仓库:https://github.com/opentiny/ TinyVue 组件库:https://github.com/opentiny/tiny-vue (欢送 Star) TinyNG组件库:https://github.com/opentiny/ng (欢送 Star)

April 6, 2023 · 1 min · jiezi

关于javascript:基于node的cli工具开发

前言如果文章对你有帮忙的话,记得一键三连哟。有问题和纳闷的话也能够在评论区留言。我会第一工夫回复大家,如果感觉我的文章哪里有知识点谬误的话,也恳请可能告知,把错的货色了解成对的,无论在什么行业,都是致命的。 背景公司外部有保护admin和h5两套根底模版,然而每次新我的项目须要关上gitlab找git地址 clone,略微有点麻烦,所以集成一个工具,方便使用。 性能个性下载公司外部前端模版 成果预览 地址taosiqi/web-cli 插件开发举荐应用nrm治理npm源 创立用户npm adduser --registry http://127.0.0.1:4873/公布npm publish --registry http://127.0.0.1:4873/应用装置npm install web-cli -g --registry http://127.0.0.1:4873/应用web-cli create实现原理应用到的工具chalk: 批改终端色彩commander: 增加版本命令提醒inquirer: 命令行交互minimis: 命令行解析ora: 终端旋转器shelljs: 执行shell命令rimraf:删除文件夹package.json{ "name": "web-cli", "version": "0.0.5", "description": "前端脚手架", "main": "dist/src/service.js", "author": { "name": "taosiqi", "email":"thinlf97@gmail.com" }, "keywords": [ "rs", "cli" ], "bin": { "web-cli": "dist/src/bin/web-cli.js" //会注册成全局可执行文件 }, "scripts": { "dev": "tsc -w -p .", "build": "rimraf dist && tsc -p .", "test": "echo "Error: no test specified" && exit 1", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" },}web-cli.ts#!/usr/bin/env node// 第一行不可少,其作用是它通知零碎这个脚本须要用node解释器来执行。// 这个文件次要是用来解决承受参数的入口文件,const Service = require('../service') //引入咱们的入口文件const service = new Service() //实例化Serviceconst rawArgv = process.argv.slice(2)const args = require('minimist')(rawArgv) //解析命令行参数const command = args._[0]// 执行初始化service.run(command, args, rawArgv)service.tsimport program from 'commander'import packageInfo from '../package.json'import { create } from "./commands/create";module.exports = class Service { constructor() { setupDefaultCommands() //设置默认命令 } run(_id, _args = {}, rawArgv = []) { program.parse(rawArgv, { from: 'user' }) //执行相应的命令 }}// 设置默认命令const setupDefaultCommands = () => { program.version(packageInfo.version, '-v, --version', '输入以后版本号') program.helpOption('-h, --help', '获取帮忙') program.command('create').description('新建我的项目').alias('c').action(async () => { await create() }) program.addHelpCommand(false)}create.tsimport shelljs from 'shelljs'import inquirer from 'inquirer'import * as fs from 'fs'import rimraf from 'rimraf'import log from '../utils/log'const templateType = { type: 'list', message: '请抉择模版类型', name: 'type', choices: [ { name: 'h5', value: 'vue3-h5-starter' }, { name: 'admin', value: 'vue3-admin-starter' } ]}const templateName = [ { type: 'input', message: '请输出项目名称:', name: 'name', validate: (val) => { return val !== '' } }]export const create = async () => { // 抉择模版类型 let { type } = await inquirer.prompt([templateType]) // 项目名称 let { name } = await inquirer.prompt(templateName) // 拼接git地址,自行替换「」字段 const url = `git clone http://gitlab-ci-token:「token」@「ip/域名」/pinxin/${type}.git --depth 1` // 执行clone await shelljs.exec(url) // 重命名 await fs.renameSync(`./${type}`, `./${name}`) // 删除无关文件 await rimraf(`./${name}/.git`) await rimraf(`./${name}/.idea`) await rimraf(`./${name}/.vscode`) log.succeed('创立胜利') log.info(`cd ${name}`) log.info(`pnpm install`)}援用首发于掘金,欢送关注 ...

April 6, 2023 · 2 min · jiezi

关于javascript:JS实用技巧断点调试详解

调试能力是一个程序员的生存基本,可是很多初学者却漠视调试。明天咱们就来讨究一下JS的调试技巧。本文章将会具体列举JS相干的各种实用调试技巧。 如果您是JS的初学者,那么这篇文章将对您有很大的帮忙。为什么要调试?程序就是函数堆砌起来的,程序的运行就是函数的执行过程。而通过JS调试,咱们能够更为直观的追踪到在程序运行中,函数的执行程序,以及各个参数的变动。这样咱们就能够疾速的定位到问题所在。 什么是JS调试?在程序运行中,咱们总会遇到各种bug,而通过代码的追踪代码的运行程序从而定位到问题的过程就叫做JS调试。首先咱们须要晓得如何进入调试的界面,此处咱们以谷歌为例,通过F12和右键查看,找到Sources就能够进入调试界面。具体界面显示如下:红框所标示的就是咱们调试罕用的按键。上面咱们会在理论利用场景中具体讲述每一个按键的作用。2. 单步调试首先是一般调试,又叫单步调试。F12找到Sources后,在左侧文件夹中找到你想运行的文件,而后点击pause script execution按钮再刷新页面(F5),就能够进入单步调试点击Step over next function call就是程序逐渐调试,每点击一次,就会依照代码执行程序,向下执行一句代码。3. 函数调试如果亲手尝试过单步调试的小伙伴就会发现,单步调试其实并不能满足咱们找bug的需要,因为单步调试是不能进入函数体内,咱们也就不能跟踪函数体内变量的变动。所以咱们接下来就来学习下第三个按钮,step into next function call按钮应用Step into按钮,咱们就能够进入函数体内,在单步调试过程中,当通过函数调用时,点击Step into就能够进入该函数体内。进入函数体内之后,持续点击Step over按钮,就能够进行函数体内的单步调试。如图所示,函数体内的变量变动就高深莫测了。然而在咱们曾经追踪到想要的变量变动时,函数体内的内容又很多,单步调试到函数完结就很浪费时间。这里就能够应用咱们明天学习的第四个按钮,step out of current function call跳出以后函数体,跳出到之前进入函数体的代码地位。4. 断点调试在理论我的项目代码量是很大的,应用单步调试就过于的浪费时间。而且有时咱们是想要定位某一处的代码是否有错,所以就没有必要调试所有的代码。所以咱们就能够应用断点调试,那么什么是断点调试呢? 首先,在想要定位问题的代码处,打断点,也就是代码进行执行的地位。如图所示点击红框处打该行的断点。(因为谷歌版本的不同,断点图标略有不同)而后刷新页面(F5),就能够进入断点调试页面。点击Resume script execution按钮就能够调到下一个断点。(留神:当调到断点处时,此行代码为蓝色背景,示意此行代码行将执行但并未执行)5. 事件调试首先咱们要来明确一个概念,就是同步与异步,当代码执行时,自上而下运行的为同步代码,而异步代码其中一类就是须要事件来触发。所以在代码调试中,事件体内的函数,须要在打断点后,通过该事件的行为,能力进入函数体。如以下代码:打断点后在刷新,其实没有成果必须动过事件能力触发调试

April 6, 2023 · 1 min · jiezi

关于javascript:JS-根据汇总结果过滤

有如下这样一组学生问题的数据,须要把 7 年级的优秀学生(所有科目问题大于等于 80 分)找进去,按数学问题从大到小排序,如果数学问题一样则按姓名排序。 const table = [ { "name": "张三", "grade": 8, "subject": "语文", "score": 90 }, { "name": "张三", "grade": 8, "subject": "数学", "score": 76 }, { "name": "张三", "grade": 8, "subject": "英语", "score": 86 }, { "name": "李四", "grade": 7, "subject": "语文", "score": 78 }, { "name": "李四", "grade": 7, "subject": "数学", "score": 98 }, { "name": "李四", "grade": 7, "subject": "英语", "score": 70 }, { "name": "王五", "grade": 8, "subject": "语文", "score": 90 }, { "name": "王五", "grade": 8, "subject": "数学", "score": 89 }, { "name": "王五", "grade": 8, "subject": "英语", "score": 87 }, ...];这里提出了两个要求,一是过滤数据,二是排序。看起来简略,仿佛又不简略,为什么呢? ...

April 6, 2023 · 3 min · jiezi

关于javascript:浅谈IntlNumberFormat

很快乐您对 Intl.NumberFormat 感兴趣。Intl.NumberFormat 是一个内置于 JavaScript 的国际化 API,它提供了一种简略的办法来格式化数字,以便在不同语言环境下进行显示。在本篇博客中,咱们将具体介绍 Intl.NumberFormat 的应用办法和应用场景,并配以示例代码作为应用阐明。 什么是 Intl.NumberFormat?Intl.NumberFormat 是一个用于格式化数字的 JavaScript 国际化 API。它使开发人员能够依据用户的语言环境和地区设置自定义数字格局。这意味着您能够应用该 API 来格式化数字,以便在不同的语言和地区中进行显示。 如何应用 Intl.NumberFormat?应用 Intl.NumberFormat 非常简单。以下是一个根本的应用示例,用于格式化一个数字: const number = 123456.789const formatter = new Intl.NumberFormat()console.log(formatter.format(number))在下面的示例中,咱们首先定义了一个数字变量number,而后创立了一个Intl.NumberFormat实例,并将其存储在变量formatter中。最初,咱们应用formatter.format()办法来格式化数字,并将后果打印到控制台中。 输入后果为: 123,456.789在下面的示例中,咱们没有提供任何参数来创立Intl.NumberFormat实例。这意味着它将应用默认设置来格式化数字。然而,您能够应用以下参数来创立自定义格局: locale:用于格式化数字的语言环境。默认值为以后用户的语言环境。style:数字格局的款式。能够是decimal(十进制)、currency(货币)或percent(百分比)。默认值为decimal。currency:如果款式为currency,则应用的货币代码。默认值为以后用户的货币代码。currencyDisplay:如果款式为currency,则货币符号的显示地位。能够是symbol(符号)、code(代码)或name(名称)。默认值为symbol。minimumIntegerDigits:数字的最小整数位数。默认值为 1。minimumFractionDigits:数字的最小小数位数。默认值为 0。maximumFractionDigits:数字的最大小数位数。默认值为 3。minimumSignificantDigits:数字的最小有效数字位数。默认值为 1。maximumSignificantDigits:数字的最大有效数字位数。默认值为 21。以下是一个示例,展现如何应用这些参数来创立自定义数字格局: const number = 123456.789const formatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2,})console.log(formatter.format(number))输入后果为: $123,456.79在下面的示例中,咱们应用了en-US作为语言环境,并将款式设置为currency。咱们还指定了货币代码为USD,最小小数位数为 2,最大小数位数为 2。这使得输入后果为美元货币格局。 应用场景Intl.NumberFormat 可用于任何须要格式化数字的场景: Intl.NumberFormat 反对的类型单位指的是 Intl.NumberFormat 对象反对的数字格式化类型。以下是每种类型的中文解释和代码示例: 1. 货币格式化货币格式化是将数字格式化为特定货币的格局。应用 Intl.NumberFormat,您能够轻松地将数字格式化为任何货币,并在不同的语言环境中进行显示。例如,以下代码将格式化数字为美元货币格局: const number = 1234.56const formatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD',})console.log(formatter.format(number))输入后果为: ...

April 6, 2023 · 1 min · jiezi

关于javascript:Vue3中defineEmitsdefineProps-是怎么做到不用引入就能直接用的

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。最近正在将一个应用单文件组件的 Options API 的 Vue2 JavaScript 我的项目降级为 Vue3 typescript,并利用 Composition API 的劣势。 比方,上面这种 选项API 形式: export default { props: { name: { type: String, required: true. } }, emits: ['someEvent', 'increaseBy']};咱们将它转成 组合API 形式: const props = defineProps<{ name: string; }>(); const emit = defineEmits<{ (event: 'someEvent): void; (event: 'increaseBy', value: number): void; }>();从 选项API 的 emit 和 props 到 组合API 的 defineemit 和 defineProps 函数的基于类型语法的转换并不简略。我也很好奇 Vue 是如何解决接口的。 ...

April 6, 2023 · 2 min · jiezi

关于javascript:js用前缀名查找class或id节点js模糊查询某个dom节点

js在操作dom的场景中,有时候会有相似的场景需要。 js用前缀名查找class节点// 参数dom为html dom节点// 参数key为需含糊查问的名称字段function queryClassNode(dom, key) { let collectArray = []; for (var i = 0; i < dom.childNodes.length; i++) { // 外围点 if (dom.childNodes[i].attributes && dom.childNodes[i].attributes["class"] && dom.childNodes[i].className.indexOf(key) !== -1) { collectArray.push(dom.childNodes[i]); } if (dom.childNodes[i].childNodes.length > 0) { let res = queryClassNode(dom.childNodes[i], key); for (var k = 0; k < res.length; k++) { collectArray.push(res[k]); } } } return collectArray;}js用前缀名查找Id节点// 参数dom为html dom节点// 参数key为需查问的前缀名function queryIdNode(dom, key) { let collectArray = []; for (var i = 0; i < dom.childNodes.length; i++) { // 外围点 if (dom.childNodes[i].attributes && dom.childNodes[i].attributes["id"] && dom.childNodes[i].id.indexOf(key) !== -1) { collectArray.push(dom.childNodes[i]); } if (dom.childNodes[i].childNodes.length > 0) { let res = queryIdNode(dom.childNodes[i], key); for (var k = 0; k < res.length; k++) { collectArray.push(res[k]); } } } return collectArray;}成果<html><body><div> <div></div> <div> <span id="test1"> 233 <span class="demo1">666</span> </span> <span id="test2"> <span id="test3">666</span> <span class="demo1">888</span> <span class="demo2">999</span> </span> </div></div></body><script>.........console.log(queryIdNode(document.body, 'test')); // [span#test1, span#test2, span#test3]console.log(queryClassNode(document.body, 'demo')); // [span.demo1, span.demo1, span.demo2]</script></html>

April 5, 2023 · 1 min · jiezi

关于javascript:Object面向对象程序设计

前言对象初始化能够通过new Object(),Object.create()办法,或者应用字面量标记(初始化标记)初始化对象。 object.create()是应用指定的原型proto对象及其属性propertiesObject去创立一个新的对象。简略实现 new Object()new 运算符是创立一个自定义对象或者具备构造函数的内置对象的实例应用new运算符会创立一个新的对象,它继承自构造函数的prototype,也就是说它的__proto__属性会指向构造函数的prototypenew Object() 也就是具备构造函数的内置Object的实例,新创建的对象的__proto__属性会指向Object的prototype 字面量标记 字面量形式申明的对象 除了用对象点(.)的形式 还能够利用ES5提供的Object.defineProperty定义对象属性(数据属性和拜访器属性) 数据属性1、configurable:示意是否通过delete删除属性从而从新定义属性,是否批改属性的个性,或者是否把属性批改为拜访器属性,默认值为false,对于间接定义在对象上的属性默认值为true2、enumerable:示意是否通过for in循环拜访属性,默认值为false,对于间接定义在对象上的属性默认值为true3、writable:示意是否批改属性的值。默认值为false,对于间接定义在对象上的属性默认值为true4、value:蕴含这个属性的数据值。默认值为undefined 拜访器属性1、configurable:示意是否通过delete删除属性从而从新定义属性,是否批改属性的个性,或者是否把属性批改为拜访器属性,默认值为false,对于间接定义在对象上的属性默认值为true2、enumerable:示意是否通过for in循环拜访属性,默认值为false,对于间接定义在对象上的属性默认值为true3、get:在读取属性时调用的函数,默认值为undefined3、set:在写入属性时调用的函数,默认值为undefined ** 备注:定义多个对象属性办法: Object.defineProperties( )读取对象某个属性个性的办法: Object.getOwnPropertyDescriptor( )读取对象所有属性个性的办法: Object.getOwnPropertyDescriptors( )

April 5, 2023 · 1 min · jiezi

关于javascript:vitejs-typescript-react-项目搭建过程实践

本文记录了应用vitejs, antd, react, redux搭建我的项目过程,其它蕴含了集成jest单元测试, tailwindcss应用,eslint代码格式化以及 git 代码提交规范化等性能。 1. 初始化我的项目咱们应用 Vite.js 来打包咱们的代码。 运行如下命令: pnpm create vite会呈现如下的抉择: √ Project name: ... react-redux-starter # 设置我的项目名 这里咱们设置为react-redux-starter√ Select a framework: » React # 抉择框架 React√ Select a variant: » TypeScript + SWC 到这里咱们我的项目初始化实现。 这时能够看到咱们初始化的我的项目目录如下: react-redux-starter │ .gitignore │ index.html │ package.json │ tsconfig.json # typescript 配置文件 │ tsconfig.node.json # typescript 配置文件 │ vite.config.ts # vite 配置文件 │ ├─public │ vite.svg │ └─src │ App.css │ App.tsx │ index.css │ main.tsx │ vite-env.d.ts │ └─assets react.svg这里咱们先把初始化的代码清理一下: ...

April 4, 2023 · 4 min · jiezi

关于javascript:一个令人惊艳的ChatGPT项目开源了

最近在GitHub上发现了一个爆火的开源我的项目。 好家伙,凑近一看,竟然还是由微软开源,并且和最近煊赫一时的ChatGPT非亲非故。 我的项目的名字叫做:Visual ChatGPT。 https://github.com/microsoft/visual-chatgpt 这个我的项目最早是3月上旬微软开源的,我的项目发表开源后仅用了短短一周,就斩获了2w+ star。 到当初为止,间隔当初我的项目开源大概过来了3周多,仓库star数则来到了28k+,亦堪称是火箭式上涨(doge)。 家喻户晓,ChatGPT自2022年11月推出以来,继续走红。 ChatGPT具备弱小的会话能力,能够了解文字、聊天、写小说、解答问题、编写代码... 然而目前还并不能间接解决或生成图像。 而Visual ChatGPT这个我的项目则能够把ChatGPT和一系列视觉根底模型(VFM,Visual Foundation Model)给分割起来,以便实现在ChatGPT聊天的过程中来发送和接管图像,也使得ChatGPT可能解决更为简单的视觉工作。 讲白了,就是通过Visual ChatGPT,能够把一系列视觉根底模型给接入ChatGPT,使得ChatGPT能胜任更为简单的视觉解决工作。 Visual ChatGPT的整体技术架构图如上所示,咱们能够分明地看到ChatGPT和视觉根底模型(VFM,Visual Foundation Model)别离位于其中的地位。 一方面,ChatGPT(或LLM)作为一个通用接口,持续施展它自身的劣势,提供对不同话题的智能了解。另一方面,根底视觉模型VFM则通过提供特定畛域的深刻常识来充当领域专家,它们通过交互治理模块(Prompt Manger)进行连贯和适配。 这样聊可能比拟形象,咱们能够拿官网给的一个例子来进行阐明: 1、首先是用户:输出一张黄色的向日葵图片,并且要求ChatGPT依据该图像预测深度来生成一朵红花,而后再一步一步将其做成卡通画。 2、接着是交互治理模块(Prompt Manger)发挥作用,在它的协调和管制下,VFM模块开始发挥作用: 首先须要使用深度预计模型来预测并生成图像的深度信息;而后须要使用深度图像模型来生成对应空间深度的红花图像;最初使用Stable Diffusion的格调迁徙模型来实现图像格调的变换。3、最初Visual ChatGPT零碎再将最终后果返回给用户,实现本次对话。 说到这里,有趣味的小伙伴能够能够看看微软给出的一篇无关Visual ChatGPT的论文。 外面对于这部分的流程解释得十分具体,而且还给出了多轮对话的案例、以及试验后果,有趣味的小伙伴能够看看。 好了,明天的分享就到这里了,感激大家的收看,咱们下篇见。 注:本文在GitHub开源仓库「编程之路」 https://github.com/rd2coding/Road2Coding 中曾经收录,外面有我整顿的6大编程方向(岗位)的自学路线+知识点大梳理、面试考点、我的简历、几本硬核pdf笔记,以及程序员生存和感悟,欢送star。

April 4, 2023 · 1 min · jiezi

关于javascript:React-为什么重新渲染

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。更新(从新渲染)是 React 的重要个性 —— 当用户与利用交互的时候,React 须要从新渲染、更新 UI,以响应用户的输出。然而,React 为什么会从新渲染呢?如果不晓得 React 为什么会从新渲染,咱们如何能力防止额定的从新渲染呢? TL; DR状态扭转是 React 树外部产生更新的唯二起因之一。 这句话是 React 更新的公理,不存在任何例外。本文也将会围绕解释这句话开展。为了防止有人抬杠,这句话引入了一些限度定语和关键词: 名词解释「更新」和「从新渲染」在 React 中,「更新」和「从新渲染」是关系严密,然而含意齐全不同的两个词。上面这句话能力正确表白这两个词的正确含意: React 的「更新」蕴含三个阶段:渲染(Render),应用 createElement 或 jsx-runtime 产生全新的 React Element 对象、组装出一颗 React 树;Reconcilation,React Reconciler 比拟 新生成的 React 树 和 以后的 React 树,判断如何用最高效的办法实现「更新」;Commit,操作 Host(如 DOM、Native 等),使新的 UI 出现在用户背后。 大部分开发者会把「更新」和「从新渲染」一概而论,因为在上述三个阶段中,只有「渲染」这一阶段是开发者能够管制的(「Reconcilation」和「Commit」别离由 react-reconciler 和 React Host 管制)。本文接下来的局部中,「从新渲染」一律指代 React 组件在「更新」时的「渲染」阶段,而「更新」则一律指代(从新)渲染、Reconcilation 和 Commit 整个过程。 「React 树」和「React 树外部」React Tree 自身能够在任意时候更新。实际上,如果你已经通过 React 文档学习 React,你在「Hello World」一章就曾经见过这个 Pattern 了: ...

April 3, 2023 · 4 min · jiezi

关于javascript:js-实现从1103中随机抽取多个数返回一个数组

function getNum(min,max,count){ let arr = []; for (let i = 0; i < count; i++) { arr[i] = (Math.ceil(Math.random()*max)); } return arr;};getNum(1,103,10);console.log(getNum(1,103,10));

April 2, 2023 · 1 min · jiezi

关于javascript:visibilitychange搭配documenthidden实现有意思的tab页离开进入效果

问题形容咱们先看上面这一张效果图: 效果图 需要当来到或进入tab标签页时,动静更改tab的title内容显示 解决方案其实很简略,只是一时间咱们可能想不到,不过Web的创造设计者们,早就想到了,并提供了相干的api 监听visibilitychange事件搭配document.hidden属性值visibilitychange visibilitychange是一个事件名此事件的触发取决于选项卡的内容可见或被暗藏时能够应用document去监听这个事件的变动,从而做一些逻辑的操作document.hidden 示意页面是(true)否(false)暗藏能够了解为进入tab标签页和来到tab标签页另有document.visibilityState为visible或hidden(罕用),一个意思晓得这两个api,那相干的需要,就能解决啦 代码<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="http://ashuai.work/static/img/avantar.png"> <title>欢送欢送</title></head><body> <script> /** * 标签页题目切换 * */ // 监听visibilitychange事件 document.addEventListener("visibilitychange", function () { console.log('document.visibilityState', document.visibilityState); // 若是来到此tab标签页 if (document.hidden) { document.title = "你快回来" } // 若是进入此tab标签页 else { document.title = "欢送欢送" } }); </script></body></html>延长应用场景实际上,在工作中,页面来到或暗藏触发相应的逻辑,还是有一些场景的。如下: 在当前页播放音乐,来到当前页暂停音乐在线做面试题时,看看求职者有没有来到以后tab页,去百度答案啥的来到以后tab页,给页面加上明码,进入时需输出明码(隐衷平安问题)一些blog的title成果,比方笔者的这个blog:http://ashuai.work:8890/官网api地址:visibilitychange:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/vis...document.hidden:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/hiddenvisibilityState:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/vis...

April 2, 2023 · 1 min · jiezi

关于javascript:在前端使用-JS-进行分类汇总

最近遇到一些同学在问 JS 中进行数据统计的问题。尽管数据统计个别会在数据库中进行,然而后端遇到须要应用程序来进行统计的状况也十分多。.NET 就为了对内存数据和数据库数据进行对立地数据处理,创造了 LINQ (Language-Integrated Query)。其实 LINQ 语法自身没什么,要害是为了实现 LINQ 而设计的表达式树、IEnumerable 和 IQueryable 的各种扩大等。 提出问题不扯远了,先来看问题。依据上面的样例数据,要求失去 先按业务,再按部门分组的数据;不按部门,间接按业务别离统计每年的数据[ { name: "部门1", businesses: [ { name: "产品销售", years: [ { name: "2021", value: 132 }, { name: "2022", value: 183 }, { name: "2023", value: 207 } ] }, { name: "原料洽购", years: [ { name: "2021", value: 143 }, { name: "2022", value: 121 }, { name: "2023", value: 120 } ] } ] }, { name: "部门2", businesses: [ { name: "产品销售", years: [ { name: "2021", value: 230 }, { name: "2022", value: 112 }, { name: "2023", value: 288 } ] }, { name: "原料洽购", years: [ { name: "2021", value: 168 }, { name: "2022", value: 203 }, { name: "2023", value: 115 } ] } ] }, { name: "部门3", businesses: [ { name: "产品销售", years: [ { name: "2021", value: 279 }, { name: "2022", value: 163 }, { name: "2023", value: 271 } ] }, { name: "原料洽购", years: [ { name: "2021", value: 129 }, { name: "2022", value: 121 }, { name: "2023", value: 226 } ] } ] }];这个数据,如果用金山文档的轻维表(飞书多维表相似)来查看,会更直观 ...

April 2, 2023 · 4 min · jiezi

关于javascript:Serverside-rendering-for-any-React-app-on-any-FaaS-provider

By this document, I'd like to introduce a general method to set up server-side rendering(SSR) for any React app on any FaaS provider. A "React app" is a web app with its client side (or frontend) built with React. A "FaaS provider" is a serverless computing platform, such as AWS Lambda. To state the idea clearly, a runnable demo app is constructed step by step below. I would guide you through the steps, then summarize the idea. ...

April 2, 2023 · 20 min · jiezi

关于javascript:一文彻底搞懂JS事件循环原理

要想说明确事件循环就要先引入过程和线程的概念。过程 广义定义:过程是正在运行的程序的实例(an instance of a computer program that is being executed)。 狭义定义:过程是一个具备肯定独立性能的程序对于某个数据汇合的一次运行流动。它是操作系统动静执行的根本单元,在传统的操作系统中,过程既是根本的调配单元,也是根本的执行单元。 线程: 线程(英语:thread)是操作系统可能进行运算调度的最小单位。它被蕴含在过程之中,是过程中的理论运作单位。一条线程指的是过程中一个繁多程序的控制流,一个过程中能够并发多个线程,每条线程并行执行不同的工作。在浏览器的工作管理器中查看以后的所有过程,能够发现,最次要的过程有: 浏览器过程次要负责界面显示、用户交互、子过程治理等。浏览器过程外部会启动多个线程解决不同的工作。网络过程负责加载网络资源。网络过程外部会启动多个线程来解决不同的网络工作。渲染过程(事件循环产生在渲染过程中)渲染过程启动后,会开启一个渲染主过程,主过程负责执行HTML,CSS,JS代码。默认状况下,浏览器会为每一个标签页开启一个新的渲染过程,以保障每一个标签页之间不相互影响。渲染主线程是如何工作的?渲染主线程算是浏览器最忙碌的线程,它须要解决的工作包含然而不限于: 解析HTML解析CSS计算款式布局解决图层执行全局的JS代码执行事件处理函数执行计时器的回调函数执行微工作 ······················ 对于渲染主线程解决的工作繁多,如何调度工作?为何不实用用多线程来解决这些事呢? 渲染主线程引入排队思维来解决调度工作的问题 在最开始的时候,渲染主线程会进入一个无线循环;每一次循环会查看音讯队列中是否有工作存在。如果有,就取出第一个工作执行,执行完一个后进入下一次循环;如果没有,则进入休眠状态;其余所有线程(包含其余过程的线程)能够随时向音讯队列增加工作。新工作会加到音讯队列的开端。在增加新工作时,如果主线程是休眠状态,则会将其唤醒以持续循环拿取工作; 这样一来,就能够让每一个工作井井有条的运行上来了。 这样的整个过程,被称之为事件循环(音讯循环) 要想深刻的了解事件循环还要搞清楚异步、阻塞渲染、工作优先级,上面接着一一阐明 何为异步?代码在执行过程中,会遇到一些无奈立刻解决的工作 计时实现后须要执行的工作 --setTimeOut、setInterval网络通信实现后须要执行的工作 --- XHR、Fetch用户操作后须要执行的工作 -- addEvenetListener如果让渲染主线程期待这些工作的机会达到,就会导致主线程长期处于【阻塞】的状态,从而导致浏览器【卡死】渲染主线程承当着极其重要的工作,无论如何都不可能阻塞因而,浏览器采纳异步来终局阻塞这个问题,如下图所示: 如何了解JS的异步?JS是一门单线程的语言,当它运行在浏览器渲染主线程中,渲染主线程只有一个。而渲染主线程承当着诸多的工作,渲染页面、执行JS都在其中运行。如果应用同步的形式,就极有可能导致主线程产生阻塞,从而导致音讯队列中的很多其余工作无奈失去执行。这样一来,一方面会导致忙碌的主线程白白的耗费工夫,另一方面导致页面无奈及时更新,给用户造成卡死景象。所以浏览器采纳异步的形式来防止。具体做法是当某些工作产生时,比方计时器、网络、事件监听,主线程将工作交给其余线程去解决,本身立刻结束任务的执行,转而执行后续的代码。当其余线程实现时,将当时传递的回调函数包装成工作,退出到音讯队列的开端,期待主线程调度执行。 在这种异步的模式下,浏览器永不会阻塞,从而最大限度的保障了单线程的晦涩进行。 工作有优先级吗?每个工作都有一个工作类型,同一个类型的工作必须在一个队列,不同类型的工作能够分属于不同的队列。 在一次事件循环中,浏览器能够依据理论状况从不同的队列中取出工作执行。 浏览器必须筹备好一个微队列,微队列中的工作优先所有其余工作。 在目前chrome的实现中,至多蕴含了上面的队列: 延时队列:用于寄存计时器达到后的回调工作,优先级【中】;交互队列:用户寄存用户操作后产生的事件处理工作,优先级【高】;微队列:用户寄存须要最快执行的工作,优先级【最高】增加工作到微队列的次要形式应用Promise,MutationObserver 例题一 例题二 例题三 总结事件循环又叫音讯循环,是浏览器渲染主线程的工作形式。 在chrome的源码中,他开启一个不会完结的for循环,每次循环从音讯队列中取出一个工作执行,而其余线程只须要在适合的时候将工作退出到队列开端即可。 过来的音讯队列简略的分为宏工作和微工作,这种说法目前曾经无奈满足简单的浏览器环境,取而代之的是一种更加灵便的解决形式。 依据W3C官网的解释,每个工作有不同的类型,同类型的工作必须在同一个队列,不同的工作能够属于不必的队列。不同工作队列有不同的优先级,在一次事件循环中,由浏览器自行决定取哪一个队列的工作。但浏览器必须有一个微队列,微队列的工作肯定具备最高的优先级,必须优先调度执行。 反诘:JS中的计时器能做到准确计时吗?为什么?

March 31, 2023 · 1 min · jiezi

关于javascript:YonTalk-大咖论道YonBuilder-低代码开发平台能力解析

开发效率远超传统形式数倍、帮忙企业大幅降本增效…… 在大家看来,低代码就是具备这些能力的利用开发方式。对于企业低代码选型而言,须要分明地晓得本人将要利用的低代码开发平台具备哪些能力,与其余平台又有哪些不同,更须要找到一些行业实际作为参考。3 月 16 日,由用友开发者核心发动的 YonTalk 大咖论道通过直播形式与大家见面。期间,用友低代码平台架构师肖培明联合用友在低代码畛域的丰盛实际,从低代码能力要求、企业低代码实战等角度带来深度分享,帮忙大家成为 IT 与业务的 “破壁者”。01谈低代码 “能力要求”要回头看 “基本需要”回到终点,低代码自身要应答什么样的问题?在用友看来,低代码要解决的是开发资源无奈撑持企业应用开发需要,即开发产能有余的矛盾。企业业务需要增多是一种必然趋势,而业务需要变动太快、我的项目周期太长、IT 估算有余、程序改变 Bug 太多、可复用性低等造成了利用开发难以突破的枷锁,满足业务需要变得越发艰难。企业数智化转型的需要是不可能被压抑的,因此只能千方百计晋升产能。在行业的一直摸索中,通过一种工具或平台把开发门槛升高,容许更多不同背景、不同角色的人参加到利用开发中以进步产能,这一方向失去了很多人的认同。这为低代码平台的迅速遍及关上了通路。现在,低代码已成为许多企业构建利用的重要伎俩,更是企业数智化转型的一种根底能力。它能够升高设计门槛,让更多角色参加,通过无代码的形式实现利用交互和业务逻辑的定义,实现业务对象之间的数据流转,同时正当地调配企业 IT 资源,实现麻利开发,为企业业务提供数智化反对。尤其在业务利用方面,需要范围广、历时长,开发规模也日益增长。为了治理开发过程,须要制订标准,并通过低代码工具注入到每个阶段的成绩中,以此来治理和晋升开发产能。同时,这些标准也能够在企业和行业之间进行复制,从而大规模晋升利用的响应能力。02用友低代码平台架构师解析 YonBuilder 能力图谱目前,用友通过全新降级后的 “用友开发者核心” 向社会化开发者、生态搭档等提供 YonBuilder 低代码开发能力。在用友看来,现阶段低代码该当可能造成对企业的数智化利用造成撑持,利用开发、数据和智能、连贯集成等方面都是 “必修课”。低代码开发平台是一个智能全过程、多角色工具链的组合。谁组合得更好、能提供更残缺的工作链,把多种角色融入进来,谁就可能解决后面提到的外围矛盾 —— 开发产能有余。YonBuilder 以云原生、多租户、模型驱动为根底技术,面向原厂开发、ISV 开发、本地化开发、企业自建、集体开发者在内的全生态,提供无代码和低代码的可视化开发能力,并与开放平台、连贯集成平台、DevOps 平台无缝整合,实现高效的企业级利用构建,无效升高技术门槛,大幅晋升企业 IT 生产力。YonBuilder 低代码开发平台的利用支撑体系分为多云适配层、技术&框架层、利用组件&框架层、畛域模型层、业务逻辑层以及应用服务层。这些档次形成了低代码开发平台的残缺工具链路。更全面地说,用友将 YonBuilder 低代码开发平台的能力划分成低代码利用构建、低代码移动开发、低代码连贯集成、低代码数据分析、低代码区块链构建、低代码 AI 开发六个方面,进而能够为用户提供三种能力,即全新利用开发、针对原厂利用的扩大、基于各行各业业余搭档和客户提供分层开发能力。借助 YonBuilder 构建利用,流程涵盖数据建模、性能建模、业务建模、集成配置、利用治理。其中较为要害的是数据模型 ——YonBuilder 设计了业务对象这一模型,助力企业建模能力及撑持服务能力晋升。通过基于业务对象的形容,能够清晰地形容出事实世界中的业务,并通过利用拜访它们。为了让利用构建更简略,用友进一步设计了基于业务对象的业务相关性规定,用以提供可了解的规定、可视化的决策建模和智能化的后果出现来辅助决策、对立规定存储和执行服务、规定全生命周期治理。例如,在构建利用须要画流程图时,通常企业会认为其流程非常简单,但实际上这些步骤中的业务审核往往蕴含许多规定。以一个更具体的场景来阐明,当物料金额超过肯定数量或物料类型发生变化时,须要转到不同的环节。如果不应用规定引擎,在流程图上可能会呈现许多环节,导致简单而难以了解。通过将规定库嵌入到每个环节中,企业就能够简化流程图。为了实现挪动 PC 一体化,充分发挥挪动设施的能力和劣势,YonBuilder 在构建传统 PC 利用的根底上,还提供了挪动开发能力,一次构建可在多个终端应用。03进步 IT 产能不止平台和工具更须要关注开发人才增长实际上,我国早就开始针对产能提供方发展改革。例如,2021 年会计教育委员会的会议上,将应用型本科、职业院校的会计学改名为大数据与会计、财税改为财税大数据利用。紧跟改名而来是教育内容的调整 —— 减少了大量的数据分析、数字化利用和可视化剖析等方面的内容。窥一斑而知全豹,大量资源曾经开始向数智化时代歪斜,以缓解资源有余的矛盾。而事实上,这些财会相干业余的改革正是利用了日渐蓬勃的低代码开发平台。在开发者生态建设一事上,用友同样不遗余力。

March 31, 2023 · 1 min · jiezi

关于javascript:再学JS高级笔记2JavaScript的执行过程

2 JavaScript的执行过程如果咱们有上面一段代码,它在JavaScript中是如何被执行的 呢? var name = "why"function foo(){ var name = "foo" console.log(name)}var num1 = 20var num2 = 30var result = num1 + num2console.log(result) 2.1 第一步:初始化全局对象 JS引擎会在执行代码之前,在堆内存中创立一个全局对象:Global Object(GO) 该对象所有的作用域(scope)都能够拜访外面会蕴含Date、Array、String、Number、setTimeout、setInterval等等其中还要一个window属性指向本人 创立GO的伪代码var GlobalObject = { String: '类', Date: '类', window: GlobalObject, name: undefined, num1: undefined, num2: undefined, result: undefined, foo: 0xa00//会指向专门为该函数在内存开拓一个空间地址}开拓的函数空间存储的内容和构造如下:2.2 第二步:执行调用栈代码要想运行,都须要先增加到内存外面,内存外面划分为栈构造和堆构造 JS引擎为了执行代码,外部有一个执行上下文(Execution Context Stack, ECS) 。那么当初它要执行谁呢?执行的是全局的代码块(能够了解为函数)。为了全局代码也可能失常执行,须要创立 全局执行上下文(Global Execution Context (GEC))GEC会放入到ECS中执行,外面蕴含两局部内容:第一局部:在代码执行前,在parser转成AST的过程中,会将全局定义的变量、哈形容等退出到GlobalObject中,然而并不会赋值 这个过程也称之为变量的作用域晋升(hoisting) var name = "why"function foo(){ var name = "foo" console.log(name)}console.log(num1) //如果在这里退出这行代码,打印的num1值为undefined,因为曾经在go外面申明var num1 = 20var num2 = 30var result = num1 + num2console.log(result) 全局执行上下文GEC中的VO(variable Object)就是GO(Global Object)对象第二局部:开始执行代码执行,对变量赋值,或者执行其余的函数2.3 遇到函数如何执行在执行的过程中执行到一个函数时,就会依据函数体创立一个函数执行上下文(Functional Execution Context,简称FEC),并且压入到ECStack中。 ...

March 30, 2023 · 1 min · jiezi

关于javascript:UEditorPlus-v300-接口请求头参数插入换行优化若干问题优化

UEditor是由百度开发的所见即所得的开源富文本编辑器,基于MIT开源协定,该富文本编辑器帮忙不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器,次要做了款式的定制,更合乎古代浏览器的审美。 在开发过程中解决了局部应用上的Bug,期待更多搭档一期退出保护。 版本介绍UEditorPlus v3.0.0 曾经公布。 新增:Markdown题目快捷模式(输出多个#+空格主动格式化为题目)新增:当内容最开端为非字符时,比拟难以在最初插入字符问题新增:beforesubmit事件,不便提交前的数据处理新增:浏览自高度和宽度主动变动时候减少动画成果新增:后端接口新增公共头参数 #gitee-I6KK5D新增:默认减少 message 插件,反对音讯提醒优化:字体设定和字体抉择,反对复原默认字体和字体不存在时异样显示 #gitee-I6JHV4优化:富文本编辑器UEditor款式缓存问题优化:草稿性能数据恢复逻辑优化,防止初始内容笼罩保留值问题优化:补全VUE应用文档示例配置项,防止CROS跨域引起的问题修复:源码中默认减少两次,生成的all.js 图片等操作多一次默认 #gitee-I6L6LU对于Bug反馈与保护家喻户晓 UEditor 应用的人数多,目前曾经累积了N个Bug,开源不易须要大家独特保护对于在理论应用中遇到的问题,如果急需解决举荐应用 悬赏Issue ,这样让更多有能力的开发者有独特保护的能源在线演示https://open-demo.modstart.com/ueditor-plus/_examples/在线文档https://open-doc.modstart.com/ueditor-plus/开源地址国内:https://gitee.com/modstart-lib/ueditor-plus国内:https://github.com/modstart-lib/ueditor-plus文档国内:https://gitee.com/modstart-lib/ueditor-plus-doc

March 30, 2023 · 1 min · jiezi

关于javascript:解决无界微前端在IE浏览器兼容

环境"dependencies": { "vue": "^3.2.47", "wujie-vue3": "^1.0.13"},"devDependencies": { "@vitejs/plugin-vue": "^4.1.0", "vite": "^4.2.0"}1. build实现之后,报错系列 解决此报错npm i whatwg-fetch -Snpm i custom-event-polyfill -S入口main.js文件引入 import "whatwg-fetch"; // fetch polyfillimport "custom-event-polyfill";import {createApp} from 'vue'import './style.css'import App from './App.vue'// vue3import WujieVue from "wujie-vue3";const {bus, setupApp, preloadApp, destroyApp} = WujieVue;const app = createApp(App)app.use(WujieVue)app.mount('#app')2. build实现之后,报错系列 解决此问题退出es6-proxy-polyfill@2.1.1这个版本 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <link rel="icon" type="image/svg+xml" href="/vite.svg"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>Vite + Vue</title> <script src="https://cdn.jsdelivr.net/npm/es6-proxy-polyfill@2.1.1/dist/es6-proxy-polyfill.min.js"></script></head><body><div id="app"></div><script type="module" src="/src/main.js"></script></body></html>完满解决 残缺package.json { "name": "my-vue-app", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { "@vitejs/plugin-legacy": "^4.0.2", "custom-event-polyfill": "^1.0.7", "vue": "^3.2.47", "whatwg-fetch": "^3.6.2", "wujie-vue3": "^1.0.13" }, "devDependencies": { "@vitejs/plugin-vue": "^4.1.0", "terser": "^5.16.8", "vite": "^4.2.0" }}

March 30, 2023 · 1 min · jiezi

关于javascript:Vue-3现实生活中的过渡和微互动

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。Vue 提供了一种简略优雅的解决动画的办法。你能够通过增加一个 <transition /> 指令轻松利用它们,该指令为你实现所有沉重的工作。或者,你能够利用 JavaScript 钩子将更简单的逻辑纳入你的动画中,甚至能够增加第三方库(如 gsap)以实现更高级的用例。 在本文中,咱们将钻研这些不同的选项,但首先,让咱们临时将 Vue.js 放在一边,探讨 CSS 过渡和动画之间的差别。 过渡与动画过渡是在两个不同状态之间进行的。开始状态和完结状态。例如,对于模态组件,开始状态可能是暗藏的,完结状态可能是可见的。你设置这些状态,浏览器会用一系列两头帧填充状态更改。 button { background-color: #0ff1ce; transition: background-color 0.3s ease-in;}button:hover { background-color: #c0ffee;}如果你想执行一些不波及明确的起始状态和完结状态的操作,或者你须要更精密地管制过渡中的关键帧,那么你必须应用动画。 button:hover { animation-duration: 3s; animation-iteration-count: infinite; animation-name: wobble;}@keyframes wobble { 0%, 100% { transform: translateX(0%); transform-origin: 50% 50%; } 15% { transform: translateX(-32px) rotate(-6deg); } 30% { transform: translateX(16px) rotate(6deg); } 45% { transform: translateX(-16px) rotate(-3.6deg); } 60% { transform: translateX(10px) rotate(2.4deg); } 75% { transform: translateX(-8px) rotate(-1.2deg); }}后果: ...

March 30, 2023 · 2 min · jiezi

关于javascript:你需要知道的Symbols

驰名symbol驰名symbol是一个在不同畛域中都雷同且未注册的symbol。如果咱们要列出驰名symbol,它们会是: Symbol.iteratorSymbol.toStringTagSymbol.toPrimitiveSymbol.asyncIteratorSymbol.hasInstanceSymbol.isConcatSpreadableSymbol.speciesSymbol.matchSymbol.matchallSymbol.replaceSymbol.searchSymbol.splitSymbol.unscopablesSymbol.dispose让咱们看一些例子来理解其有用性。 Symbol.iteratorSymbol.iterator:该symbol被用来为对象定义默认的迭代器。它被用来在for-of循环中实现对对象的迭代,或用于扩大操作符。 const obj = { a: 1, b: 2, c: 3 };obj[Symbol.iterator] = function*() { for (const key of Object.keys(this)) { yield [key, this[key]]; }};for (const [key, value] of obj) { console.log(`${key}: ${value}`);}Symbol.toStringTagSymbol.toStringTag:该symbol被用来指定在调用Object.prototype.toString办法时返回的字符串值,以便为对象提供自定义的字符串示意模式。 class MyClass { static [Symbol.toStringTag] = 'MyClass';}const myInstance = new MyClass();console.log(myInstance.toString()); // outputs '[object MyClass]'Symbol.toPrimitiveSymbol.toPrimitive:该symbol被用来指定对象在隐式调用valueOf和toString办法时的行为。能够用它来为对象提供自定义的字符串和数字示意模式。 class Life { valueOf() { return 42; } [Symbol.toPrimitive](hint) { switch (hint) { case "number": return this.valueOf(); case "string": return "Forty Two"; case "default": return true; } }}const myLife = new Life();console.log(+myLife); // 42console.log(`${myLife}`); // "Forty Two"console.log(myLife + 0); // 42Symbol.asyncIteratorSymbol.asyncIterator:该symbol被用来为对象定义一个异步的迭代器。能够用它来为对象启用异步迭代。 ...

March 30, 2023 · 2 min · jiezi

关于javascript:单行JS珍藏提升效率

数组去重从数组中删除反复元素,如何简略优雅的实现 const uniqueArr =(item)=> [... new Set(item)]console.log(uniqueArr(arr)) 从url获取参数并转为对象 const getParameter = URL => JSON.parse(`{"${decodeURI(URL.split("?")[1]).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`)getParameter("http:''www.baidu.com/search?q=js+md&type=webpage")//{q:"js+md",type:"webpage"}检测对象是否为空 const isEmpty = obj => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;isEmpty({}) // trueisEmpty({1:'my name is empty'}) // false十六进制随机色调 // 生成随机色const randomColor = () =>`#${Math.floor(Math.random()* 0xffffff) .toString(16).padEnd(6,'0')}`console.log(randomColor())查看以后选项卡是否在后盾 const isTabActive = () => !document.hiddenisTabActive() // true | false查看设施类型 //查看设施类型const isMobileOrPc = () =>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|OperaMini/i.test(navigator.userAgent) ? 'Mobile' : 'PC';### isMobileOrPc() // PC | Mobile文字复制到剪贴板 // 文字复制到剪贴板const copyText = async (text) => await navigator.clipboard.writeText(text)copyText('13678933456')获取选定文本const getSelectText = () => window.getSelection.toString()getSelectText()判断某天是否为工作日 ...

March 29, 2023 · 1 min · jiezi

关于javascript:用JavaScript写一个彩票系统

本来这篇文章是打算叫「如果我是彩票零碎开发者」,但细想一下,如果在文章中援用太多的 JavaScript 的话,反而不是那么纯正,毕竟也只是我的两厢情愿,彩票开发也不全如本文所讲,有所误导的话便也是得失相当了。 所以索性就叫「用 JavaScript 写出一个彩票零碎」,也算清朗了一些,申明一下,实在的彩票零碎不是这么开发进去的,也不具备明面上的法则,咱们应该置信彩票的公正性,只管其可能不是基于随机! 杂谈最近大抵是迷上彩票了,空想着本人若能暴富,也能够带着家庭"鸡犬升天"了,不过大失所望,我并没有冲天的气运,踏踏实实工作才是前途? 买彩票的时候,我也思考了很久,到底怎么样的号码能够在1700万注中怀才不遇,随机试过,精心筛选的也试过,找法则的模式也试过,甚至我还用到了爬虫去统计数据,啼笑人非! 咱们默认彩票零碎是基于统计学来实现一等奖的开奖,那么历史以来的一等奖天经地义应该是当期统计率最低的一注,所以,最开始的时候我是这么想的: 获取历史以来所有的中奖彩票号码应用代码去统计出所有号码的中奖次数依照呈现几率最低的数字来排序顺次组成某几注新号码天马行空,却也是本人发财欲望的一种发泄渠道罢了,称之为胡思乱想也不为过,扯了挺多,哈哈! 下面的思路我曾经实际过了,用了差不多一年的工夫,没有用!别用!当然你也能够试试,如果你中了,祝贺,你才是天选之人! 彩票的规定咱们这里的彩票规定对立应用「双色球」的规定来阐明,其购买的规定如下: 红球为六位,选项从 1 - 33 中筛选,不可反复蓝球为一位,选项从 1 - 16 中筛选红蓝双色球一共七位组成一注一等奖个别中全副购买的注外面筛选一注,这一注可能被多集体买,也有可能是一个人买了该注的倍数。 所以粗略统计,彩票的中奖几率计算公式如下所示: 应用组合数公式来计算,从n个元素中取k个元素的的组合数公式为: $$C\binom{k}{n}=\frac{n!}{k!(n-k)!}$$ 依据公式,咱们能够很容易的写进去一个简略的算法: function factorial(n) { if (n === 0 || n === 1) { return 1 } else { return n * factorial(n - 1) }}function combination(n, k) { return factorial(n) / (factorial(k) * factorial(n - k))}console.log(combination(33, 6) * combination(16, 1)) // 17721088所以能够得出的论断是,双色球头奖的中奖几率为:$$\frac{1}{17721088}$$ 数据量咱们通过下面的算法得悉了彩票的总注数为 17721088,那么这么多注数字组成的数据到底有多大呢? 简略计算下,一注彩票能够用14个数字来示意,如 01020304050607,那么在操作系统中,这串数字的大小为 14B,那么粗略可知的是,如果所有的彩票注数都在一个文件中,那么这个文件的大小为: ...

March 28, 2023 · 6 min · jiezi

关于javascript:IDEA-插件上新-生成接口文档就是这么快

当有接口对接需要的时候,开发终于不必再放心 API 文档难写了,也不必再一个个接口文档从新写!装置这个 IDEA 插件,能够一步将文档导入到 Postcat。这款插件操作简略,容易上手,可能让开发者省去API文档编写的工作,更专一于开发。插件通过剖析用户正文进行接口解析,最终生成接口文档并上传至 Postcat 服务器,使得开发者能够在 Postcat 上进行 API 治理和分享,进步合作能力和开发速度。 和Swagger 有什么区别呢?Postcat 插件不会入侵到代码外部,无需增加任何jar包依赖 插件通过剖析用户正文进行接口解析,最终生成接口文档并上传至 Postcat 服务器,使得开发者能够在 Postcat 上进行 API 治理和分享,进步合作能力和开发速度。 Postcat 提供了多种拓展正文,如@path、@url、@method、@name、@hidden和@required,这些正文能够在设置界面进行自定义或兼容现有正文。 此外,Postcat 还提供了正文生成性能,对于没有或仅有大量正文的类和办法,开发者无需费劲手动增加,该性能能够分析方法字段含意并主动生成正文。开发者只须要查看或依据理论场景进行微调,即可生成一份较欠缺的API文档。 如果原有正文有余,Postcat 会通过增加形式补充正文,移除正文时只会移除Postcat提供的那些拓展性正文,不会毁坏用户本身的正文。同时,开发者还能够应用"用意"性能部分生成插件正文,并进行调整和批改。 Postcat提供了多种 API 上传形式,不便开发者在不同的场景下应用: 对于首次应用Postcat的现有我的项目,开发者能够应用主菜单中Tools分组下的Upload Project Api Doc来实现我的项目级别的接口上传。对于新需要下创立的Controller,在实现接口定义后,开发者能够右键菜单,抉择 Upload All Api 来进行单个文件级别全副上传,做到先有文档再有逻辑,前后端工作不再串行阻塞。对于某个局部独自接口的改变,无需全副上传,开发者能够右键菜单,抉择Upload Api性能,该性能会展现以后编辑类的接口信息,并提供接口预览和接口抉择界面,使得用户能够勾选须要更新或上传的指标API进行信息核查和上传。如何装置配置?IDEA 版本需大于 IntelliJ IDEA 2022.03在 IDEA “设置-插件-Marketplace” 中搜寻 Postcat,找到 Postcat 插件装置即可。同时也可在IDEA插件市场上进行下载安装,本地的IDEA没有主动唤起时,能够间接把zip包拖入IDEA中即可实现装置/更新。 1. 填写配置信息首次上传须要填写配置信息,配置信息我的项目之间独立。配置信息获取路径:登陆 Postcat 进入我的项目中获取 Token、WorkspaceID 和 ProjectID。 Server 默认填写:https://postcat.com/api, 用户无需批改Token获取 WorkspaceID 和 ProjectID 获取 进入我的项目设置页面,点击我的项目名右侧“问号” StringType 决定出入参的字符串类型,只有参数名一开始就是恪守驼峰标准才会发现扭转,预览窗口可看到变动后果 当参数名为userInfo,抉择 camelCase,仍旧是userInfo,这是默认选项当参数名为userInfo,抉择 lower_underscore,会变成user_info当参数名为userInfo,抉择 UPPER_UNDERSCORE,会变成USER_INFO ...

March 28, 2023 · 1 min · jiezi

关于javascript:Microsoft-Flow-微信-LDP-整合开发

咱们在应用本人的企业应用平台时,常常会遇到以下场景: 场景1 业务零碎的告诉太多,心愿收到告诉时同步发送企业微信来随时查看。 场景2 须要和其余ERP、BI、CRM等零碎对接。 通常的解决方案是自行开发一套程序来实现平台到微信的同步性能。 如果这样做,咱们就须要域名空间,要学会搭建web服务器,要github备份保护代码,要当心破绽被攻打,要编写简单的代码。(以下将以kintone平台为例进行阐明) 然而我只想实现一个小小的微信揭示性能,却受到了这么大的束缚!那是否有能够不须要服务器,不须要编写很多代码的实现办法呢? 其实简略的利用好收费的Microsoft Flow,就能实现这些性能,而且根本不须要编码能力。(具体Microsoft Flow是什么,小伙伴们能够自行去百度下哦。) 一、Microsoft Flow 如何分割起kintone和企业微信?Microsoft Flow利用webhook将kintone和微信等其余第三方利用联合起来。 Webhook:是用户定义的一种HTTP回调,它通常由某些事件触发,而后向其指定的webhook站点收回HTTP申请。 能够通过以下这张图直观的理解这个实现过程: 那就让咱们来一步一步实现这一性能吧。 二、微信篇1、创立一个自建利用首先在企业微信上创立一个利用接管来自kintone的告诉。具体创立过程,能够参见企业微信阐明。 微信发送信息的流程: 获取access_token 利用access_token调用发送微信api 2、获取access_token申请形式:GET 申请地址:https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpse... 3、利用access_token调用发送微信api申请形式:POST(HTTPS)申请地址:https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token... 申请内容: {   "touser" : "@@all",   "msgtype" : "text",   "agentid" : 1000002,   "text" : {         "content " : "增加记录胜利"   },   "safe":0}所有微信API文档请参见微信官网:文档 - 企业微信开发者核心 三、Microsoft Flow篇kintone => Microsoft Flow => 微信 流程图 1、增加kintone到Microsoft Flow 触发器点击“从空白创立”。增加[申请]触发器 申请注释JSON架构: {     "type": "object",        "properties": {               "type": {                        "type": "string"                },                "app": {                        "type": "object",                        "properties": {                                "id": {                                        "type": "string"                                },                               "name": {                                       "type": "string"                               }                        }                },                "recordTitle": {                        "type": "string"                 },                 "url": {                         "type": "string"                 }        }}在高级选项中,抉择[method]为POST 2、增加微信api的连接器 -- 获取access_token接下来再增加一个HTTP的连接器设置[办法]:GET 设置Uri:https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpse... (其中ID和SECRECT请应用理论申请的企业微信的corpid和corpsercret) 3、增加微信发送信息的连接器接着再增加一个HTTP的连接器 办法:POST Uri:https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token... 这里access_token的值设置为之前那个HTTP连接器获取到的动静内容。 查阅Microsoft Flow 官网api能够得出:actions('HTTP')'outputs'['access_token']注释: {   "touser" : "@@all",   "msgtype" : "text",   "agentid" : 1000002,   "text" : {         "content " : "增加记录胜利"   },   "safe":0}touser 设置为所有人,agentid 为之前利用的agentid 4、生成webhook申请步骤实现,保留下。再把画面迁徙到最开始的那个触发器(当收到HTTP申请时), 这时候那个HTTP POST URL就曾经生成好了,点击复制URL,这就是咱们的webhook地址。 5、kintone端增加webhook在kintone的利用的设置界面点击Webhook,粘贴方才的webhook申请地址(请删除复制后果后面的https://),勾选须要执行webhook的发送告诉条件,并且启用它。 最初别忘了更新利用能力失效哦! 四、验证好了,咱们曾经实现了所有设置,增加一个利用数据来看看是否发送到企业微信上吧! 想尝试一下吗?快来注册账号体验:开发者账号收费申请

March 27, 2023 · 1 min · jiezi

关于javascript:h3c无线网web端自动登录

h3c无线网web端主动登录背景公司的无线网应用h3c进行web端验证登录,须要两个步骤: 先手动将windows的无线网连上(无需明码,此时无奈上网)在浏览器中关上h3c的登录页面,输出账号密码进行验证登录 注:本文只实用上述登录页面截图的解决痛点每次早上都是反复这样的步骤开机启动的软件(钉钉、微信、qq等)因为没有网路导致登陆失败,还须要从新登录预期每天早上开机之后,可能主动实现上述步骤,即: 主动连上windows的无线网主动实现浏览器中的h3c登录钉钉、qq等须要网络的app,能够胜利登录源码地址源码地址 疾速开始环境要求nodejs // 版本无要求yarngit(如抉择间接下载压缩包,则无需git)下载源码(二选一)下载压缩包并解压到本地git clone装置依赖yarn须要提前装置yarn批改 config.js 信息,依据理论状况批改{ // windows连贯的无线网名称 "wifiName": "Guest", // 浏览器登录的地址 "webLoginAddress": "http://172.30.1.1/portal/", // 账户 "user": "guest", // 明码 "password": "guest123"}注册 h3c 指令npm link应用h3c关上控制台,测试是否能够主动连贯并登录至此,曾经能够通过在cmd中通过全局指令 h3c 来实现主动登录 接下来,只有让windows启动后,主动执行该指令即可 开机主动运行脚本步骤:关上控制面板 - 管理工具 - 工作打算程序 右侧操作 - 创立工作惯例: 触发器: 操作: 点击确定,实现。相干问题app开机启动设置,在对应app的设置中自行设置即可上述开机运行的脚本,会在app自启动之前执行,因而能够胜利登录须要网络的app偶尔的开机无奈主动执行脚本的状况 偶发状况。测试发现多发于周末后的周一开机(思考是否因为长时间未开机的起因,后续会持续排查)若呈现上述情况,重启即可

March 27, 2023 · 1 min · jiezi

关于javascript:书籍推荐Modern-CMake-for-C中文版英文版

编辑:一点人工一点智能原文:书籍举荐-《Modern CMake for C++》中文版&英文版书籍:Modern CMake for C++(中文版&英文版)作者:Rafał Świdziński 译者:陈晓伟出版:Packt编辑:东岸因为@一点人工一点智能 01  书籍介绍发明优良的软件并非易事。开发人员常常会遇到无奈确定哪些倡议是最新的,以及哪些办法曾经有更新或更好的实际的问题。同时,大多数资源在没有交代背景、上下文和构造的状况下,解释起来也很难。本书提供了全面构建 C++ 的端到端解决方案,提供了更简略的办法。理解如何应用 CMake,如何使其可保护、优雅和洁净。将应用自动化的形式帮忙您实现我的项目中呈现的许多简单工作,比方构建、测试和打包。本书会领导您如何生成源目录,以及如何构建指标和包。随着学习的深刻,将理解如何编译和链接可执行文件和库,以及如何优化各种步骤以获得最佳后果。还将理解如何向我的项目增加内部依赖项:第三方库、测试框架、程序剖析工具和文档生成器。最初,导出外部和内部指标,以及装置和打包的解决方案。浏览完本书后,置信您就可能在十分业余地应用 CMake 了。 02  合适读者这本书是为具备 C/C++ 编程常识的工程师和软件开发人员所著,从而能够学习 CMake,以理解自动化构建小型和大型软件的解决方案。若刚开始应用 CMake,并长期应用GNU Make,或者只是想温习一下最新的最佳实际,那么本书也非常适合您。 03  作者介绍Rafał Świdziński 在Google公司负责工程师,具备超过10年业余教训的全栈开发人员,理解大量的编程语言和技术,始终在本人的公司和包含Cisco Meraki、Amazon和Ericsson在内的公司开发软件。他来自波兰的罗兹 (Łódź),当初生存在英国伦敦,在那里经营一个YouTube 频道“Smok”,探讨与软件开发相干的话题。他很喜爱解决技术问题,包含该畛域的挑战。在工作中,他理解各种技术概念,并揭开了软件工程师角色背地的艺术和迷信的神秘面纱。他次要关注代码品质和编程技巧。 04  本书内容第1章,初识 CMake,如何装置和应用 CMake 命令行,以及如何创立相应的我的项目文件。第2章,CMake 语法,介绍了要害的代码信息:正文、命令调用和参数、变量、列表和控制结构。第3章,CMake 我的项目,介绍了我的项目的根本配置、所需的 CMake 版本、我的项目元数据、文件构造,以及如何设置工具链。第4章,应用指标,为可执行程序和库生成构建指标。第5章,CMake 编译 C++,编译过程的工作形式,以及如何在 CMake 我的项目中进行管制。第6章,进行链接,对于链接、动态和动静库。解释了如何构建一个我的项目,以便对其进行测试。第7章,治理依赖关系,古代 CMake 中治理依赖关系的办法。第8章,测试框架,如何将测试框架增加到我的项目中,以及如何应用 CMake 提供的 CTest。第9章,剖析工具,如何在我的项目中主动格式化,以及如何进行动态和动态分析。第10章,生成文档,如何应用 Doxygen 依据 C++ 源代码生成手册。第11章,装置和打包,展现如何筹备将我的项目用于其余我的项目或装置到零碎上,还有如何应用Pack。第12章,创立残缺的我的项目,如何将理解的所有常识整合到一个残缺的我的项目中。附录:其它指令,提供了相应指令的疾速援用:string()、 list ()、 file() 和 math()1、 书籍举荐-《简单地形中,SLAM技术在移动机器人中的利用》2、 书籍举荐-《基于多视图几何的机器人零碎视觉感知与管制》3、 书籍举荐-《多无人机布局和任务分配》4、 书籍举荐-《平面视觉物体检测》5、 书籍举荐-《TinyML教程》

March 27, 2023 · 1 min · jiezi

关于javascript:定时长关机-tcc

定时(长)关机 - tcctcctimed-close-computer背景预约某个工夫,windows自动关机预约多长时间之后,windows自动关机快捷关机针对以上三个问题,windows并未提供便捷的、疾速的形式来供咱们应用。疾速开始环境nodejs仓库地址源码地址 下载我的项目到本地间接下载压缩包,并解压到本地应用 gitgit clone装置yarn提前装置yarn增加npm全局软连贯npm link以便可能在windows全局应用形式一:菜单抉择tcc进入菜单选项,如图: 形式二:快捷操作(举荐)tcc [arg]启动参数阐明: 立刻关机tcc 0固定工夫关机tcc [HH:mm]工夫格局为:HH:mm示例:tcc 18:00,即:固定工夫18:00:00关机 固定时长关机tcc [规范工夫格局]规范时长格局:数字+h|m|s即:h-小时,m-分钟,s-秒示例:tcc 2h,即:2小时后关机;tcc 2m,即:2分钟后关机;tcc 2s,即:2秒后关机; 勾销定时(长)关机tcc -1如何优雅地全局疾速应用快捷键:ctrl + r,唤出: 间接在此处输出tcc的脚本命令,既可执行 疾速关机因为该窗口会记录上一次的脚本命令,只须要之前输出过一次 tcc 0 (立刻关机脚本) 下次再关机,只须要: ctr + r,回车 即可实现疾速关机。

March 27, 2023 · 1 min · jiezi

关于javascript:可视化搭建-keepAlive-模式

因为 React 的特点,组件扭转所在父级后会产生 Remount,而在可视化搭建场景存在两个特点: 自在、磁贴、流式布局都能够通过拖拽轻松扭转组件父元素。大数据量下组件 Remount 的耗费不容忽视。联合下面两个特点,拖拽过程中或者松手时不可避免会产生卡顿,这就是咱们这篇文章要解决的问题。 利用 createPortal 解决 Remount 问题createPortal 能够将 React 实例渲染到任意指定 DOM 上,所以咱们利用这个 API,将组件树的组件打平,但通过 createPortal 生成到嵌套的 DOM 树上,就同时实现了以下两点: 在 dom 构造上仍然合乎组件树的嵌套形容。在 React 实例角度,没有嵌套关系。实现分为三步: 遍历组件树,依据组件树嵌套构造生成 createPortal 的指标 dom,咱们权且称为 keepElement,对须要挂载 keepElement 的容器地位生成 dom,称为 keepContainer。对于没有渲染的容器,能够先不挂载 keepElement,而是等到父容器 mount 后再将 keepElement 移过去,前面再开展阐明。遍历组件树,一次性打平渲染所有树中 React 组件实例,并利用 createPortal 挂载到对应的 keepElement 上。当数据流产生变动导致父级变动,或者布局插件拖动扭转父级时,咱们仅利用 dom api 将 keepElement 在不同的 keepContainer 之间挪动,而在 React 实例视角没有产生任何变动。<img width=500 src="https://s1.ax1x.com/2023/03/25/ppDLFSO.png"> 协定做到用户无感知因为实现了 dom 构造与 React 实例构造拆散,因而开启 keepAlive 模式不须要扭转 componentTree 形容,也不会影响任何逻辑性能,咱们只须要标记一下 keepAlive 参数即可开启: import { createDesigner } from 'designer'const { Designer, Canvas, useDesigner } = createDesigner()const App = () => { <Designer keepAlive={true} />}渲染减少了额定 dom 嵌套keepAlive 模式惟一对性能产生的影响是减少了额定 dom 嵌套,别离是 keepContainer 与 keepElement,产生这两层 dom 的起因别离是: ...

March 27, 2023 · 1 min · jiezi

关于javascript:什么是-Spartacus-Custom-Config-initializer

SAP Spartacus是一个用古代Web技术(如Angular、TypeScript和Node.js)构建的开源店面,用于SAP Commerce Cloud(以前称为SAP Hybris),它提供了一组性能和组件,可用于构建响应式和可扩大的电子商务应用程序。 SAP Spartacus Custom Config initializer 是一个配置实用程序,它容许开发人员通过提供一组配置选项来自定义Spartacus店面的行为和外观。它容许开发人员笼罩默认配置并增加各种Spartacus性能的自定义配置,例如身份验证、购物车、产品和结账。 Custom Config initializer 是一个TypeScript模块,能够导入到应用程序中并用于配置Spartacus店面。该模块蕴含一组配置接口和函数,可用于自定义Spartacus的行为。 应用自定义配置初始化器能够实现的一些自定义示例包含更改默认主题、将自定义组件增加到店面中、配置付款和配送形式以及与第三方服务集成。 看个具体的例子。 以下是一个应用SAP Spartacus Custom Config Initializer自定义Spartacus身份验证流程的示例代码: 创立一个新的TypeScript文件,例如custom-auth.config.ts。在该文件中导入Spartacus Custom Config Initializer模块: import { ConfigInitializer } from '@spartacus/core';创立一个名为CustomAuthConfigInitializer的类并实现ConfigInitializer接口。在该类中实现自定义身份验证流程的逻辑。export class CustomAuthConfigInitializer implements ConfigInitializer { initialize(): Promise<any> { // 在此处实现自定义身份验证逻辑 return Promise.resolve(); }}在initialize办法中实现自定义身份验证逻辑,例如替换默认的登录页面,如下所示:import { Injectable } from '@angular/core';import { ConfigInitializer, AuthConfig } from '@spartacus/core';@Injectable()export class CustomAuthConfigInitializer implements ConfigInitializer { constructor(private authConfig: AuthConfig) {} initialize(): Promise<any> { // 替换默认的登录页面 this.authConfig.login = { components: { LoginPageComponent: 'app-custom-login-page' } }; return Promise.resolve(); }}最初,在app.module.ts中将CustomAuthConfigInitializer增加到providers数组中,如下所示: ...

March 26, 2023 · 1 min · jiezi

关于javascript:什么是-Web-应用里加载-google-font-带来的-FOIT-和-FOUT-问题

在 Web 利用中,当你应用 Google Fonts 或其余字体资源时,能够通过增加 &display=swap 参数来实现 FOIT(Flash of Invisible Text)和 FOUT(Flash of Unstyled Text)的优化。 当 Web 利用在加载 Google 字体时,可能会遇到 FOIT(Flash Of Invisible Text)和 FOUT(Flash Of Unstyled Text)问题。 FOIT 意味着在页面加载 Google 字体之前,文本内容是不可见的,这通常产生在字体文件下载时。如果字体文件下载速度较慢或不可用,用户将看到无字体的页面,直到字体文件下载实现为止。 FOUT 意味着在 Google 字体加载完之前,浏览器应用了默认字体渲染文本。一旦字体加载实现,文本会忽然扭转款式,从默认字体切换到 Google 字体。 这些问题通常能够通过应用适当的 CSS 和 JavaScript 技术来解决,例如应用 Web Font Loader 等库来管制字体加载过程,或者应用内联字体来防止字体文件的网络申请。 在默认状况下,浏览器会在字体加载实现之前应用备用字体来展现文本内容,这可能会导致 FOIT 或 FOUT 的问题。而增加 &display=swap 参数能够让浏览器在字体加载实现之前先展现备用字体,而后再切换到正确的字体,从而防止 FOIT 或 FOUT 的问题。 通过增加 &display=swap 参数,字体资源会在后盾加载,而不会阻塞主线程的渲染,这有助于进步页面加载速度和性能。 Web Font Loader是一个JavaScript库,用于在网页加载期间异步加载和治理Web字体。Web字体是自定义字体,能够在网页中应用,这些字体不是装置在用户计算机上的规范零碎字体。 Web Font Loader提供了一种办法,能够在网页加载过程中异步加载Web字体,这样能够更好地管制字体的出现和渲染,进步网站的性能和可拜访性。它还提供了一些附加性能,如检测字体加载状态和解决加载失败的状况。 Web Font Loader反对各种Web字体加载服务和格局,包含Google Fonts、Typekit、Webtype和Fontdeck。它是一个开源我的项目,能够通过GitHub获取代码并集成到您的网站中。 ...

March 26, 2023 · 1 min · jiezi

关于javascript:JS中undefined和null的区别

JavaScript 真是一个非凡的语言, 其余语言都只有一个示意 "无" 的值, 比方 Java 语言用的是 null, C 语言用的是 NULL, Python 语言用的是 None, Ruby 语言用的是 nil。只有 JS 外面示意 "空" 的有两个, 一个是 undefined, 一个是 null。 很多敌人在刚开始学习的时候, 都会有一个疑难, 就是 undefined 和 null 二者之间有什么区别呢 ? 我什么时候该用什么呢 ?接下来, 咱们就来好好聊一聊! JS的根本数据类型在 JS 内, 有几个根本数据类型 ES5Number 数值 String 字符串 Boolean 布尔 Undefined 空 Null 空 ES6Symbel 惟一值 undefined 和 null 其实就是 JS 中的根本数据类型, 空类型 从这个角度来看, 他们两个是一样的, 都示意 空 的意思,并且在进行数据类型比拟的时候, 某些状况下也是一样的 console.log(undefined == null) // true两者的区别两者的区别还是在于含意,之前咱们说过, 所有的数据在计算机都是以二进制模式存储的,那么这两个数据也是会依照二进制模式存储的 ...

March 24, 2023 · 1 min · jiezi

关于javascript:用Javascript写一个根据MacBook触控板手势缩放或移动的页面元素

以挪动一个SVG图形为例,残缺代码如下: <!doctype html><html> <head> <style>body { margin: 0;}/* 最外层容器 */#content { /* 阻止页面大小随着SVG挪动而变动 */ overflow: hidden;}/* 固定Header */#header { left: 0; right: 0; position: fixed; height: 50px!important; background-color: rgb(124, 252, 45); z-index: 10;}/* 包容须要追随手势挪动的SVG的容器 */#panel_container { height: 100vh; z-index: 5; background-color: rgb(248, 213, 98);}/* 固定Footer */#footer { left: 0; right: 0; bottom: 0; position: fixed; height: 50px!important; background-color: rgb(124, 252, 45); z-index: 10;}/* 须要追随手势挪动的SVG */svg { background-color: rgb(250, 250, 153); width: 100%; height: 100%;} </style> <script>// 须要追随手势挪动的SVG。页面加载后赋值var svg = null;// 用户操作后冀望的SVG缩放比例var scale = 1;// 用户操作后冀望的SVG中心点的横向偏移var posX = 0;// 用户操作后冀望的SVG中心点的纵向偏移var posY = 0;// 咱们不心愿SVG比例过小或偏出屏幕,所以在SVG被挪动或缩放到合乎用户冀望的比例和地位后,还须要让SVG回弹到以下合乎咱们冀望的比例和地位// 通过修改后的SVG缩放比例var finalScale = 1;// 通过修改后的SVG中心点的横向偏移var finalPosX = 0;// 通过修改后的SVG中心点的纵向偏移var finalPosY = 0;// 上次依据用户操作进行渲染的工夫戳。每次执行render()时被设置。用户的操作优先于零碎的回弹修改,所以只有以后工夫间隔该工夫戳曾经过来了一段时间(200毫秒)后,咱们才能够开始对SVG进行回弹修改。详见bounce()var lastRenderingTime;// 监听页面加载实现事件。为SVG加点元素以便地位参考window.addEventListener("load", function() { svg = document.querySelector("svg"); // 简略加一个小方块 let newRect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); newRect.setAttribute("x", "150"); newRect.setAttribute("y", "150"); newRect.setAttribute("width", "100"); newRect.setAttribute("height", "100"); newRect.setAttribute("fill", "#5cceee"); svg.appendChild(newRect);});// 依据用户的操作进行渲染var render = () => { // 更新渲染的工夫戳 lastRenderingTime = new Date().getTime(); window.requestAnimationFrame(() => { // 依据新的地位和缩放比例渲染SVG svg.style.transform = `translate3D(${posX}px, ${posY}px, 0px) scale(${scale})`; // 如果不想要回弹成果,以下代码能够去掉 // 让零碎稍后尝试回弹修改(有必要的话) setTimeout(bounce, 500); });};// 如果不想要回弹成果,以下bounce()代码能够去掉// 依据修改值回弹修改SVGvar bounce = () => { // 用户操作后的缩放和地位没有问题,用户冀望与零碎冀望雷同,间接返回 if (scale == finalScale && posX == finalPosX && posY == finalPosY) return; // 用户可能还在操作中,按优先级规定不进行零碎操作,而是期待片刻再尝试 if (new Date().getTime() - lastRenderingTime < 200) { // 期待500毫秒 setTimeout(bounce, 500); // 返回 return; } // 包容SVG的容器。联合SVG和包容SVG的容器的绝对地位和大小来计算回弹量 var ref = document.getElementById("panel_container").getBoundingClientRect(); // SVG以后的缩放比例 var lastScale = svg.getBoundingClientRect().width / ref.width; // SVG以后的中心点横向偏移 var lastPosX = svg.getBoundingClientRect().x + svg.getBoundingClientRect().width / 2 - ref.width / 2; // SVG以后的中心点纵向偏移 var lastPosY = svg.getBoundingClientRect().y + svg.getBoundingClientRect().height / 2 - ref.height / 2; // 该次回弹的指标比例。与最终修改值差距过小则间接置为最终修改值 var stepScale = Math.abs(finalScale - lastScale) > 0.1 ? (lastScale + Math.sign(finalScale - lastScale) * 0.1) : finalScale; // 该次回弹的指标中心点横向偏移。与最终修改值差距过小则间接置为最终修改值 var stepPosX = Math.abs(finalPosX - lastPosX) > 10 ? (lastPosX + (finalPosX - lastPosX) / 10 + Math.sign(finalPosX - lastPosX) * 10) : finalPosX; // 该次回弹的指标中心点纵向偏移。与最终修改值差距过小则间接置为最终修改值 var stepPosY = Math.abs(finalPosY - lastPosY) > 10 ? (lastPosY + (finalPosY - lastPosY) / 10 + Math.sign(finalPosY - lastPosY) * 10) : finalPosY; window.requestAnimationFrame(() => { // 依据指标地位和缩放比例渲染SVG svg.style.transform = `translate3D(${stepPosX}px, ${stepPosY}px, 0px) scale(${stepScale})`; }); // 如果曾经修改实现则返回 if (stepScale == finalScale && stepPosX == finalPosX && stepPosY == finalPosY) return; // 持续尝试进行下一次修改 setTimeout(bounce, 500);};// 监听触控板手势事件。理论为鼠标滚轮事件window.addEventListener('wheel', (e) => { // 包容SVG的容器。联合SVG和包容SVG的容器的绝对地位和大小来计算修改值 var ref = document.getElementById("panel_container").getBoundingClientRect(); // SVG以后的缩放比例 var lastScale = svg.getBoundingClientRect().width / ref.width; // SVG以后的中心点横向偏移 var lastPosX = svg.getBoundingClientRect().x + svg.getBoundingClientRect().width / 2 - ref.width / 2; // SVG以后的中心点纵向偏移 var lastPosY = svg.getBoundingClientRect().y + svg.getBoundingClientRect().height / 2 - ref.height / 2; if (e.ctrlKey) { // 缩放事件 // 依据操作确定缩放值。地位不变 finalScale = scale = lastScale - e.deltaY * 0.01; finalPosX = posX = lastPosX; finalPosY = posY = lastPosY; } else { // 挪动事件 // 依据操作确定地位。缩放值不变 finalScale = scale = lastScale; finalPosX = posX = lastPosX - e.deltaX * 2; finalPosY = posY = lastPosY - e.deltaY * 2; } // 如果不想要回弹成果,以下对finalXXX的赋值能够间接批改为对XXX的赋值 // 不容许SVG过小(缩放值小于1) if (scale < 1) finalScale = 1; // 不容许SVG右边界进入屏幕内 var minPosX = ref.width / 2 - ref.width * finalScale / 2; // 不容许SVG左边界进入屏幕内 var maxPosX = ref.width * finalScale / 2 - ref.width / 2; // 不容许SVG下边界进入屏幕内 var minPosY = ref.height / 2 - ref.height * finalScale / 2; // 不容许SVG上边界进入屏幕内 var maxPosY = ref.height * finalScale / 2 - ref.height / 2; // 依据以上限度值确定零碎最终修改值 if (posX < minPosX) finalPosX = minPosX; if (posX > maxPosX) finalPosX = maxPosX; if (posY < minPosY) finalPosY = minPosY; if (posY > maxPosY) finalPosY = maxPosY; // 依据用户操作进行渲染 render();}); </script> </head> <body> <!-- 最外层容器 --> <div id='content'> <!-- 搁置一个固定Header为肉眼察看位移作参考 --> <div id='header'> Header </div> <!-- 包容须要追随手势挪动的SVG的容器 --> <div id='panel_container'> <!-- 须要追随手势挪动的SVG --> <svg></svg> </div> <!-- 搁置一个固定Footer为肉眼察看位移作参考 --> <div id='footer'> Footer </div> </div> </body></html>

March 24, 2023 · 3 min · jiezi

关于javascript:微信小程序原生AI运动动作检测识别解决方案

前几年受疫情影响,人员流动受限,反而让“AI静止”概念风行一时、空前火爆。目前曾经在AI静止锤炼、体育教学、线上静止主题流动等场景中,胜利失去了利用,并取得了宽广互联网用户的认可。一、AI静止锤炼足不出户,只需一部手机和家中几平方米的场地,也能确保锤炼达到可计数、计时、可纠正的成果,成了宅家一族的衰弱锤炼助理。 二、体育教学辅导随着基础教育,对体育教学的器重水平越来越高,为了监督学生在家的锤炼状况,很多学校也利用AI静止辨认技术,将学生的静止打卡搬上手机,进行云辅导。 三、云上主题静止流动全民健步走,是前些年异样炽热的线上主题流动,通过AI静止辨认技术,当初能够发展如:跳绳、开合跳、平板撑、仰卧起坐、俯卧撑、深蹲、马步蹲等模式更多样的云上健身被动流动,还能够主动生成排行榜。适宜单位发展“全民健身”、“团队健身”等被动流动。 尽管AI静止概率异样炽热,然而受小程序框架的制约,要想把AI静止辨认搬上小程序,却难度不小。间接调用第三方静止辨认API服务,老本高、即时性差;应用本地抽帧+后盾辨认的计划,老本稍低,但完整性、即时性较差。 针对以上状况,通过咱们的技术团队致力及一直偿试,咱们把一套精简的人体辨认深度学习模型搬上了微信小程序,并联合咱们基于规定配置的静止辨认计算引擎,能够轻松实现跳绳、开合跳、平板撑、俯卧撑、仰卧撑等多种静止的辨认。计划具备以下特点: 一、老本破费低通过咱们的比对测试,大部分第三方静止辨认、人体辨认API服务,都是按秒数或图片帧数计费, 以时长5分钟左右的静止锤炼视频,辨认大概要花费0.5元-1元之间,如此昂扬的老本,对于个别利用难于接受。而咱们的计划,每应 用只有一次性收取几千元的受权费即可,再无其它破费。 二、易于集成本计划以微信小程序插件的模式公布,开箱即用;为了缩小您开发团队的开发成本,咱们还为您封装了摄像头取像、人体骨骼绘制等性能,您只有专一于UI开发即可。 三、易于扩大咱们的计划中,带有静止辨认规定计算引擎,您只需依照文档阐明,简略的配置规定即可实现一种新的静止辨认,还能够将配置规定JSON化,搁置于服务端,实现静止辨认可配置化。

March 23, 2023 · 1 min · jiezi

关于javascript:为了开放互联明道云做了十件事

本文来自明道云资深研发经理孙伟,在明道云2022年秋季搭档大会流动演讲,经校对编辑后整顿为演讲精髓。 一、凋谢没有抉择很多客户抉择咱们的一个重要起因,是明道云所能提供的产品凋谢能力。凋谢其实是没有抉择的,坦率来讲,我也不心愿凋谢,我心愿客户所有的业务零碎都用明道云治理,这样对咱们是更无利的。然而,事实中因为企业业务的多样性与复杂性,没有任何一家平台能够做到一站式解决所有问题。为了不便客户,咱们就必须凋谢本人,让客户用得更好。 1.一个典型的业务场景须要多少个零碎? 咱们先来看一个典型的业务场景。一个客户从网站高低了一个订单,经销商收到订单之后去向企业订货。企业订货之后如果本身不进行生产,就须要向供应商洽购。供应商生产好之后,须要去找物流公司发货。发货实现,客户最初进行收货。这样一个企业日常常常波及到的环节,会须要用到哪些零碎?从下单开始,可能须要有一个电商平台,比方京东、天猫;也有一些客户是自营的,会应用一些小程序,会波及到领取零碎。还会波及到业务管理,应用CRM、ERP等管理系统。如果他是分销商体系,还要有分销零碎。如果是工厂还会波及到MES零碎、物流管理系统等。这么多零碎,让一家企业来实现是不太事实的,并且如果两头任何一个环节不能与其余零碎敌对互通,客户可能就不会抉择你了。 2.明道云为什么须要凋谢?如果不思考交互能力,实践上来阐明道云是能够搭建任何一套业务零碎的。然而,咱们的客户有很多个性化需要,让咱们必须抉择凋谢。 非凡交互。有一些客户对前端的界面排版、交互有特殊要求,这个时候用明道云来实现,就不太敌对。系统集成。一些客户曾经应用了电商平台现有的外围零碎很多年了,他不太可能立马把零碎都迁徙到明道云,然而却须要明道云跟原有的零碎互通,进行一些数据流转。运算逻辑极其简单。比方股票基金的净值运算,它是要去收集大量的历史数据,做很多的解决;还有比方大规模的数据分析,这种TB级别的明道云自身是不善于解决的。其余需要。比方同步一些物流信息、海关数据、企业工商信息,在线签约等。这些场景用明道自身来做就不太适合,咱们不能敌对实现这些客户需要,所以咱们只能抉择凋谢本人,交给别的产品来实现。 二、明道云做了哪些事件大家一起看一下,明道云为了平台开放性做了哪些工作。 1.开放平台 它其实是明道老的合作模块的产物。因为明道云是一个企业合作的平台,反对用户或者是第三方开发者进入明道云的开放平台,去设计开发一些扩大利用,而后上架到明道云的利用市场,进行推广并取得额定的支出。当然,这里的扩大利用不是指咱们当初用明道云搭建的利用。 最典型的是第三方的SaaS与明道云的联合,它是基于Auth2.0受权机制,通过账号密码登录后拿到token,再去获取一些数据。这里次要就是老合作模块,比方动静、工作、日程、群组;另外还有组织与账户。比方,我拿到账户信息以及用户退出的网络信息后,对网络下的用户做音讯的推送集成性能。 当然,当初明道云的产品路线图里也有集成核心、开发者核心,并且未来可能会交融在一起,打造一个全新的明道云开放平台。2.企业受权凋谢接口 咱们后面讲的开放平台是基于集体受权,所有数据都是用户本人的;而企业的受权凋谢接口是独立于明道云集体的受权API。将来,这两套体系会共存。 这套受权体系齐全服务于企业相干的数据接口,有较高的权限级别,当初这套密钥只有网络管理员在后盾才能够看到,次要内容包含三大块: 审批。明道云现有的审批能够通过这一套体系在线创立审批,获取审批列表,为每个审批配置一个Webhook告诉节点。当明道云的审批有任何的变动,它能够把变动告诉到内部的零碎。组织架构。又分为四项:用户、部门、职位、汇报关系。咱们通过这些接口,与内部第三方平台做账号集成,次要用于数据的增删查改,包含与第三方已有的相似数据的关联解决。利用治理。利用指明道云中搭建的利用。咱们能够在线创立利用,并获取利用上面的受权信息。3.利用OpenAPI每创立一个利用,明道云都会主动为它生成一套API示范模板。利用管理员能够看到利用的API开发文档,外面涵盖了白名单、受权治理、受权密钥。它也是非集体的,只有是利用下的数据,全副能够获取到,然而权限分为了全副权限和只读权限。只读权限就是指能够凋谢给第三方来调数据,然而不容许他进行编辑删除。除了受权之外,外围的性能还有什么?第一,组织架构,咱们能够通过利用的受权信息获取利用的组织构造,包含菜单项、工作表,获取工作表的构造信息,包含一些控件列表。其次就是利用数据,咱们能够对于利用数据做增删查改。还有一个大块是利用权限体系,咱们能够通过这一套API,去对利用下的角色做一些解决。4.工作流Webhook 后面讲的这些,开放平台也好,API也好,都须要第三方零碎。然而有的时候,咱们并不需要挂第三方零碎,而想要用无代码的形式与内部零碎做比拟好的联合。那么,明道云工作流就反对用Webhook与内部互通,它次要分两种形式:Webhook节点和API申请节点。 Webhook节点会主动生成一个URL链接,被动地接管内部音讯的申请。咱们晓得,数据同步个别分两种,一种是这种传统的集成,定时地批量同步;还有一种音讯集成模块,遵循IFTTT模式进行实时同步。比方我在另一个平台外面做了一个实时的操作,假如这个平台也是反对音讯推送的,它就能够往Webhook节点推一条音讯告诉。明道云拿到之后就能够去实时获取信息,不须要每过一段时间再去拉取它。 API申请节点以前也叫Webhook节点,前面因为咱们做了集成核心,所以才改成了API申请节点。明道云外部的一些事件触发或者是定时工作,就能够去申请内部地址。这个申请能够是获取数据,也能够是把明道云的数据推送给里面。5.工作流代码块工作流Webhook是基于HTTP的,然而事实中有一些传统的零碎,或者一些比拟非凡的零碎,它的受权模式比较复杂,所以咱们针对有开发能力的这部分客户做了一些比拟深刻的能力,就是工作流中的代码块节点。 它次要有两种开语言:Javascript和Python。Node.js和Python有些版本会援用一些包,比方有一些简单的受权模式,通过API的形式不可能间接对接,那咱们就能够通过代码块,自行援用。咱们去做一些申请的时候常常须要前置解决申请参数,比方拿到参数之后须要对返回的数据做一些预处理。 如果咱们通过现有的工作流节点去解决它,就会比拟麻烦。但有了代码块,咱们就能够在申请前先对申请参数做优化,拿到申请后果之后再做格式化解决返回给前端,这样就会绝对敌对一些。6.集成核心当初的集成核心能够封装一组受权认证,包含一个API的接口组,很不便地供企业外部甚至内部用户去调用,咱们当初曾经预置了天眼查、小鹅通、易签宝等等这些接口。后面咱们提到的客户有在线签单的要求,明道云自身做不到,然而如果咱们和e签宝单干,就能够通过明道云的一个节点,疾速实现这些操作。7.工作表/自定义页面 API查问控件。后面咱们提到的Webhook和集成核心,他们的流程都是有滞后性的,以前没有API查问控件的时候是怎么解决的?解决流程个别是这样的:记录创立或者更新之后,主动触发一个工作流,工作流再去做一些逻辑,最初将后果更新到工作表中。这种做法后果不是实时反馈的,所以咱们推出了工作表控件API查问,它容许在界面上间接地调用第三方的接口,在界面上实时反馈,它也是一个按钮,点击查问之后把数据实时地出现到页面上来。嵌入控件。工作表和自定义页面都有嵌入控件,明道云现有的控件可能不能满足一些客户的需要,那客户就能够本人开发一些控件,通过嵌入控件嵌在明道云中,做好单点登录、账号集成,这样就能够实现自定义控件的能力。自在连贯控件。这个控件可能用的人不是很多,它次要是连贯明道云的老合作模块,包含动静、工作等。比方一条工作表记录跟一个日程或者工作无关,咱们就能够把它关联过去。文本辨认。自带的能力次要是身份证跟一些发票的辨认。因为有了咱们API能力,其实咱们能够本人去扩大更多的OCR辨认能力。8.公开表单、内部门户和分享公开表单事实中咱们有很多的需要是不须要有状态的,只是须要收集一些内部数据。比方政府单位做民意调查,或者咱们明道云的搭档大会要收集报名信息,这种状况咱们不心愿用户注册,只须要拿到这些数据就行了。明道云提供了公开表单的能力,容许用户将现有的工作表生成并公布一个公开链接或者二维码,让内部用户间接填写。填写完之后,咱们也能够生成一个公开查问的链接,用户通过本人方才填写的关键性的信息,就能够把之前填报的具体数据再查出来。 内部门户公开信息是无状态的,它不会去记录填写人的一些标识性的身份信息,因为它没有账号或者权限体系,可能在某些场景下就不太实用。比方我后面讲到那个场景,一个经销商跟一个工厂的合作,经销商去洽购的时候,我不心愿他去注册明道云账号,然而我又心愿他有肯定的权限,可能看到本人历史的数据;并且可能对这个经销商做身份认证,比方通过手机号、微信号等进行认证。 这种场景下,咱们为每一个利用提供了内部门户的能力。用户能够配置本人企业微信号、公众号,集成音讯告诉性能,用户通过第三方平台就能无感知地进入利用,实现操作。 分享分享用在什么场景呢?分享的内容不须要有状态,也不须要有内部数据,只须要核查能力。举个例子,我妻子的公司是做谷歌推广的,他们每个季度都须要跟供应商做账单核算。之前我看她很辛苦地拿Excel做汇总,再为每个供应商生成一个独自的Excel,发给客户去确认。 我说你齐全不须要这样做。我花了几分钟工夫,搭建了两张表。数据导进来后,为每个供应商主动生成了一条对外分享的二维码。再把这二维码分享给他,他扫码就能看到历史账单记录,这样供应商的体验也很好,工作效率也大大晋升。 咱们在接下来的版本会强化分享能力,可能反对更多视图品种的分享,反对分享进来的记录能够配置哪些数据是能够填写的,反对生成相似分享明码、密钥的身份验证工具。9.前端开源 咱们针对高端玩家提供了一个前端开源能力,零门槛获取并扩大APaaS能力,充沛实现前端界面的个性化。通过前端开源,用户能够对界面做排版、交互上的优化,再联合咱们的方才讲到的这些自定义的界面,就能够去实现更多的交互可能。10.第三方平台集成 咱们进入明道云的后盾账号外面,会看到有一个集成核心,它当初集成了企业微信、钉钉、微信公众号、飞书、Welink,包含其余LDAP形式的受权。通过这些集成,能够做到音讯推送、账号体系同步。再依据方才说的企业级的受权接口,就能够以现有的第三方平台做账号集成和音讯推送。 三、明道云能够怎么做讲了这么多咱们明道云凋谢的能力,咱们再回过头来看明道云能够怎么做? 还是方才结尾提到的场景,从客户下单到残缺的结算。假如咱们没有用第三方零碎,该怎么做?首先,客户下单平台有非凡的交互,能够通过前端开源加上内部门户,用微信号、手机号登录,实现这种小程序的能力。将其嵌入到公众号中,用户能够间接在线下单,查看本人的订单记录,应用微信的领取零碎。 到业务流转环节,经销商的订货、企业接单、供应商生产制作,他们之间的信息交融就能够通过利用的API、工作流的Webhook。再联合一些内部门户的能力,在这些不同的角色之间做数据的合作流转。如果是物流发货或者一些对实时性要求高的场景,就能够集成第三方平台或者应用API查问控件、工作流代码块。员工在明道云界面上就能够实时获取物流信息。 四、咱们还须要哪些能力除此之外,咱们还须要哪些能力?我大略总结一下咱们要做的4大块的内容。 第一是开放平台。我最早讲的开放平台是老的合作模块的产物,它对咱们目前利用上面的API反对还不够敌对,所以前面打算开放平台会退出更多的利用级别的接口。或者咱们当初利用API是利用级别的,前面咱们也会反对用户生成集体的受权token,它的接口只能够获取本人的数据,这样再去做利用第三方集成的时候会不便很多。 第二就是SDK。当初利用对接零碎的时候,它是要依据咱们的示例代码,它的别名比较复杂,控件类型比拟多,筛选类型比拟多。前面咱们会针对不同的开发语言提供针对性的SDK,用户再去对接OpenAPI的时候就会更不便。 第三是用户冀望已久的数据集成能力。减少直连数据库能力,数据在第三方,我不心愿同步过去,然而又心愿拿到相似咱们当初API查问里的后果。比方企查查,其实工商信息是存在那边的,然而我能够通过接口的形式拿过去,通过直连数据库间接获取到这部分数据。而后就是内部数据源的同步,要反对内部的数据源给写到明道云,或者是明道云的数据写到内部的数据库,当然也可能是明道云不同网络下的利用,把一个工作表的数据同步到另外的一个利用的工作表中。 第四个就是插件能力。有的搭档是有AI能力的,那么能够开发一个自定义控件,放到利用市场,大家下载之后就人造有了AI的能力。咱们的插件核心次要蕴含了自定义控件、工作流自定义节点、自定义的视图、自定义的函数,有了这些能力后,咱们对这些有深度开发能力的客户提供了一种可能,咱们把本人的产品能力间接放到利用市场或者开发者核心,上传过来就能够供客户不便地应用它。

March 23, 2023 · 1 min · jiezi

关于javascript:HHDESK文本对比功能升级

在咱们工作中,Word和pdf文档的利用是十分宽泛的,而一个文档从开始到定稿,会呈现多个版本。那么问题来了——你是否能精准的记住每一个改变?恐怕很难。很多软件为此开发了文本比照性能,但大多数只反对txt格局。HHDESK针对这一状况,对文本比照性能进行了降级,反对Word及pdf格局,极大的不便宽广办公人员。 以下便以笔者的2版pdf文档为例,介绍一下此降级性能。应用这个性能仍旧只须要一个步骤:点击文件比照,别离抉择须要比照的文本文档;能够看到,2个文档别离显示,并呈现标识: 红色背景局部为雷同内容的文本;灰色局部为内容有变动的文本;绿色局部为后一份文档所减少的内容;红色局部为后一份文档删除内容(此文档中笔者删除了一个空白行)。 简略不便。

March 23, 2023 · 1 min · jiezi

关于javascript:优秀组件设计的关键自私原则

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。当把组件从设计转化为开发时,经常会发现一些属性与内容无关,而与组件自身无关。这种考虑周到的组件设计办法导致了简单的属性、更平缓的学习曲线和最终的技术债权。然而,防止这些陷阱的要害是自私或自我利益为核心的组件设计。在开发新性能时,是什么决定了现有组件是否可行?当一个组件不能应用时,这到底意味着什么? 该组件在性能上是否没有做它所冀望的事件,比方一个标签零碎没有切换到正确的面板?或者它太死板,不能反对设计的内容,比方一个在内容之后而不是之前有图标的按钮?或者是它太过预设和结构化,无奈反对轻微的变体,比方一个始终有题目局部的模态,当初须要一个没有题目的变体? 这就是组件的生存。很多时候,它们是为了一个狭隘的指标而构建的,而后匆忙地为一个接一个的小变动进行扩大,直到不再可行。在这个时候,会创立一个新组件,技术债权增长,入职学习曲线变得更平缓,代码库的可维护性变得更具挑战性。 这仅仅是组件不可避免的生命周期吗?还是这种状况能够防止?最重要的是,如果能够防止,怎么做? 自私。或者说,自利。更好的说法可能是两者兼而有之。 很多时候,组件过于体贴。它们对彼此太体贴了,尤其是对它们本人的内容太体贴了。为了创立可能随着产品扩大的组件,要害是自私地关注本人的利益——冷酷、自恋、世界环绕着我旋转的自私。 本文并不打算解决自利和自私之间几百年的争执。坦白说,我没有资格参加任何哲学答辩。然而,本文要做的是证实构建自私组件对其余组件、设计师、开发者和应用你内容的人来说是最无利的。事实上,自私的组件在它们四周发明了如此多的益处,以至于你简直能够说它们是自私的。 留神:本文中的所有代码示例和演示都将基于React和TypeScript。然而,这些概念和模式是与框架无关的。思考的迭代兴许,展现一个体贴的组件的最好形式是通过走过一个组件的生命周期。咱们将可能看到它们是如何开始时很小,性能很强,但一旦设计倒退起来就会变得很轻便。每一次迭代都会使组件进一步陷入困境,直到产品的设计和需要超过了组件自身的能力。 让咱们考虑一下虚心的Button组件。它具备欺骗性的复杂性,而且常常被困在思考模式中,因而,是一个很好的工作实例。 迭代1尽管这些样本设计相当简陋,比方没有显示各种:hover、:focus和 :disabled状态,但它们的确展现了一个有两种色彩主题的简略按钮。 乍一看,所产生的Button组件有可能和设计一样是赤裸裸的。 // 首先,从React扩大原生HTML按钮属性,如onClick和disabled。type ButtonProps = React.ComponentPropsWithoutRef<"button"> & { text: string; theme: 'primary' | 'secondary';}<Button onClick={someFunction} text="Add to cart" theme="primary"/>有可能,甚至有可能,咱们都见过这样的一个Button组件。兴许咱们甚至本人也做过这样的一个。有些名字可能不一样,但 props 或Button的API大抵上是一样的。 为了满足设计的要求,Button 为 theme 和 text 定义了 props 。这第一个迭代工作,满足了设计和产品的以后需要。 然而,设计和产品的以后需要很少是最终需要。当下次设计迭代时,增加到购物车的按钮当初须要一个图标。 迭代2在验证了产品的用户界面后,决定在增加到购物车的按钮上减少一个图标,这将是无益的。不过,设计人员解释说,不是每个按钮都会包含一个图标。 回到咱们的Button组件,它的 props 能够用一个可选的 icon 来扩大,该 props 映射到一个图标的名称,以便有条件地渲染。 type ButtonProps = { theme: 'primary' | 'secondary'; text: string; icon?: 'cart' | '...all-other-potential-icon-names';}<Button theme="primary" onClick={someFunction} text="Add to cart" icon="cart"/>呜呼!危机解除了。 ...

March 23, 2023 · 3 min · jiezi

关于javascript:学会了slidevjs的开发者-也许可以考虑不用ppt了

背景、 作为一个开发者, 每次应用PPT或者Word写简历或者述职都好苦楚啊, 这些App也不太适宜展现代码, 然而明天来的家人们有福了, 一款叫做是slidev的库露出了邪魅的微笑 官网地址。 Slidev (slide + dev, /sldv/) 是基于 Web 的幻灯片制作和演示工具。它旨在让开发者专一在 Markdown 中编写内容,同时领有反对 HTML 和 Vue 组件的能力,并且可能出现像素级完满的布局,还在你的演讲稿中内置了互动的演示样例。 上面间接上动图吧: 其实官方网站写的还算残缺, 但之所以写这篇文章是因为官网里一些写法其实有bug, 并且官网里很多出都展现了代码然而没有展现效果图, 并且官网文档的编写程序有一点点不敌对, 让人看起来有点晕。 一、装置npm init slidev 你能够把他当成是用create-react-app创立了一个react我的项目 这里要留神尽管官网说大于等于14.0.0, 然而亲测至多须要14.18.0 创立好后进入我的项目目录运行: yarn dev二、模块分页与动画 slidev每一页都是等比缩放的, 并且每页都是无奈滚动的, 所以每页的内容是无限的这点要留神: slidev有点奇怪, 我的项目启动后会默认以外层的slidev.md为入口文件进行解析: 咱们能够先把slidev.md文件内容清空, 因为官网的例子里是把简直所有页面的代码都写在了这里, 这导致看起来乱遭遭并且写代码容易窜行, 所以这里我倡议先学如何划分页面模块: ---src: ./pages/1:首页.md------src: ./pages/2:代码展现.md------src: ./pages/3:图片.md---在 pages文件夹里新增md文件 在slidev的语法外面, "---"两头包裹的个别是一些全局设置, 如果独自写"---"就相似于" "标签的款式, 然而留神这里有个bug:---# ---src: ./pages/1:首页.md--- ...

March 22, 2023 · 2 min · jiezi

关于javascript:处理尚不存在的-DOM-节点

摸索 MutationObserver API 与传统轮询期待最终被创立的节点办法相比的优劣。有时候,您须要操作尚未存在的 DOM 的某个局部。 呈现这种需要的起因有很多,但你最常看到的是在解决第三方脚本时,这些脚本会异步地将标记注入页面。举个例子,我最近须要在用户敞开Google reCAPTCHA的挑战时更新UI。诸如blur事件的响应并没有失去工具的正式反对,所以我打算本人来设计一个事件监听器。然而,通过像.querySelector()这样的办法来尝试拜访节点会返回null,因为此时节点还没有被浏览器渲染,并且我也不晓得到底什么时候会被渲染。 为了更深刻地探讨这个问题,我设计了一个按钮,让它在随机的工夫内(0到5秒之间)被挂载到DOM中。如果我试图从一开始就给这个按钮增加一个事件监听器,我就会失去一个异样。 // Simulating lazily-rendered HTML:setTimeout(() => { const button = document.createElement('button'); button.id = 'button'; button.innerText = 'Do Something!'; document.body.append(button);}, randomBetweenMs(1000, 5000));document.querySelector('#button').addEventListener('click', () => { alert('clicked!')});// Error: Cannot read properties of null (reading 'addEventListener')真的是毫无意外。你看到的所有代码都会被丢进调用栈并立刻执行(当然,除了setTimeout的回调函数),所以当我试图拜访按钮时,我所失去的便是null。 轮询为了解决这个问题,通常做法是应用轮询,不停的查问DOM直到节点呈现。你可能会看到应用setInterval或者setTimeout这样的办法,上面是应用递归的例子: function attachListenerToButton() { let button = document.getElementById('button'); if (button) { button.addEventListener('click', () => alert('clicked!')); return; } // If the node doesn't exist yet, try // again on the next turn of the event loop. setTimeout(attachListenerToButton);}attachListenerToButton();或者,你可能曾经见过一种基于Promise的办法,这感觉更古代一些: ...

March 22, 2023 · 2 min · jiezi

关于javascript:再学JS高级笔记1JS运行原理

1 JavaScript运行原理1.1 浏览器的工作原理JavaScript代码在浏览器中是如何被执行的? 1.2 浏览器的内核那么,向服务器申请了相干文件并下载了之后,是什么来解析咱们的js文件的呢?答案是浏览器内核。 实际上,咱们常常说的浏览器内核指的是浏览器的排版引擎: 排版引擎(layout engine)也称为浏览器引擎(browser engine)、页面渲染引擎(rendering engine)或样板引擎不同的浏览器有不同的内核 GeckoTridentWebkitBlink1.3 浏览器渲染过程 如果在执行这个过程中,HTML解析的时候遇到了JavaScript标签,应该怎么办呢? 会进行解析HTML,而去加载和执行JavaScript代码那么JavaScript代码由谁来执行呢? JavaScript引擎1.4 JavaScript引擎为什么须要JavaScript引擎? 高级的编程语言都须要转成最终的机器指令来执行实际上咱们编写的JavaScript无论是交给浏览器或者Node执行最初是都须要被CPU执行的CPU只意识本人的指令集,只有机器语言能力被CPU所执行所以须要JavaScript引擎帮忙咱们将JavaScript代码翻译成CPU指令能力被执行常见的JavaScript引擎: SpiderMonkeyChakraJavaScriptCodeV8:Google开发的JS引擎,帮忙Chrome从泛滥浏览器中怀才不遇1.5 浏览器内核和JS引擎的关系以WebKit为例,WebKit事实上由两局部组成: WebCore:负责HTML解析、布局、渲染等等相干的工作JavaScriptCore:解析、执行JavaScript代码 小程序也是相似的,将代码分为两层: Webview渲染层:负责渲染HTML构造等JsCore逻辑层:负责解析执行JavaScript代码 1.6 V8引擎官网的定义: V8是用C++编写的Google开源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等能够在很多不同的操作系统上运行V8能够独立运行,也能够嵌入到任何C++应用程序中V8引擎自身的源码非常复杂,大略有超过100w行C++代码,通过理解它的架构,咱们能够晓得它是如何对JavaScript执行的: Parse模块:进行词法剖析和语法分析,将代码转换成<u>AST(形象语法树)</u>,因为解析器并不间接意识JS代码如果函数没有被调用,那么是不会被转换成AST的Parse的V8官网文档:https://v8.dev/blog/scannerIgnition解释器:会将AST转换成ByteCode(字节码)同时会收集TurboFan优化所须要的信息(比方函数参数的类型信息,有了类型能力进行实在的运算)如果函数只调用一次,Ignition会执行解释去执行ByteCodepIgnition的V8官网文档:https://v8.dev/blog/ignition-interpreter字节码是能够跨平台的,所以当运行的时候cpu会将字节码转成相干平台的汇编代码,再转换成cpu指令TurboFan编译器:能够将字节码编译为CPU能够间接执行的机器码如果一个函数被屡次调用,会被标记为热点函数,那么就会通过TurboFan转换成优化的机器码,进步代码的执行性能然而机器码实际上也会被还原为ByteCode。这是因为如果后续执行函数的过程中,类型产生了变动(比方sum函数原来执行的是number类型,起初执行变成了string类型),之前优化的机器码并不能正确地解决运算,就会逆向地转换成字节码(Deoptimization)TurboFan的V8官网文档:https://v8.dev/blog/turbofan-jit1.7 V8执行过程的细节 JavaScript源码是如何被解析(parse过程)的呢? Blink(内核)将JS代码交给V8引擎,Stream获取到JS代码并且进行编码转换Scanner(扫描器)会进行词法剖析(lexical analysis),词法剖析会将代码转换成tokens接下来tokens会通过Parser和Preparser,被转换成AST树Parser就是间接将tokens转成AST树架构PreParser称为预解析,为什么须要预解析呢? 因为不是所有的JavaScript代码在一开始时就会被执行,那么对所有代码进行解析必然会影响网页的运行效率所以V8引擎就实现了Lazy Parsing(提早解析)的计划,它的作业是将不必要的函数进行预解析,也就是只解析临时须要的内容。而对函数的全量解析是在函数被调用时才会进行生成的AST树只会被Ignition转成字节码之后的过程就是代码的执行过程

March 21, 2023 · 1 min · jiezi

关于javascript:100行代码实现一个乞丐版webpack

Hello各位靓仔大家好呀!在我一次一次迁延症之后这篇文章终于问世了;首先祝大家新年好吧(搪塞)~ 明天来讲讲webpack的打包原理,以及简略实现吧~ 置信大家对webpack多多少少都有了解,说到webpack是什么基本上都能说出这是一个模块化打包工具,明天我就从模块化与打包动手来简略解说一下 模块化与webpack说到Webpack总绕不开模块化,咱们来看看模块化的倒退过程与Webpack在其中起到的作用;晚期因为没有标准的束缚,模块化计划也是层出不穷,最后的模块化计划是最原始简略的文件划分计划;每个文件代表一个独自模块,而后在页面中通过script标签援用,因为代码是在同一个作用域中执行的短期内的确没有什么影响,然而随着我的项目体量的增大随之而来的是各种命名抵触,作用域净化,变量晋升等一系列辣手的问题;过后最显著的莫过于命名抵触问题;为了解决命名抵触问题,优良的前端切图仔先辈们在文件划分的根底之上整出了一个命名空间模块化划分计划,顾名思义就是为每一个模块提供独立的命名空间并挂载到Window上,通过Window.moduleXXX的形式去调用模块内的属性,这的确解决了命名抵触的问题;然而作用域净化的问题仍旧存在,那怎么办?当然是给模块提供独自的作用域咯!过后最广泛的是IIFE模块化划分计划,在命名空间划分计划的根底之上为模块提供一个公有作用域;这个公有作用域是通过调用一个立刻执行函数通过闭包的模式将模块挂载到window之上至此也就解决了作用域净化问题;人么吃饱了饭没事干总喜爱打老婆(bushi),没事总喜爱瞎折腾,尽管IIFE曾经完满解决了作用域净化与变量命名抵触的问题然而切图仔们并不满足,他们感觉IIFE这种形式并不够快,当我的项目体量变得非常微小的时候很容易造成卡顿(页面引入的模块并不会打消,每次加载都会将所有模块加载);这时官网出手了,官网并没有惩治这群不知足的切图仔,相同还助他们一臂之力,随之而来的推出了一套AMD标准(异步模块加载标准) 因为cjs并不能很好的实用于浏览器,然而前端代码却是要在浏览器中执行的,因而诞生了赫赫有名的require.js,原理即是在须要引入模块时创立一个script标签挂载到页面中来做到异步加载;随着前端的倒退,切图仔的欲望又得不到满足;在应用require.js倒退的期间为了能兼容cjs也诞生过例如CMD标准然而究竟是过眼云烟;再往后随着模块化规范的增多,与依赖的不对立切图仔们发现急需一套新规范来标准模块化,为了兼容AMD,cjs与全局变量于是便诞生了UMD,随着ES规范的不断完善ES Modules诞生了,这便是咱们当初罕用的import导入的模块化形式; 讲了这么多模块化常识那么跟webpack有个鸡毛关系?随着前端模块的与我的项目资源的一直增多,对模块的治理熬掉了不少切图仔乌黑亮丽的秀发;秃头的切图仔们急需一个模块化管理工具来治理高效我的项目中的每一个文件与资源;于是诞生了webpack rollup gulp等等一系列工具 webpack解决了什么问题?关上webpack官网映入眼帘的就是这张图片 由这张图中咱们能够看到webpack将一堆零散的文件打包编译成为js css 以及图片;这么做有什么用?又解决了什么问题呢? 我总结出了以下三点: 模块整合能力随着我的项目体量的增大,模块文件增多使切图仔们解决模块文件变得异样艰苦,而模块资源又在浏览器当中运行,频繁的申请零散文件势必会对服务器造成负荷与利用的工作效率;而webpack能够将多个模块文件打包成一个文件,在缩小资源内存的同时也缩小了对服务器的申请 代码编译能力随着ES标准的疾速倒退,很多浏览器并不能及时兼容新的语法与API;这导致API的兼容变成一个较大的问题,而webpack则能够将这些浏览器看不懂的API与语法转换成浏览器看得懂的ES5语法; 多品种模块资源管理随着前端的倒退模块品种增多(css,html,js,图片),而前端须要通过代码或者工具对模块资源进行治理整合; 创立你的第一个Webpack我的项目置信在日常工作中大家对React与Vue脚手架的应用曾经十分的纯熟,然而不晓得大家在日常工作中是否用webpack从0到1创立过一个残缺的我的项目,接下来我将用一个简略的webpack我的项目动手为大家剖析解说webpack的目录构造与打包原理; 初始化我的项目 #初始化我的项目npm init #为我的项目增加依赖yarn add webpack 我的项目目录构造 ├── node_modules├── package-lock.json└── package.json在目录下为我的项目增加webpack文件,webpack配置文件以及源码目录(src) webpack.js const { webpack } = require("webpack");const webpackOptions = require("./webpack.config.js");const compiler = webpack(webpackOptions);//开始编译compiler.run();webpack.config.js const path = require("path");module.exports = { mode: "development", entry: "./src/index.js", //入口文件 output: { path: path.resolve(__dirname, "dist"),//输入门路 filename: "[name].js", }, devtool: "source-map", };为源码我的项目(src)增加文件 name.js ...

March 20, 2023 · 7 min · jiezi

关于javascript:树根据节点的值计算父节点的值

前段时间答复了一个相似的问题,产生了写一篇博客的想法。这个问题的确存在一些常见的的利用场景,比方一个多层组织构造中,已知每个员工的绩效分,心愿计算各级部门的绩效分以便对部门评优。 筹备依据这个形容,筹备一个试验数据如下: { "name": "某某公司", "children": [ { "name": "生产序列", "children": [ { "name": "研发部", "children": [{ "name": "软件部" }, { "name": "测试部" }] }, { "name": "工程部", "children": [{ "name": "估算部" }, { "name": "项目管理部" }] } ] }, { "name": "行财序列", "children": [{ "name": "财务部" }, { "name": "办公室" }] } ]}直观的树形示意如下 某某公司├── 生产序列│   ├── 研发部│   │   ├── 软件组│   │   └── 测试组│   └── 工程部│      ├── 估算组│      └── 项目管理组└── 行财序列    ├── 财务部    └── 办公室每个部门又有若干员工。假如拿到的数据是用元组(数组)来示意,别离是 [姓名, 部门, 岗位, 集体绩效],上面是随机生成的一个用例数据。 ...

March 20, 2023 · 4 min · jiezi

关于javascript:Taro-小程序持续集成

大家好,我是杨胜利。 传统意义上的继续集成,是在 Web 端通过自动化的形式将我的项目打包并上传到服务器,这一过程须要 Git 参加。继续集成的目标是为了免去手动打包、手动上传这一繁琐且容易出错的步骤,进步部署效率和部署的安全性。 而小程序部署形式与 Web 端不同,它不须要在本地打包,点击开发者工具中的上传按钮就会公布版本,版本能够在小程序管理后盾看到。当须要其他人测试时,将某个版本设置为体验版,而后分享体验版二维码即可。 为什么小程序也须要继续集成?在理论开发中咱们遇到了这样的问题:每个前端人员上传后会产生一个新版本,不同的人上传后须要测试时,就要登录到治理后盾切换体验版,在频繁测试场景下这个过程十分繁琐。 那么如何解决呢?解决方案就是将某个固定的版本号设置为体验版(如上图中的 v1.1.0),每个人都在这个版本号下上传,这样就不须要在后盾切换版本了。多人在一个版本号下上传,开发者工具办不到,此时须要集成 CI 的能力。 Taro 集成 CI我司小程序是基于 Taro 开发的,Taro 提供了官网插件 @tarojs/plugin-mini-ci 来反对继续集成。应用形式也很不便,文档在 [这里]。(https://docs.taro.zone/docs/plugin-mini-ci) 咱们以微信小程序为例,介绍接入继续集成的正确姿态。 留神:小程序继续集成至多须要 Taro v3.6.2 的版本,之前的版本会报错,请留神降级。1. 小程序后盾升成上传密钥。用代码的形式上传小程序,必然须要微信提供一个凭证,这个凭证就是上传密钥。在小程序后盾找到【开发->开发治理->开发设置】,会看到“小程序代码上传”面板。点击“生成”按钮,依据步骤创立密钥并下载。 下载后将密钥命名为 private.key,而后将其保留在我的项目的 config 目录下。 2. 装置插件并配置在终端执行命令: $ yarn add @tarojs/plugin-mini-ci -D在配置文件 config/index.js 中引入插件并配置: const ciPlugin = { // 微信小程序 weapp: { appid: 'xxxxx', privateKeyPath: 'config/private.key', }, // 版本号 version: '1.1.0', // 版本公布形容 desc: 'CI主动公布',}const config = { ... plugins: [ ['@tarojs/plugin-mini-ci', ciPlugin] ],}配置中的 weapp 选项示意微信小程序配置,传入小程序的 appid,属性 privateKeyPath 示意下载后的上传密钥的门路(相对路径)。简略两步,配置就实现了。 ...

March 18, 2023 · 2 min · jiezi

关于javascript:那些不用js也能实现的效果

本文首发于公众号:GitWeb,欢送关注,接管首发推文本文列举几个不须要应用js也能实现的成果 一、页面回到顶部 回到顶部是页面开发中很常见的一个性能,个别的做法是对回到顶部组件做一个监听,当用户点击的时候,设置body的scrollTop为0。明天发现一种更加简略的形式,不须要用到js也能实现。就是通过链接的href来做 <a href="#">回到顶部</a> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> <div>10</div> <div>11</div> <div>12</div> <div>13</div> <div>14</div> <div>15</div> <div>16</div> <div>17</div>像代码中这样,当点击这个链接的时候,页面会主动回到顶部,然而这种回到顶部是霎时实现的,咱们须要一个滚动的过程。所以咱们须要对整个页面做一个平滑滚动的款式。设置html的scroll-behavior为smooth html{ scroll-behavior: smooth; }二、文本多行截断可(开展)收起 1.实现这个多行截断比较简单,就是借助line-clamp这个属性就能够,再配合这个webkit-box-orient属性,就能够实现这种三行截断 .clamp{ overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; } <p class="clamp"> 庆历四年春,滕子京谪守巴陵郡。越明年,政通人和,百废具兴,乃重修岳阳楼,增其旧制,刻唐贤今人诗赋于其上,属予作文以记之。 予观夫巴陵胜状,在洞庭一湖。衔远山,吞长江,浩浩汤汤,横无际涯,朝晖夕阴,气象万千,此则岳阳楼之大观也,前人之述备矣。 然则北通巫峡,南极潇湘,迁客骚人,多会于此,览物之情,得无异乎?若夫淫雨霏霏,连月不开,阴风怒号,浊浪排空,日星隐曜, 山岳潜形,商旅不行,樯倾楫摧,薄暮冥冥,虎啸猿啼。登斯楼也,则有去国怀乡,忧谗畏讥,满目萧然,感极而悲者矣。至若春和景明, 波澜不惊,高低天光,一碧万顷,沙鸥翔集,锦鳞游泳,岸芷汀兰,郁郁青青。而或长烟一空,皓月千里,浮光跃金,静影沉璧,渔歌互答, 此乐何极!登斯楼也,则有赏心悦目,宠辱偕忘,把酒临风,其气冲冲者矣。嗟夫!予尝求古仁人之心,或异二者之为,何哉?不以物喜,不以己悲, 居庙堂之高则忧其民,处江湖之远则忧其君。是进亦忧,退亦忧。然则何时而乐耶?其必曰“先天下之忧而忧,后天下之乐而乐”乎!噫!微斯人, 吾谁与归?时六年九月十五日。 </p>2.借助checkbox和label来实现按钮(开展)收起 .btn::after{ content: '开展'; } #state:checked + .btn::after{ content: '收起'; } #state{ position: absolute; left: -999999px; } #state:checked ~ p{ -webkit-line-clamp: 100; } <input type="checkbox" name="" id="state"> <label for="state" class="btn"></label>三、图片对齐不变形 ...

March 17, 2023 · 1 min · jiezi

关于javascript:GPT4终于来了

就在昨天凌晨,OpenAI公布了多模态预训练大模型GPT-4。 这不昨天一沉睡来,GPT-4都快刷屏了,不论是在朋友圈还是网络上都看到了很多信息和文章。 GPT是Generative Pre-trained Transformer的缩写,也即生成型预训练变换模型的意思。 OpenAI在布告中写道,GPT-4是一个多模态大模型,也是OpenAI致力扩大深度学习最新的里程碑。 OpenAI的CEO也说这是他们到目前为止性能最弱小的模型。 置信这两天大家在网络上看到的信息比拟多也比拟杂,对于GPT-4,咱们这里也总结了几个比拟要害的点。 1、反对视觉输出GPT-4领有多模态能力,当初能够承受图像输出并了解图像内容,这也是这次公布比拟有吸引力的一个点。 比方官网给出了一个示例,给出一幅图,手套掉下去会怎么样? GPT-4能够了解并输入给到:它会掉到木板上,并且球会被弹飞。 再比方给GPT-4一个长相奇怪的充电器图片,问为什么这很可笑? GPT-4答复道,VGA 线充 iPhone。 另外GPT-4也能够辨认与解析图片内容,比方间接将论文截图后丢给GPT-4,它就能够主动对其进行了解和剖析。 用户甚至还能够间接画一个网站草图拍照丢给GPT-4,它就能够立马帮忙生成代码。 2、文字输出限度晋升GPT-4的文字输出限度进一步晋升,得益于此,GPT-4的实用性也进一步扩大。比方发布会直播上OpenAI总裁现场演示了一波GPT-4给代码修Bug。 用户能够间接把万字的程序文档丢给GPT-4等着解决办法。 3、性能晋升在失常的对话过程中,对于GPT-3.5和GPT-4之间的区别感知可能很奥妙,然而当解决一些简单输出时GPT-4的劣势会更显著。 团队示意,GPT-4在各种业余测试和学术基准上的体现与人类程度相当,其中一个数据就是它通过了模仿律师考试,且分数在应试者的前10%左右,而此前公布的GPT-3.5,则处于倒数10%的行列。 OpenAI也在那些为机器学习模型设计的传统基准上评估了GPT-4。从试验后果来看,GPT-4 大大优于现有的大型语言模型,以及大多数SOTA模型。 4、仍然有限制性只管这次公布的GPT-4体现出了很弱小的能力,然而官网仍然示意GPT-4与晚期的GPT模型具备类似的局限性,并不是相对牢靠。 官网示意应用这些语言模型时还是要审慎审查其输入内容,必要时应用与特定用例的需要相匹配的确切协定(例如人工审查、附加上下文或完全避免高风险场景下的应用) 。 GPT-4依然可能会产生幻觉、生成谬误答案,并呈现推理谬误,所以团队这也是提前给打了一个预防针。 尽管这依然是一个问题,但GPT-4相较于于以前的模型显著缩小了“幻觉”。在外部的对抗性真实性评估中,GPT-4的得分比最新的GPT-3.5高40%。 5、对于应用聊了这么多,普通用户要想应用上GPT-4预计还要再等等。 目前是只有ChatGPT Plus付费订阅会员才能够试用GPT-4,且试用阶段每四小时最多发100条信息。 而且目前来说,用户仍然只能收回纯文本信息,像图像等一些视觉输出性能预计后续才会放开应用。 目前OpenAI仅仅是凋谢了GPT-4 API的申请通道。 用户如果想要应用的话,能够先提申请加入waitlist列表期待通过。 6、对于GPT-4论文对于GPT-4公布的细节和技术,官网也给出了一个pdf版本的具体技术报告,有趣味的小伙伴能够自行查看。 总而言之,这两天看到太多无关GPT-4的信息,不晓得为啥心里总有一种说不出来的感觉。 我不晓得怎么样去形容这种感触,然而我想起来之前发的一篇文章评论区一位小伙伴的留言: “忽然感觉向将来迈出了一步是怎么回事” 好了,明天的分享就先到这里吧,咱们下期见。

March 16, 2023 · 1 min · jiezi

关于javascript:如何移除事件监听器

在运行时清理你的代码是构建高效、可预测的应用程序,没有商量余地的局部。在JavaScript中,实现这一指标的办法之一是很好地治理事件监听器,尤其是当不再须要时移除它们。 有好几种办法能够做到这件事件,每种都有本人的一套衡量办法,使其在某些状况下更适合。咱们将介绍几种最罕用的策略,以及当你试图决定哪种办法最适宜于任何特定工夫的工作时,须要思考的一些问题。 咱们将对上面的设置进行修补--一个带有单击事件监听器的按钮: <button id="button">Do Something</button><script>document.getElementById('button').addEventListener('click', () => { console.log('clicked!');});</script>应用getEventListeners()函数,你会看到只有一个监听器连贯到该元素: 如果你须要移除该监听器,你能够用以下几个办法。 应用.removeEventListener()这可能是最不言而喻的,但也是最有可能威逼到你心智的一个。.removeEventListener()办法接管三个参数:待移除监听器的类型,监听器的回调函数,以及可选对象。 但这里有一个(潜在的)辣手的局部:这些确切的参数必须与设置监听器时应用的参数完全一致,包含内存中回调的雷同援用。否则,.removeEventListener()啥也不做。 思考到这一点,上面的示例将是齐全有效的: document.getElementById('button').addEventListener('click', () => { console.log('clicked!');});document.getElementById('button').removeEventListener('click', () => { console.log('clicked!');});只管回调函数看起来一样,但它们不是雷同的援用。解决方案是将回调函数设置为一个变量,并在.addEventListener()和.removeEventListener()中援用它。 const myCallback = () => { console.log('clicked!');};document.getElementById('button').addEventListener('click', myCallback);document.getElementById('button').removeEventListener('click', myCallback);或者,对于特定的用例,你也能够通过在函数自身中援用一个伪匿名函数来移除监听器: document .getElementById('button') .addEventListener('click', function myCallback() { console.log('clicked!'); this.removeEventListener('click', myCallback); });只管有其特殊性,.removeEventListener()的劣势在于其目标十分明确。当你通读完代码时,对它的作用没有任何疑难。 应用.addEventListener()的once选项如果.addEventListener()是为了一次性应用,.addEventListener()办法自带一个工具能够帮忙本人清理:once选项。这和它听起来一样简略。如果设置为true,监听器会在第一次被调用后主动移除它本人: const button = document.getElementById('button');button.addEventListener('click', () => { console.log('clicked!');}, { once: true });// 'clicked!'button.click();// No more listeners!getEventListeners(button) // {}假如它合乎你的应用状况,如果你热衷于应用匿名函数,这种办法可能是适合的,因为你的监听器只须要被调用一次。 克隆&替换节点有时,你不晓得某个节点上所有沉闷的监听器,但你晓得你想要捣毁它们。在这种状况下,克隆整个节点并应用克隆的替换该节点是可行的。应用.cloneNode()办法,通过.addEventListener()附加的监听器都不会被带过来,给它一个洁净的环境。 让咱们回到客户端JavaScript的石器时代,你会看到这是由查问到父节点,而后用一个克隆节点替换一个特定的子节点实现的: button.parentNode.replaceChild(button.cloneNode(true), button);但在古代浏览器中,能够应用.replaceWith()进行简化: button.replaceWith(button.cloneNode(true));有一件事可能会让你感到困惑,那就是外部监听器会被保留下来,这意味着一个带有onclick属性的按钮依然会依照定义触发: <button id="button" onclick="console.log('clicked!')"> Do Something</button>总之,如果你须要用蛮力不分青红皂白地删除任何品种的监听器,这是一个值得一试的抉择。然而,在毛病方面,就是它的目标不太显著。有人会说它是一个hack伎俩。 ...

March 16, 2023 · 1 min · jiezi

关于javascript:JavaScript构造函数面向对象编程

前言大家应该都据说过面向对象编程吧,在java和c语言中,是有”类(class)”的概念的,所谓“类”就是对象的模板,对象就是“类”的实例。而在JavaScript语言,他的对象体系是基于构造函数(constructor)和原型链(prototype)的。 你可能会问,不对啊,es6不是有个class么?实际上es6的class只是模拟java起了一个面向对象的习惯性的名字,让对象原型的写法更加清晰、更像面向对象编程的语法而已,而且es6的class本身指向的就是构造函数。 所以能够认为ES6中的类其实就是构造函数的语法糖或者是构造函数的另外一种写法而已! 通常生成一个对象的传统形式就是通过构造函数,这也是JS面向对象惟一终点。 一、构造函数根底学习1.构造函数的定义和应用办法JavaScript构造函数是用于创建对象的函数。它们与一般函数的区别在于,构造函数被用于创立一个新的对象,并且该对象的属性和办法能够在函数外部定义,为了辨别一般函数,构造函数个别首字母大写。 构造函数的应用办法非常简单。您只须要应用new关键字来调用构造函数,并将其赋值给一个变量即可。例如: function Car(name, age) { this.name = name; this.age = age;}const car1 = new Car('小明', 20);在这个例子中,咱们创立了一个名为Car的构造函数,并应用new关键字创立了一个名为car1的Car对象。该对象具备两个属性:name和age。这些属性是在构造函数外部定义的。 2.构造函数的参数和返回值构造函数能够承受任意数量的参数,并且能够返回一个新的对象。在构造函数外部,应用this关键字来定义对象的属性和办法。 上面是一个应用构造函数返回对象的例子: function Rectangle(width, height) { this.width = width; this.height = height; this.area = function() { return this.width * this.height; }}const rect1 = new Rectangle(5, 10);console.log(rect1.area()); // 50在这个例子中,咱们创立了一个名为Rectangle的构造函数,并应用它创立了一个名为rect1的对象。该对象具备三个属性:width、height和area。其中,area是一个函数,用于计算矩形的面积。 3.原型和原型链的概念在JavaScript中,每个对象都有一个原型。原型是一个对象,蕴含了该对象的属性和办法。当您尝试拜访一个对象的属性或办法时,JavaScript会首先查找该对象自身是否具备该属性或办法。如果对象自身没有该属性或办法,JavaScript会查找该对象的原型,并在原型中查找该属性或办法。 原型链是一系列由对象原型组成的链。当您尝试拜访一个对象的属性或办法时,JavaScript会沿着该对象的原型链向上查找,直到找到该属性或办法为止。 <aside> js构造函数的执行过程是怎么的? </aside> 创立一个空对象(this)。将this绑定到新创建的对象上。执行构造函数外部的代码,给this增加属性和办法。默认返回this(除非显式返回其余值)实际上,用new调用函数后,JS引擎就会在内存中创立一个空对象{},创立进去的新对象的__proto__属性指向构造函数的原型对象(艰深了解就是新对象隐式原型__proto__链接到构造函数显式原型prototype上。)构造函数外部的this会指向这个新对象, 而后从上到下执行函数体(只有这步是咱们能直观看到代码的)最初,返回发明进去的对象,也就是咱们失去的实例对象 原型对象,构造函数和实例三者的关系如图所示: 也就是说,你每次new,都会失去一个全新的对象,有本人的内存空间,所以创立多个实例对象,他们之间互不影响,只会共用一个原型对象上的属性和办法,这里就要留神,尽量把雷同的属性或者办法都放在构造函数外部,这样多个实例应用时能够节俭本身空间 4.如何继承构造函数JavaScript容许您通过继承构造函数来创立新的对象类型。这能够通过应用原型来实现。上面是一个应用原型继承构造函数的例子: function Animal(name) { this.name = name;}Animal.prototype.getName = function() { return this.name;}function Dog(name, breed) { Animal.call(this, name); this.breed = breed;}Dog.prototype = Object.create(Animal.prototype);Dog.prototype.constructor = Dog;Dog.prototype.getBreed = function() { return this.breed;}const dog1 = new Dog('小黑', '拉布拉多');console.log(dog1.getName()); // '小黑'console.log(dog1.getBreed()); // '拉布拉多'在这个例子中,咱们创立了一个名为Animal的构造函数,并在其原型中定义了一个名为getName的办法。而后,咱们创立了一个名为Dog的构造函数,并通过调用Animal.call办法来继承Animal构造函数。最初,咱们在Dog原型中定义了一个名为getBreed的办法,并将Dog.prototype设置为Animal.prototype的一个新实例,从而实现了继承。 ...

March 15, 2023 · 3 min · jiezi

关于javascript:JAVAEE与JAVA有何区别

Java分三个版本:Java SE(标准版)、Java EE(企业版)、Java ME(微型版) 其中SE就是大家学的Java根底,EE是公司罕用的用于网站开发(PC端),ME用于挪动端开发,当初相熟的安卓零碎就是用JAVAME开发的。 Java既能够被编译,也能够被解释。通过编译器,能够把Java 程序翻译成一种中间代码 - 称为字节码 - 能够被Java解释器解释的独立于平台的代码。通过解释器,每条Java字节指令被剖析,而后在计算机上运行。只需编译一次,程序运行时解释执行。 Java不同于个别的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),而后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台个性。 或者用一种更总结性的话术来表白就是:java跨平台就是能在不同的环境(次要是操作系统)上运行java程序! 这也是Java为什么这么火,为什么这么多年仍然耸立不倒且久盛而不衰的起因。一个无视于平台,跨平台的语言,必然有短暂的生命力。而作为程序员来说,职业倒退的长远规划,抉择Java远比抉择其余无奈实现跨平台的语言,更有久远价值(包含当初十分风行的H5语言,也是一种跨平台语言,“一次设计,广泛实用。一次编写,随处部署”,感兴趣的能够加QQ3227716772)。 类似的JAVAEE、javase、javame可简略的总结为三点: Java SE 是做电脑上运行的软件。 Java EE 是用来做网站的-(咱们常见的JSP技术) Java ME 是做手机软件的。

March 15, 2023 · 1 min · jiezi

关于javascript:树莓派阿里云IoT人脸识别场景实战业务系统架构类

1.整体架构基于阿里云的Serverless架构 2.阿里云产品IoT平台:https://www.aliyun.com/product/iot函数计算:https://www.aliyun.com/product/fc表格存储:https://www.aliyun.com/product/otsOSS存储:https://www.aliyun.com/product/oss人脸识别:https://data.aliyun.com/product/face 3.设施洽购 4.树莓派设施端开发4.1 Enable Camera 4.2 目录构造1.在/home/pi目录下创立 iot文件夹,2.在/home/pi/iot创立 photos文件夹,iot.cfg配置文件,iot.py文件 4.3 Python3程序4.3.1 装置依赖pip3 install oss2pip3 install picamerapip3 install aliyun-python-sdk-iot-client4.3.2 iot.cfg配置文件[IOT]productKey = xxxdeviceName = xxxdeviceSecret = xxx[OSS]ossAccessKey = xxxossAccessKeySecret = xxxossEndpoint = xxxossBucketId = xxx4.3.3 iot.py应用程序 #!/usr/bin/python3# -*- coding: utf-8 -*-import oss2from picamera import PiCameraimport timeimport aliyunsdkiotclient.AliyunIotMqttClient as AliyunIotimport configparserconfig = configparser.ConfigParser()config.read('iot.cfg')# IoTPRODUCE_KEY = config['IOT']['productKey']DEVICE_NAME = config['IOT']['deviceName']DEVICE_SECRET = config['IOT']['deviceSecret']HOST = PRODUCE_KEY + '.iot-as-mqtt.cn-shanghai.aliyuncs.com'SUBSCRIBE_TOPIC = "/" + PRODUCE_KEY + "/" + DEVICE_NAME + "/control";# ossOSS_AK = config['OSS']['ossAccessKey']OSS_AK_SECRET = config['OSS']['ossAccessKeySecret']OSS_ENDPOINT = config['OSS']['ossEndpoint']OSS_BUCKET_ID = config['OSS']['ossBucketId']auth = oss2.Auth(OSS_AK, OSS_AK_SECRET)bucket = oss2.Bucket(auth, OSS_ENDPOINT, OSS_BUCKET_ID)camera = PiCamera()camera.resolution = (720,480)# Take a photo first, then upload photo to ossdef take_photo(): ticks = int(time.time()) fileName = 'raspi%s.jpg' % ticks filePath = '/home/pi/iot/photos/%s' % fileName # take a photo camera.capture(filePath) # upload to oss bucket.put_object_from_file('piPhotos/'+fileName, filePath)def on_connect(client, userdata, flags, rc): print('subscribe '+SUBSCRIBE_TOPIC) client.subscribe(topic=SUBSCRIBE_TOPIC)def on_message(client, userdata, msg): print('receive message topic :'+ msg.topic) print(str(msg.payload)) take_photo()if __name__ == '__main__': client = AliyunIot.getAliyunIotMqttClient(PRODUCE_KEY,DEVICE_NAME, DEVICE_SECRET, secure_mode=3) client.on_connect = on_connect client.on_message = on_message client.connect(host=HOST, port=1883, keepalive=60) # loop client.loop_forever()5.函数计算开发5.1 index.js应用程序const request = require('request');const url = require('url');const crypto = require('crypto');const TableStore = require('tablestore');const co = require('co');const RPCClient = require('@alicloud/pop-core').RPCClient;const config = require("./config");//iot clientconst iotClient = new RPCClient({ accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey, endpoint: config.iotEndpoint, apiVersion: config.iotApiVersion});//ots clientconst otsClient = new TableStore.Client({ accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey, endpoint: config.otsEndpoint, instancename: config.otsInstance, maxRetries: 20});const options = { url: config.dtplusUrl, method: 'POST', headers: { 'Accept': 'application/json', 'Content-type': 'application/json' }};module.exports.handler = function(event, context, callback) { var eventJson = JSON.parse(event.toString()); try { var imgUrl = config.ossEndpoint + eventJson.events[0].oss.object.key; options.body = JSON.stringify({ type: 0, image_url: imgUrl }); options.headers.Date = new Date().toUTCString(); options.headers.Authorization = makeDataplusSignature(options); request.post(options, function(error, response, body) { console.log('face/attribute response body' + body) const msg = parseBody(imgUrl, body) // saveToOTS(msg, callback); }); } catch (err) { callback(null, err); }};parseBody = function(imgUrl, body) { body = JSON.parse(body); //face_rect [left, top, width, height], const idx = parseInt(10 * Math.random() % 4); const age = (parseInt(body.age[0])) + "岁"; const expression = (body.expression[0] == "1") ? config.happy[idx] : config.normal[idx]; const gender = (body.gender[0] == "1") ? "帅哥" : "靓女"; const glass = (body.glass[0] == "1") ? "戴眼镜" : "火眼金睛"; return { 'imgUrl': imgUrl, 'gender': gender, 'faceRect': body.face_rect.join(','), 'glass': glass, 'age': age, 'expression': expression };}//pub msg to WebApp by IoTiotPubToWeb = function(payload, cb) { co(function*() { try { //创立设施 var iotResponse = yield iotClient.request('Pub', { ProductKey: config.productKey, TopicFullName: config.topicFullName, MessageContent: new Buffer(JSON.stringify(payload)).toString('base64'), Qos: 0 }); } catch (err) { console.log('iotPubToWeb err' + JSON.stringify(err)) } cb(null, payload); });}saveToOTS = function(msg, cb) { var ots_data = { tableName: config.tableName, condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null), primaryKey: [{ deviceId: "androidPhoto" }, { id: TableStore.PK_AUTO_INCR }], attributeColumns: [ { 'imgUrl': msg.imgUrl }, { 'gender': msg.gender }, { 'faceRect': msg.faceRect }, { 'glass': msg.glass }, { 'age': msg.age }, { 'expression': msg.expression } ], returnContent: { returnType: TableStore.ReturnType.Primarykey } } otsClient.putRow(ots_data, function(err, data) { iotPubToWeb(msg, cb); });}makeDataplusSignature = function(options) { const md5Body = crypto.createHash('md5').update(new Buffer(options.body)).digest('base64'); const stringToSign = "POST\napplication/json\n" + md5Body + "\napplication/json\n" + options.headers.Date + "\n/face/attribute" // step2: 加密 [Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )] const signature = crypto.createHmac('sha1', config.secretAccessKey).update(stringToSign).digest('base64'); return "Dataplus " + config.accessKeyId + ":" + signature;}5.2 config.js配置文件module.exports = { accessKeyId: '账号ak', secretAccessKey: '账号ak secret', iotEndpoint: 'https://iot.cn-shanghai.aliyuncs.com', iotApiVersion: '2018-01-20', productKey: 'web大屏产品pk', topicFullName: 'web大屏订阅辨认后果的topic',//可选,如果不保留后果,不须要ots otsEndpoint: 'ots接入点', otsInstance: 'ots实例', tableName: 'ots后果存储表',}6. Web端App开发<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>阿里云IoT</title> <style type="text/css"> body { line-height: 1.6; font-family: Arial, Helvetica, sans-serif; margin: 0; padding: 0; background: url(http://iot-face.oss-cn-shanghai.aliyuncs.com/iot-face-yq.png) no-repeat; background-color: #202124; } .face-msg { display: inline; font-size: 32px; color: #5FFFF8; padding: 30px 160px 0px 60px; } </style></head><body> <div style="padding: 190px 10px 0px 360px;"> <div class="face-msg" id='glass' style="color: #5FFFF8"></div> <div class="face-msg" id='gender' style="color: #FF5FE5"></div> <div class="face-msg" id='age' style="color: #FFDD5F"></div> <div class="face-msg" id='expression' style="color: #FC4D4D"></div> </div> <!-- --> <div style="position: relative;padding: 145px 10px 0px 165px;"> <div style="position: absolute;"> <canvas id="myCanvas" width="720px" height="480px"></canvas> </div> <img id='imageUrl' src="" width="720px" height="480px" /> </div> <script type="text/javascript" src="http://iot-face.oss-cn-shanghai.aliyuncs.com/zepto.min.js"></script> <script src="http://iot-face.oss-cn-shanghai.aliyuncs.com/mqttws31.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { initMqtt(); }); var client; function initMqtt() { //模仿设施参数 var mqttClientId = Math.random().toString(36).substr(2); client = new Paho.MQTT.Client("public.iot-as-mqtt.cn-shanghai.aliyuncs.com", 443, mqttClientId); // set callback handlers var options = { useSSL: false, userName: '替换iotId', password: '替换iot token', keepAliveInterval: 60, onSuccess: onConnect, onFailure: function(e) { console.log(e); } }; client.onConnectionLost = onConnectionLost; client.onMessageDelivered = onMessageDelivered; client.onMessageArrived = onMessageArrived; // connect the client client.connect(options); } // called when the client connects function onConnect() { // Once a connection has been made, make a subscription client.subscribe("替换订阅数据更新topic"); } // called when the client loses its connection function onConnectionLost(responseObject) { if (responseObject.errorCode !== 0) { console.error("onConnectionLost:", responseObject); } } function onMessageArrived(message) { fillData(JSON.parse(message.payloadString)) } function onMessageDelivered(message) { console.log("onMessageDelivered: [" + message.destinationName + "] --- " + message.payloadString); } function fillData(data) { $("#age").html(data.age); $("#expression").html(data.expression); $("#gender").html(data.gender); $("#glass").html(data.glass); $("#imageUrl").attr("src", data.imgUrl); var rect = data.faceRect.split(","); //"270,22,202,287" var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = '#03A9F4'; ctx.lineWidth = 2; ctx.beginPath(); ctx.rect(rect[0], rect[1], rect[2], rect[3]); ctx.stroke(); }; </script></body></html>7. 拍照指令触发器/** * package.json 增加依赖:"@alicloud/pop-core": "1.5.2" */const co = require('co');const RPCClient = require('@alicloud/pop-core').RPCClient;const options = { accessKey: "替换ak", accessKeySecret: "替换ak Secret",};//1.初始化clientconst client = new RPCClient({ accessKeyId: options.accessKey, secretAccessKey: options.accessKeySecret, endpoint: 'https://iot.cn-shanghai.aliyuncs.com', apiVersion: '2018-01-20'});const params = { ProductKey: "a1p35XsaOS7", TopicFullName: "相机指令topic", MessageContent: new Buffer('{"action":"takephoto"}').toString('base64'), Qos: "0"};co(function*() { try { //3.发动API调用 const response = yield client.request('Pub', params); console.log(JSON.stringify(response)); } catch (err) { console.log(err); }});物联网平台产品介绍详情:https://www.aliyun.com/product/iot/iot_instc_public_cn ...

March 15, 2023 · 4 min · jiezi

关于javascript:fabricjs设置canvas的clipPath后背景色不显示解决办法

当您在 Fabric.js 中设置 clipPath 后,该门路区域之外的任何内容都将被剪切,包含 canvas 的背景色。因而,如果您心愿 canvas 背景色显示在剪切门路之外的区域,您能够应用以下两种办法之一: (1)应用一个蕴含背景色彩的对象或者一个填充了背景色的矩形作为 clipPath,这样 clipPath 区域内的内容将被保留,而其余区域将绘制为背景色。例如: var rect = new fabric.Rect({ left: 0, top: 0, width: canvas.width, height: canvas.height, fill: 'white'});var circle = new fabric.Circle({ left: 100, top: 100, radius: 50, fill: 'red'});var clipPath = new fabric.Circle({ left: 50, top: 50, radius: 25});canvas.add(rect, circle, clipPath);circle.clipPath = clipPath;在这个例子中,咱们创立一个矩形对象作为背景,而后将它增加到 canvas 上。咱们还创立了一个圆形对象,并将它的 clipPath 属性设置为一个圆形对象。这样,圆形对象将只在圆形 clipPath 区域内显示,并且矩形对象将在 clipPath 区域外显示。 (2)应用 CSS 款式为 canvas 增加背景色。例如: canvas { background-color: white;}在这个例子中,咱们应用 CSS 款式为 canvas 增加背景色。这将在整个 canvas 上绘制一个背景色,即便在应用 clipPath 剪切时,背景色也将持续显示。 ...

March 15, 2023 · 1 min · jiezi

关于javascript:fabricjs-如何为Rect设置背景图片

在 Fabric.js 中,您能够为 fabric.Rect 对象设置背景图片。要设置背景图片,您须要创立一个新的 fabric.Pattern 对象,并将其设置为 fabric.Rect 对象的 fill 属性。 例如,以下代码将一个背景图片利用到 fabric.Rect 对象上: var img = new Image();img.src = 'path/to/image.png';// 期待图像加载实现img.onload = function() { // 创立一个新的 Pattern 对象 var pattern = new fabric.Pattern({ source: img, repeat: 'repeat' }); // 创立一个新的 Rect 对象 var rect = new fabric.Rect({ width: 200, height: 200, fill: pattern }); // 增加 Rect 对象到画布上 canvas.add(rect);};在这个例子中,咱们创立一个新的 Image 对象,并将其加载实现后创立一个新的 fabric.Pattern 对象。而后,咱们应用 fabric.Rect 构造函数创立一个新的矩形对象,并将其 fill 属性设置为咱们刚刚创立的 fabric.Pattern 对象。最初,咱们将矩形对象增加到画布上。 ...

March 15, 2023 · 1 min · jiezi

关于javascript:JavaScript-中-callapplybind-的用法

其实是一个很简略的货色,认真看十分钟就从一脸懵B 到齐全 了解!先看明确上面: 例1 obj.objAge;  //17  obj.myFun()  //小张年龄undefined 例2 shows()  //盲僧  比拟一下这两者this 的差异,第一个打印外面的this 指向obj,第二个全局申明的shows()函数   this 是window ; 1,call()、apply()、bind() 都是用来重定义 this 这个对象的! 如: ` obj.myFun.call(db); //德玛年龄99   obj.myFun.apply(db); //德玛年龄99   obj.myFun.bind(db)(); //德玛年龄99 以上出了bind 办法前面多了个 () 外 ,后果返回都统一! 由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行  2,比照call 、bind 、 apply 传参状况下 ![图片](https://images2015.cnblogs.com/blog/736712/201703/736712-20170316173631526-1279562612.png)obj.myFun.call(db,'成都','上海');  //德玛 年龄 99  来自 成都去往上海obj.myFun.apply(db,['成都','上海']);     //德玛 年龄 99  来自 成都去往上海 obj.myFun.bind(db,'成都','上海')(); //德玛 年龄 99  来自 成都去往上海  obj.myFun.bind(db,['成都','上海'])(); //德玛 年龄 99  来自 成都,上海去往undefined   ...

March 15, 2023 · 1 min · jiezi

关于javascript:Nodejs设备接入阿里云IoT平台设备接入类

1. 筹备工作1.1 注册阿里云账号应用集体淘宝账号或手机号,开明阿里云账号,并通过__实名认证(能够用支付宝认证)__ 1.2 收费开明IoT物联网套件产品官网 https://www.aliyun.com/product/iot 1.3 软件环境Nodejs装置 https://nodejs.org/en/download/编辑器 sublimeText/nodepad++/vscodeMQTT lib https://www.npmjs.com/package/mqtt 2. 开发步骤2.1 云端开发1) 创立高级版产品 2) 性能定义,产品物模型增加属性增加产品属性定义 物模型对应属性上报topic /sys/替换为productKey/替换为deviceName/thing/event/property/post物模型对应的属性上报payload { id: 123452452, params: { temperature: 26.2, humidity: 60.4 }, method: "thing.event.property.post"}3) 设施治理>注册设施,取得身份三元组 2.2 设施端开发咱们以nodejs程序来模仿设施,建设连贯,上报数据。 1.创立文件夹 aliyun-iot-demo-nodejs2.进入文件夹,创立package.json文件,增加内容3.执行npm install命令,装置sdk4.创立thermometer.js文件,增加内容5.执行node thermometer.js命令1) package.json增加阿里云IoT套件sdk依赖{ "name": "aliyun-iot", "dependencies": { "mqtt": "2.18.8" }, "author": "wongxming", "license": "MIT"}2) 下载安装SDK在aliyun-iot-demo-nodejs文件夹下,执行命令 $ npm install3) 应用程序目录构造4) 模仿设施thermometer.js代码/**"dependencies": { "mqtt": "2.18.8" }*/const crypto = require('crypto');const mqtt = require('mqtt');//设施身份三元组+区域const deviceConfig = require("./iot-device-config.json");const options = { productKey: deviceConfig.productKey, deviceName: deviceConfig.deviceName, timestamp: Date.now(), clientId: Math.random().toString(36).substr(2)}options.password = signHmacSha1(options, deviceConfig.deviceSecret);options.clientId = `${options.clientId}|securemode=3,signmethod=hmacsha1,timestamp=${options.timestamp}|`;options.username = `${options.deviceName}&${options.productKey}`;const url = `tcp://${deviceConfig.productKey}.iot-as-mqtt.${deviceConfig.regionId}.aliyuncs.com:1883`;//建设连贯const client = mqtt.connect(url,options);//属性上报的Topicconst topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/property/post`;setInterval(function() { //公布数据到topic client.publish(topic, getPostData());}, 5 * 1000);function getPostData(){ const payloadJson = { id: Date.now(), params: { temperature: Math.floor((Math.random() * 20) + 10), humidity: Math.floor((Math.random() * 40) + 60) }, method: "thing.event.property.post" } console.log("===postData topic=" + topic) console.log(payloadJson) return JSON.stringify(payloadJson);}/* 生成基于HmacSha1的password 参考文档:https://help.aliyun.com/document_detail/73742.html?#h2-url-1*/function signHmacSha1(options, deviceSecret) { let keys = Object.keys(options).sort(); // 按字典序排序 keys = keys.sort(); const list = []; keys.map((key) => { list.push(`${key}${options[key]}`); }); const contentStr = list.join(''); return crypto.createHmac('sha1', deviceSecret).update(contentStr).digest('hex');}设施配置文件 ...

March 15, 2023 · 1 min · jiezi

关于javascript:网易云音乐开源全链路埋点方案曙光埋点dawn

本文作者: 丁立网易云音乐开源了曙光埋点 dawn,一个跨多端的全链路埋点解决方案,旨在结构一个完满的数据理想国。曙光埋点创造性的提出了埋点虚构树(VTree),并在此基础上实现了诸多能力,解决大前端侧埋点艰难、精度差、不稳固、品质不高的问题,并且设计一套残缺的端侧全链路追踪能力,完满助力大数据用户画像、实时归因/离线归因剖析、漏斗剖析、大数据举荐场景。 曙光埋点从埋点设计、到大前端(iOS、Android、H5、RN等)开发、以及埋点校验&稽查、再到埋点数据应用的全链路服务,让客户端的埋点变得真正的好用。目前曾经广泛应用于云音乐各个次要APP。 行业难点&痛点埋点开发成本高:端侧埋点开发,往往是一一坑位进行,坑位上大量且反复的参数,开发成本昂扬;埋点精准度低:资源曝光埋点,复杂度高且准确低,短少全站对立的曝光策略;埋点模型不稳固:mspm以及x-path模式的埋点,独自坑位以及主动坑位计划,很难保障埋点模型的稳固;链路追踪能力弱:端侧没有链路追踪能力,往往须要借助数据侧对离线数据进行简单剖析得来,老本高;埋点品质管控难:从设计、开发,再到验证、以及上线,QA人力来保障老本大、收益小。特色高性能虚构树:曙光埋点提出了埋点对象和虚构树(前面称VTree),view申明成一个对象,原始view树高性能的导出一颗VTree,VTree构建了咱们整个曙光埋点计划的基石;埋点内容结构化:借助于VTree,咱们的埋点内容是结构化的,是具备自我形容能力的,人造具备了高低层级关系,继而做到埋点内容承载坑位、内容、高低层级关系,从而得出有意义的、稳固的spm(Super Position Model)以及scm(Super Content Model);全站对立的曝光策略:跨多端对立的资源曝光策略,做到所见即曝光开始,不可见即曝光完结,大大加重了开发人员的开发成本和出错几率;全链路追踪能力: 端侧弱小的链路追踪能力,100%可追踪用户日志的操作链路关系,完满助力大数据实时归因剖析、离线归因剖析、漏斗剖析、大数据举荐场景,做到不限深度,不限广度的数据分析能力;残缺的埋点迭代治理:弱小的埋点迭代治理平台,专门承载互联网app疾速迭代场景,残缺治理历史记录和多版本并行;多机制的埋点品质保障:线下埋点校验做到开发埋点免去了QA人力,同时保障了埋点上线品质;线上数据稽查保障以全自动的形式发现线上埋点问题;全平台笼罩:笼罩iOS、Android、RN、以及站外内H5,而且极易的可扩大Flutter、weex等其余平台。更多信息能够参见文章 云音乐曙光埋点:还原数据理想国 应用曙光曙光埋点笼罩了iOS、Android、H5、RN,以及埋点治理平台(easyinsight平台),BI分析师在埋点平台设计埋点VTree,端侧开发人员以极低的开发成本、申明式的开发方式导出VTree,联合easyinsight平台的上线前埋点校验以及线上数据稽查,即进步了开发效率,又保障了埋点品质。 更加具体的曙光埋点应用,参见 曙光埋点-文档 行业比照曙光 与 x-path系列x-path系列形式的埋点,比拟有代表性的是Mixpanel(游戏)、GrowingIO、网易HubbleData、以及美团,次要特点是强化无痕埋点,埋点坑位后关联,数据后处理;实用的场景次要是一些UI复杂度低,比拟固定的场景,这样能够使得从view原始树生成x-path,用来惟一标识一个埋点坑位变得可行。比方典型应用场景是按钮的点击、页面的曝光等场景,对高精度的资源位曝光有些有力。其中美团在自有动态化计划业务场景做可视化埋点,曙光目前也在H5流动场景反对可视化埋点。 然而毛病也很显著,就是不实用简单业务场景,埋点模型不稳固,对于埋点品质要求特地高的业务来说无奈应用该计划。埋点坑位后关联,数据后处理,老本也很大,应用也诸多不便。 性能曙光x-path系列VTree可视化反对(贯通全流程)无可视化埋点反对H5反对(美团)埋点内容结构化层级化 & 可高度定制平铺(参数冗余、信息量少)埋点模型稳固(spm&scm)高度稳固低(后关联)端侧开发成本个别(申明式)低全链路链路追踪弱小(对立范式)个别(依靠大数据后处理)全平台对立的曝光策略抹平列表&非列表;全平台对立;弱化曝光埋点埋点校验&数据稽查弱小(可视化校验 & 线上稽查)弱曙光 与 坑位mspm系列坑位mspm系列的埋点计划,是目前行业内大多数公司采纳的计划,比方腾讯、字节、快手、美团、以及晚期的云音乐;该计划埋点坑位独立,往往通过机器生成的 mspm 字符串来标识埋点坑位,然而通常mspm都是无意义的字符串。这个计划可灵便适应各种简单业务场景,并且依靠大公司弱小的大数据能力,也能够实现很不错的漏斗剖析、数据归因等能力。 然而客户端开发/保护老本高,特地是资源位曝光埋点,做不到端内列表、非列表策略对立,更做不到全平台策略对立,实现起来又比拟艰难,这也是最容易产生bug的中央。因为端侧不参加链路追踪,准确归因能力大数据侧比拟艰难,没有对立范式来对立解决。 性能曙光x-path系列VTree可视化反对(贯通全流程)无埋点内容结构化层级化 & 可高度定制平铺(参数冗余、信息量少)端侧开发成本个别(申明式)低全链路链路追踪弱小(对立范式)个别(依靠大数据后处理)全平台对立的曝光策略抹平列表&非列表;全平台对立;弱化曝光埋点曝光埋点高精度高精度(解决遮挡)弱埋点校验&数据稽查弱小(可视化校验 & 线上稽查)弱曙光 与 四段式spm四段式spm是在坑位mspm系列的根底上,赋予spm层级关系(站点.页面.区块.区块内)信息,阿里大量应用该计划,晚期云音乐也做过这方面的尝试;该计划让埋点坑位有肯定的意义,在埋点治理过程中也更加不便一些。 然而四段式也就限定了模式,灵便度升高,也短少端侧明确的VTree构造,对于埋点稳定性、埋点校验/数据稽查、埋点内容结构化,都有一些能力局限。 性能曙光x-path系列VTree可视化反对(贯通全流程)无埋点迭代治理可视化、实用迭代并行个别埋点内容结构化层级化 & 可高度定制平铺(参数冗余、信息量少)端侧开发成本个别(申明式)低全链路链路追踪弱小(对立范式)个别(依靠大数据后处理)全平台对立的曝光策略抹平列表&非列表;全平台对立;弱化曝光埋点曝光埋点高精度高精度(解决遮挡)弱埋点校验&数据稽查弱小(可视化校验 & 线上稽查)弱云音乐落地因为曙光埋点能够带来的这些益处,截止到目前为止,云音乐APP曾经全面拥抱曙光,笼罩简直全副的P0/P1业务场景,从双端客户端、H5、RN等,到数仓、大数据举荐等,曾经全数切换到曙光。 依靠于稳固的VTree构造,以及弱小的埋点校验&埋点数据稽查,QA人力已齐全开释,数据相干Bug也大幅降落,曾经很长时间没有呈现过因为资源曝光不准确而导致的数据问题了。 社区dawn 打算建设一个对于端侧埋点的凋谢社区,如果你对客户端侧埋点或者埋点数据分析感兴趣,请与咱们分割,或者能够在 dawn-discussions 跟咱们进行交换。 Github:https://github.com/eventtracing/dawn官网与文档:https://eventtracing.github.io欢送退出微信官网答疑群 最初本文公布自网易云音乐技术团队,文章未经受权禁止任何模式的转载。咱们长年招收各类技术岗位,如果你筹备换工作,又恰好喜爱云音乐,那就退出咱们 grp.music-fe(at)corp.netease.com!

March 14, 2023 · 1 min · jiezi

关于javascript:前端食堂技术周刊第-74-期RspackNew-in-Chrome-111重新认识-CSS-优先级

美味值: 口味:碧螺知春拿铁 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly本期摘要字节跳动自研 Web 构建工具 Rspack 正式公布TypeScript’s Migration to ModulesNew in Chrome 111重新认识 CSS 优先级2023 动态站点生成器盘点Sandworm AuditMrmUX glossary大家好,我是童欧巴。欢送来到前端食堂技术周刊,咱们先来看下上周的技术资讯。 技术资讯1. 字节跳动自研 Web 构建工具 Rspack 正式公布 天下苦 Webpack 久已,Rspack 闪亮退场,如下是社区对 Rspack 的积极响应: 与 Webpack 官网正式确立单干关系Nx 内置 Rspack 作为官网构建计划之一unplugin 增加对 Rspack 的实验性反对vue-rsloaderGatsby 公布了 gatsby@alpha-rspack 版本Netlify 示意接入 Rspack 后,有 300%~500% 的本地启动、构建性能晋升与 Turbopack 更加激进的路线相比,Rspack 抉择了与 Webpack 生态兼容的路线。 这让咱们想起 Deno 和 Bun 的初期路线也是一个抉择激进,一个抉择兼容,起初 Deno 还是做出了斗争,那么 Turbopack,接下来轮到你发言了。:) 2. TypeScript’s Migration to ModulesTS 5.0 将源码迁徙到 ESM,npm 包体积减小 46%,构建工夫缩短 10-25%。 ...

March 13, 2023 · 1 min · jiezi

关于javascript:什么是前端开发领域的-Page-Blink-和-Page-Flicker

我做了一段时间的 Angular 之后,听到共事们解决 Github issue 时,偶然会提到 Page Blink 这个名词。 例如这个: 能够看出如果一个 Angular 利用不足 ngrx store,缓存以及 SSR Transfer State 等机制,就容易呈现 Page Blink 的问题。 以及咱们在 Github 的代码仓库里收到其余开发者报的一个 issue: 这个问题在 3G 网络下尤其显著: Page blink 指的是在前端开发中,当页面从新加载或导航到新的URL时,浏览器中的页面会短暂地"闪动"或"白屏"的景象。 这种景象的呈现次要是因为浏览器在从新渲染页面时须要从新加载 CSS、JavaScript和其余资源文件,这个过程会导致页面上的所有内容都被删除,而后再从新绘制。当浏览器加载资源的工夫很长时,页面就会呈现显著的白屏或闪动景象。 为了防止这种景象的呈现,开发者们通常会采取一些优化策略,比方应用预加载、预渲染等技术,以尽可能减少从新加载资源所需的工夫,并尽可能减少页面的白屏工夫。另外,一些框架和库(如React、Vue等)也提供了一些优化机制,能够在页面从新渲染时尽可能地缩小闪动和白屏景象的呈现。? Page flicker 则是另一个概念:Page flicker指的是在前端开发中,当页面加载时,因为CSS款式或JavaScript脚本的加载程序等起因,页面上的元素会在加载实现前闪动或跳动的景象。 通常状况下,当浏览器开始加载页面时,会先加载HTML内容,而后再加载CSS款式和JavaScript脚本等资源。如果CSS款式或JavaScript脚本的加载程序不正确,或者它们的加载工夫过长,就可能导致页面上的元素呈现闪动或跳动的景象。这种景象在用户体验上会产生肯定的负面影响,升高用户对网站的满意度。 为了防止Page flicker景象的呈现,开发者们通常会采取一些优化策略。比方,将CSS样式表放在文档头部,将JavaScript脚本放在文档底部等等,这些策略能够最大限度地缩小Page flicker的产生。 总之,Page flicker是前端开发中一个常见的问题,须要通过正当的优化策略来防止它的呈现,从而晋升用户体验。 Spartacus 已经修复过的一个 Page Flicker 的问题:

March 13, 2023 · 1 min · jiezi

关于javascript:可视化搭建-组件值校验

组件值校验,即在组件值变动时判断是否满足校验逻辑,若不满足校验逻辑,能够拿到校验错误信息进行谬误提醒或其余逻辑解决。 申明 valueValidator 可开启值校验: import { ComponentMeta } from "designer";const input: ComponentMeta = { componentName: "input", element: Input, valueValidator: () => ({ required: true, maximum: 10, }),};如下面的例子,相当于对组件值做了 “不能为 undefined 且最大值为 10” 的限度。 能够内置 JSONSchema validate 的全副校验规定作为内置规定。反对拓展自定义校验规定。反对异步校验。能够用 selector 绑定任意变量(如全局状态 state 或者以后组件实例的 props 来灵便定义组件值校验规定)。当校验出错时,框架也不会做任何解决,而是将谬误抛给业务,由业务来判断如何处理错误。 接下来咱们来具体说说每一项特色。 错误处理定义了组件值校验后,当校验谬误呈现时,能够通过 selector 的 validateError 拿到错误信息: const input: ComponentMeta = { componentName: "input", element: Input, valueValidator: () => ({ required: true, maximum: 10, }), runtimeProps: ({ selector }) => ({ errorName: selector(({ validateError }) => validateError.ruleName), errorMessage: selector(({ validateError }) => validateError.payload), }),};ruleName: 校验规定名称。payload: 该规定未命中时的返回值,校验函数返回什么,这里拿到的就是什么。内置的校验函数返回的是错误信息文案。拿到校验谬误后,通过 runtimeProps 传给组件,咱们可通过组件本身或 element 减少对立的组件 React 容器层解决并展现这些错误信息。 ...

March 13, 2023 · 2 min · jiezi

关于javascript:vue2614的前端微服务改造方案

老我的项目vue2.6.14的前端微服务革新计划微前端思维基于接口协议:子利用依照协定导出几个接口,主利用在运行过程中调用子利用导出的这几个接口基于沙箱隔离:主利用创立一个隔离环境,让子利用根本不必思考本人是在什么环境下经营,依照一般的开发思路进行开发即可基于模块协定:主利用把子利用当作一个模块,和模块的应用形式无异计划抉择路由散发动态资源与iframe联合,懂得都懂,问题很大阿里qiankun(基于single SPA):对我的项目侵入性比拟大京东MicroApp(基于Web Components) 须要引入脚手架革新腾讯wujie(基于Web Components) ,刚开源,未深刻理解webpack5(module-federation)微服务项目,联合老我的项目只需降级vue-service到5.0以上即可应用实现思路主我的项目订阅服务子项目公布服务架构分为根底组件服务,中层业务模块,内部门户。我的项目革新内容降级局部依赖,webpack版本升级到5以上,应用其module-federation新个性 "@vue/cli-service": "~5.0.0", "vue":"^2.7.14",批改入口js新增bootstrap.js用于寄存原入口js文件(main.js),mainjs批改点 window.componentsUrl = "http://localhost:1006"; import bootstrap from "./bootstrap"; bootstrap;批改vue.config.js实现bootstrap.js懒加载 { test: /bootstrap\.js$/, loader: "bundle-loader", options: { lazy: true, }, },主我的项目chainWebpack示例(基于本地服务ip订阅): config .plugin("module-federation-plugin") .use(require("webpack").container.ModuleFederationPlugin, [ { name: "web", remotes: { app1: "app1@http://localhost:8084/remoteEntry.js", }, }, ]);子项目chainWebpack示例(公布子项目组件或者页面) config .plugin("module-federation-plugin") .use(require("webpack").container.ModuleFederationPlugin, [ { name: "app1", // 模块名称 filename: "remoteEntry.js", exposes: { // 对外裸露的组件 "./HelloWorld": "./src/components/HelloWorld.vue", }, }, ]);dev代理配置(路由重定向到所订阅的服务) "/componentsService": { changeOrigin: true, target: process.env.VUE_APP_OA_componentsUrl, pathRewrite: { ["^" + "/componentsService"]: "", }, }, "/workflowService": { changeOrigin: true, target: process.env.VUE_APP_workflowUrl, pathRewrite: { ["^" + "/workflowService"]: "", }, },页面模块共享示例zc-workflow-web服务发布页面 ...

March 11, 2023 · 1 min · jiezi

关于javascript:20230308-20230310-更新面试问题

高级开发者相干问题41.垂直居中的计划有哪些, 简略手写一下?【CSS】答复链接:https://github.com/pro-collection/interview-question/issues/41 42.程度居中的计划有哪些, 简略手写一下?【CSS】答复链接:https://github.com/pro-collection/interview-question/issues/42 43.未知高度和宽度元素的程度垂直居中的计划有哪些, 简略手写一下?【CSS】答复链接:https://github.com/pro-collection/interview-question/issues/43 中级开发者相干问题37.对于 JS 闭包理解多少【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/37 38.手写实现一下 lodash.get?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/38 39.JS 中 this 指向问题理解多少?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/39 40.JS 深拷贝有哪些形式, 手写实现一下?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/40 44.数组去重形式有哪些,简略手写一下?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/44 45.cookie 和 session 有什么区别?【网络】答复链接:https://github.com/pro-collection/interview-question/issues/45 46.银行卡号四位空一位, 例如:6222023100014763381 -->6222 0231 0001 4763 381【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/46 47.js 宏工作与微工作都是指什么, 优先级如何?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/47 48.commonjs 模块援用标准有哪些?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/48 49.fetch 理解多少?【网络】答复链接:https://github.com/pro-collection/interview-question/issues/49 50.数字字符串千分位解决(正则与非正则)?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/50 51.手写防抖函数【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/51 52.process.nextTick, setTimeout 以及 setImmediate 三者的执行程序?【JavaScript】答复链接:https://github.com/pro-collection/interview-question/issues/52

March 10, 2023 · 1 min · jiezi

关于javascript:关于-varlet和const-关键字定义变量的一些归纳

constThe const declaration creates block-scoped constants, much like variables declared using the let keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be redeclared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed常量是块级范畴的,十分相似用 let 语句定义的变量。但常量的值是无奈(通过从新赋值)扭转的,也不能被从新申明。文档形容实际://eg1:const a = 12if (a) { const a = 10 console.log(a)}console.log(a)//console:>10>12//eg2:const a = new Object({name: 'jack'})const b = new Object({name: 'jack'})a.name = 'peters'delete b.nameconsole.log(a,b)//console:> [object Object] { name: "peters" },[object Object] { ... }//eg3:/*数组shift办法用于删除数组第一个元素数组pop办法用于删除数组最初一个元素*/const a = new Array(1)const b = new Array(1)a[0] = 'peters'b.shift() //[] 后果和pop()一样console.log(a,b)//console:>["peters"],[]key points:block-scoped (块作用域)value can't be changed, and it can't be redeclared (常量的值不可被更改,常量也不能从新被申明)在申明的同一语句中必须指定它的值 (因为申明的常量值是不可更改的)However, if a constant is an object or array its properties or items can be updated or removed (const定义的常量是对象或数组时,它们的属性或者items(数组中的一项或某项)能被赋值更新或移除(删除))varThe var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value. ...

March 10, 2023 · 5 min · jiezi

关于javascript:Js-比较两个对象的键名与键值是否相等

文中还应用了sort函数来排序,这样做的益处是只管对象程序不统一也能够比拟相等 let obj = { leftDom1: 'rightDom1', leftDom2: 'rightDom1', leftDom3: 'rightDom3', leftDom4: 'rightDom2', }; let obj2 = { leftDom2: 'rightDom1', leftDom3: 'rightDom3', leftDom4: 'rightDom2', leftDom1: 'rightDom1', }; function compareObjects(obj1, obj2) { const keys1 = Object.keys(obj1).sort(); const keys2 = Object.keys(obj2).sort(); if (keys1.length !== keys2.length) { return false; } for (let i = 0; i < keys1.length; i++) { if (keys1[i] !== keys2[i] || obj1[keys1[i]] !== obj2[keys2[i]]) { return false; } } return true; } console.log(compareObjects(obj, obj2)); // true

March 10, 2023 · 1 min · jiezi

关于javascript:HHDESK便捷功能介绍一

作为一个桌面软件,HHDESK致力于为不便用户,为用户节约精力和工夫。本篇简略介绍一下几个实用功能。 1 快捷压缩文件思考到很多人压缩文件是为了传输,并且在传输时喜爱把文件放在桌面上,所以HHDESK出了一键压缩至桌面性能。 如图所示,右键文件可间接抉择压缩按需要,可抉择更换目录弹出如下对话框。点击“桌面”便可 2 备份性能备份的重要性显而易见。 举例,本次笔者须要把HHDESK相干文章备份,流程如下:点击左上角“文件”,抉择备份抉择须要备份的文件,可按住“Ctrl”多选,而后点击“保留”即可。 3 设置罕用文件夹常常应用的文件夹,可在文件治理栏内设置为罕用,进步工作效率当前便可通过点击箭头所示按钮,在下拉框选项中间接点击进入。

March 10, 2023 · 1 min · jiezi

关于javascript:JS-ES6-Destructuring-语法-JS-解构分配语法使用

本节中次要介绍一下 js 中构造赋值语法的应用,首次看到这种写法 const { a, b, c } = myObject; 可能会感到纳闷,当你看完本章,置信会对解构赋值有更清晰的理解。 具体内容参考:http://javacorn.com/

March 10, 2023 · 1 min · jiezi

关于javascript:行为验证码验证类型的讲解

前言最近在开发行为验证码,常常涉及到对于验证类型的相干内容。但应用起来不太纯熟,空闲之余,总结一下我对行为验证码验证类型的了解。 验证类型概述滑动拼图翻新行为式验证,轻松一滑实现拼图,体验极佳,秒速通过验证。简洁高效,在保障用户极致体验的同时,抵挡机器危险。实用于谋求用户体验的场景。 # 生成背景图 basemap1 = Image.open(bg).convert("RGBA") # 背景图 if basemap1.size != size: # 须要裁切或拉伸 basemap1 = Graphics.crop(basemap1, size[0], size[1]) puzzle1 = Image.open(url_absolute(img)).convert("RGBA") # 方块图,蒙板 # 旋转角度 if rotate == 2: angle = randint(0, 360) elif rotate == 1: angle = choice([0, 90, 180, 270]) else: angle = 0 # angle = 45 if angle: puzzle1 = puzzle1.rotate(angle, resample=Image.Resampling.BILINEAR) puzzle1.putalpha(ImageEnhance.Brightness(puzzle1.split()[3]).enhance(alpha)) # 设置透明度,0-1之间 # 产生随机地位 img_size = puzzle1.size # 滑动图片尺寸 spacing = 0 # 滑动图片在底图地位周围间距,临时应用0,小图片中的图案自身有20px边距 # 随机地位 x = randint(img_size[0] + spacing, size[0] - img_size[0] - spacing) y = randint(spacing, size[1] - img_size[1] - spacing) basemap1.paste(puzzle1, (x, y), puzzle1) # 拷贝 # 方块滑动图 # basemap2 = Image.open(url_absolute(bg)).convert("RGBA") basemap2 = Image.open(bg).convert("RGBA") if basemap2.size != size: # 须要裁切或拉伸 basemap2 = Graphics.crop(basemap2, size[0], size[1]) puzzle2 = Image.open(url_absolute(img)).convert("RGBA") if angle: puzzle2 = puzzle2.rotate(angle, resample=Image.Resampling.BILINEAR) # 旋转 basemap2 = basemap2.crop((x, y, x + img_size[0], y + img_size[1])) # 裁切 puzzle2.paste(basemap2, (0, 0), puzzle2) # 替换成长条形滑动块 strip = Image.new('RGBA', (img_size[0], size[1]), (255, 255, 255, 0)) strip.paste(puzzle2, (0, y), puzzle2) # 拷贝文字点选程序点击图中文字,全新行为验证,安全性极高,保障验证平安。进步机器辨认难度的同时,保障实在用户可读。实用于平安要求较高的业务场景。 ...

March 9, 2023 · 4 min · jiezi

关于javascript:day28mongodb

day28-mongodb一、介绍 1.数据库介绍2.数据库分类3.mongodb介绍二、下载安装 三、命令行操作 1.基本操作 在cmd输出mongo 退出mongodb应用exit 查看所有数据库列表----show dbs----此命令不显示空库 创立数据库或切换数据库--use 数据库名---存在则切换,不存在则创立 查看库中所有表---show tables 或 show collections 数据库中的表不须要创立,增加数据会主动生成表 db.表名.insert(JSON格局数据)---数据是对象则增加一条,是数据则增加多条 删除表---db.表名.drop() 删除库---需进入要删除的库,后执行命令--db.dropDatabase()***2.数据操作 2.1 增 db.表名.insertMany([{},{},{}]) 增加一条数据就是数据中的一个对象,多条数据就是数组中的多个对象 2.2 删 删除已存在的文档数据---db.表名.deleteOne(条件) 2.3 改 依据指定条件,将数据中的某一部分批改为指定的新数据 db.表名.updateOne({条件}, {$set: {新的数据}}) 让指定条件的数据中的某个数字自增或自减: db.表名.updateOne({条件}, {$inc: {键: 自增多少的数字}}) 2.4 查 查问所有数据:db.表名/汇合名.find() 带条件查问:db.表名/汇合名.find({条件}) 某个键 等于 某个值-----{键: 值} 某个键 大于 某个值-----{键: {$gt: 值}} 某个键 大于等于 某个值-----{键: {$gte: 值}} 某个键 小于 某个值-----{键: {$lt: 值}} 某个键 小于等于 某个值-----{键: {$lte: 值}} 某个键 不等于 某个值-----{键: {$ne: 值}} 某个键 在 某个数组中-----{键: {$in: [值, 值]}} 并且的条件-----{条件, 条件} 或者的条件-----{$or: [{条件}, {条件}]} 以正则表达式作为条件查问----{键: 正则表达式} 空条件示意查问所有---{} 在查问后果中,心愿某些键值对不显示或强制显示--db.表名.find(条件, {键: 0/1})----------- 0示意这个键不显示,1示意这个键要强制显示 统计查问后果的数据的数量-----db.表名.find(条件).count() 统计所有数据的数据量------db.表名.count() 排序------db.表名.find(条件).sort({键: 1/-1})--------- 1示意升序,-1示意降序 数据很多,然而要分页显示,依据以后是第几页来查问须要的数据----db.表名.find().skip(数字).limit(数字)---------- skip中的数据,示意跳过后面多少条数据,开始查问, limit中的数据,示意要查问多少 条数据四、可视化操作 ...

March 8, 2023 · 1 min · jiezi

关于javascript:浅谈移动端单屏解决方案横屏单屏

前文《浅谈挪动端单屏解决方案》中,我介绍了挪动端单屏场景下的一些惯例解决方案。然而,这些计划次要针对的是竖屏的页面,对于一种非凡状况:横屏单屏页面,咱们则须要进一步适配。 强制横屏某些业务场景下,咱们的页面须要用户横屏能力进行浏览和操作 (横屏的网页H5游戏、内嵌在横屏手游中的webview流动页...) 惯例且老本最低的解决方案是:当用户处于竖屏状态下浏览咱们的网页时,咱们只须要在页面上揭示用户手动切换为横屏即可。 然而对于一些锁定屏幕方向的用户来说,还须要解除竖屏能力拜访咱们的页面,用户体验上来说确实大打折扣。 因而,现实状态下,咱们更心愿的交互是:当用户横屏状态时,网页失常拜访;当用户竖屏状态时,展现内容强制横屏。 解决办法如下: 咱们将最外层的容器元素(#app),在竖屏时强行旋转90度即可 <!DOCTYPE html><html lang='en'><head> <meta charset='UTF-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <title>landscape</title> <style> * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; } #app { width: 100%; height: 100%; background: orange; position: absolute; } </style></head><body> <div id='app'> <p>landscape</p> </div></body></html>forceLandscape.js const forceLandscape = (id = '#app') => { const handler = () => { let width = document.documentElement.clientWidth; let height = document.documentElement.clientHeight; let targetDom = document.querySelector(id); if (!targetDom) return; // 如果宽度比高度大,则认为处于横屏状态 // 也能够获取 window.orientation 方向来判断屏幕状态 if (width > height) { targetDom.style.position = 'absolute'; targetDom.style.width = `${width}px`; targetDom.style.height = `${height}px`; targetDom.style.left = `${0}px`; targetDom.style.top = `${0}px`; targetDom.style.transform = 'none'; targetDom.style.transformOrigin = '50% 50%'; } else { targetDom.style.position = 'absolute'; targetDom.style.width = `${height}px`; targetDom.style.height = `${width}px`; targetDom.style.left = `${0 - (height - width) / 2}px`; targetDom.style.top = `${(height - width) / 2}px`; targetDom.style.transform = 'rotate(90deg)'; targetDom.style.transformOrigin = '50% 50%'; } }; const handleResize = () => { setTimeout(() => { handler(); }, 300); }; window.addEventListener('resize', handleResize); handler();};点击页面 强制竖屏 查看成果 ...

March 8, 2023 · 4 min · jiezi

关于javascript:使用JSONPath解析JSON数据

本文由 Deguang 发表于 码路-技术博客 在前端开发中,当接口返回一个简单的嵌套JSON时,获取其中某个固定层级的数据,须要应用链式取值 // 接口数据var obj = { name: "历史书", value: 3, children: [ { name: "明清", value: "3-1", count: 10 }, { name: "近代", value: "3-2", count: 20 } ]}// 获取第二个子类型的valueconst val = obj.children[1].value // 3-2当层级构造再次变长,应用链式取值代码简短,且容易出错如,若这里的数据层级呈现问题,比方children长度仅为1,就会遇到咱们常见的报错:Uncaught TypeError: Cannot read property 'value' of undefined。 为了防止报错导致问题,这里就能够应用 JSONPath 来进行取值。 JSONPath在意识JSONPath前,先理解下xPath。xPath是XML的门路语言,应用门路标识符通过层级构造定位文档元素,例如在HTML 中定位元素: 相似的,JSONPath 是通过门路检索JSON,反对操作符、函数、过滤器等用法,不便疾速定位,下面的value获取,能够用JSONPath 形容为JSONPath('$.children[1].value', obj) 操作符符号形容$查问的根节点对象,用于示意一个ison数据,能够是数组或对象@过滤器断言 (filter predicate) 解决的以后节点对象,相似于iava中的this字段*通配符,示意一个名字或数字*递归搜寻.<name>子节点['<name>'(,'<name>')一个或多个子节点<number> (, <number>)]一个或多个数组下标[start:end]数组片段,区间为[start.end),不蕴含end[?(<expression>)]过滤器表达式,表达式后果必须是boolean函数函数能够在门路的尾部调用,函数的输入是门路表达式的输入 符号形容输入min()获取数值类型数组的最小值Doublemax()获取数值类型数组的最大值Doubleavg()获取数值类型数组的平均值Doublestddev()获取数值类型数组的标准差Doublelength()获取数值类型数组的长度Integer过滤器过滤器是用于筛选数组的逻辑表达式。 操作符形容==等于,但数字1不等于字符1!=不等于<小于<=小于等于>大于>=大于等于=~判断是否合乎正则表达式,例如[?(@.value =~ foo.*?/i)]in所属符号,例如[?(@.size in [s,M)]nin排除size长度empty判空参考:https://goessner.net/articles/JsonPath/

March 8, 2023 · 1 min · jiezi

关于javascript:学习图片14网站生成器框架和内容管理系统

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。理解内容管理系统(CMS),如WordPress和其余站点生成器如何使响应式图像的应用更加容易。 尽管比起手动保留每张图片的交替剪辑并通过Squoosh.app这样的工具进行手工优化必定是一种提高,但将图片压缩作为开发过程中的一个步骤也有一些限度。首先,你不肯定能齐全管制整个网站所应用的图片--网络上大多数面向用户的图片更多的是内容问题,而不是开发问题,它们由用户或编辑上传,而不是与JavaScript和样式表等开发资产一起存在于资源库中。 这通常须要一个以上的图像治理过程:一个开发层面的工作,用于建设和保护网站的图像资产--背景、图标、标记等等;另一个工作是对于通过应用网站产生的图像资产,如编辑团队在帖子中嵌入的照片,或用户上传的头像。尽管上下文可能不同,但最终目标是雷同的:依据开发团队定义的设置自动编码和压缩。 侥幸的是,你从本地开发工作流程中理解到的图像处理库能够在任何状况下应用。尽管对你的响应式图像标记不可能有一个放之四海而皆准的办法,但这些零碎提供了正当的默认值、配置选项和API挂钩,以以便简化其实现。 动态站点生成器与工作运行器相比,动态网站生成器(如Jekyll或Eleventy)解决图像的形式有一些相似之处。应用这些工具来制作一个能够部署的网站,须要对资产进行治理,包含CSS最小化或转码和捆绑JavaScript。正如你可能设想的那样,这意味着这些工具使你可能以同样的形式解决图像资产,应用你曾经理解过的许多库。 Eleventy的官网图像插件应用Sharp来提供调整大小、生成多种源尺寸、从新编码和压缩,就像你在这里学到的一些工作。 与工作运行器不同,动态网站生成器能够间接理解这些库的配置和应用状况,以及为生产网站生成的标记--这意味着它能够做更多的事件来自动化咱们的响应式图像标记。例如,当作为显示图像的简码的一部分被调用时,这个插件将依据传递给夏普的配置选项输入HTML。 const Image = require("@11ty/eleventy-img");module.exports = function(eleventyConfig) {async function imageShortcode(src, alt, sizes="100vw") { let metadata = await Image(src, { formats: ["avif", "webp", "jpeg"], widths: [1000, 800, 400], outputDir: "_dist/img/", filenameFormat: function( id, src, width, format, options ) { const ext = path.extname( src ), name = path.basename( src, ext ); return `${name}-${width}.${format}` } }); let imageAttributes = { alt, sizes, loading: "lazy" }; return Image.generateHTML(metadata, imageAttributes);}eleventyConfig.addAsyncShortcode("respimg", imageShortcode);};而后能够用这个短码来代替默认的图片语法。 ...

March 8, 2023 · 1 min · jiezi

关于javascript:浅析-SplitChunksPlugin-及代码分割的意义

起因有共事分享webpack的代码宰割,其中提到了SplitChunksPlugin,对于文档上的形容大家有着不一样的了解,所以打算探索一下。 Q:什么是 SplitChunksPlugin?SplitChunksPlugin 是用来干嘛的? A: 最后,chunks(以及外部导入的模块)是通过外部webpack 图谱中的父子关系关联的。CommonsChunkPlugin曾被用来防止他们之间的反复依赖,然而不可能再做进一步的优化。从webpack v4 开始,移除了CommonsChunkPlugin,取而代之的是 optimization.splitChunks。SplitChunksPlugin能够去重和拆散 chunk webpack的中文文档,对SplitChunksPlugin的形容是这样子的: 针对以上的第二点形容新的 chunk 体积大于 20kb(在进行 min+gz 之前的体积),有共事是这么了解的:chunk 大于 20kb 时,webpack会对以后的chunk进行拆包,个别状况下,100kb的包会拆成 5 个包 即 5 * 20kb = 100kb. 如果有并发申请的限度,webpack会主动把某些包合并,如并发申请数是 2 ,那么这个100kb的包将会被拆成 2 个,每个包的大小为50kb,即 2 * 50kb = 100kb。 而我对此示意有不同的认识:既然这个插件是用来对代码进行宰割的,那么没有必要再对代码进行合并,这样子会让这个插件变得不纯正,而且会减少插件逻辑的复杂度,所以这句话的意思应该是宰割进去的新chunk得大于 20kb。 因为大家都不是喋喋不休就能被压服的,所以打算去查查材料,动动手验证一下到底是怎么一回事。 文档资料一、英文文档首先为了防止中华语言博大精深,导致集体了解有偏差,我先去查看了一下英文文档,英文文档上是这么形容的: 关键词 new chunk:新的chunk,只有分离出来的才算是新的chunk吧,那么这句话的意思应该就是新的chunk将会大于20kb。 二、社区文章其次为了再次防止集体英文了解有偏差,到网上去翻阅了一些社区文章: 作者:前端论道链接:https://juejin.cn/post/6844904103848443912起源:稀土掘金 从上图中能够看到,第三方包vue曾经超过了默认的20kb,间接被宰割成一个独自的2.js的包,并不是依照20kb均匀分成多个包。 入手实际// index.jsimport "./a";console.log("this is index");// a.jsimport "vue";import "react";import "jquery";import "lodash";console.log("this is a");// webpack.config.jsconst path = require('path');module.exports = { mode: "production", entry: './src/index.js', output: { filename: '[name].js', path: path.resolve(__dirname, 'dist'), }, optimization: { splitChunks: { chunks: 'all', }, },};编译后果: ...

March 7, 2023 · 1 min · jiezi

关于javascript:TypeScript-与-JavaScript你应该知道的区别

作者:京东批发 杨冰 译自Radix网站的文章,原文链接:https://radixweb.com/blog/typescript-vs-javascript,原文作者:Nihar Raval 正在寻找经验丰富的 JavaScript 开发团队来将您的利用创意变为事实?作为一名开发人员,如果您有机会参加 Web 开发我的项目,您肯定理解 JavaScript 的工作原理。JavaScript 上市多年,已成为开发者社区中风行的脚本语言。 但正如咱们所知,如果一种技术或语言正在崛起,总会有另一种抉择进入市场并与领先者开展强烈竞争。这里有一个新的竞争对手 ——TypeScript。随着 TypeScript 的日益遍及,咱们能够将其视为具备额定性能的 JavaScript 增强版。 谈到 TypeScript,它是一种用于开发大型简单应用程序的开源编程语言。TypeScript 由科技巨头之一——微软——于 2012 年开发,其创立背地的真正起因是解决大型应用程序。 此外,Angular 还应用 TypeScript 进行 Web 开发服务。依据这项钻研,TypeScript 和 JavaScript 别离是开发人员心愿应用的第二和第三大风行语言。你晓得为什么吗? 实际上,JavaScript 被认为是应用程序和网页的次要脚本语言。因而,当初,咱们能够将 JavaScript 用于TezJS 、React等前端框架,以及 Node.Js 和 Deno 框架的后端。 但当初真正的问题是,JavaScript 是为创立大型简单的 Web 应用程序而开发的吗?我想答案是否定的! 在本文中,咱们将比拟这两种编程语言——TypeScript 与 JavaScript,它们之间的关系,它们的区别,并概述每种语言的长处。 但在此之前,在此视频中疾速理解 TypeScript 和 JavaScript 之间的差别。 TypeScript 与 JavaScript:真正的区别如果咱们同时思考两者——TypeScript 与 JavaScript,那么每个 JavaScript 代码在 TypeScript 中都是无效的。这意味着 TypeScript 是 JavaScript 的超集。 换句话说,咱们能够说, ...

March 7, 2023 · 4 min · jiezi

关于javascript:学习图片13自动压缩和编码

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。本课程中的所有语法——从图像数据的编码到反对响应式图像的信息密集标记语言——都是机器与机器之间通信的办法。 客户端浏览器与服务器互相通信有许多形式。响应式图像标记语言(尤其是srcset和sizes)应用较少的字符形容了大量信息。 不论是好是坏,这种简洁是设计进去的:让这些语法不那么简练,从而让开发者更容易了解,可能会让浏览器更难解析它们。字符串的复杂性越高,解析器出错的可能性就越大,或者在不同的浏览器之间呈现无心的行为差别。 然而,能使这些主题感到如此可怕的个性也能为你提供解决方案:机器容易浏览的语法更容易被它们编写。作为Web用户,咱们必定遇到过许多自动化图像编码和压缩的示例:通过社交媒体平台、内容管理系统(CMS)甚至电子邮件客户端上传到Web的任何图像简直都会通过一个零碎来调整大小、从新编码和压缩。 同样地,无论是通过插件、内部库、独立构建过程工具还是负责应用客户端脚本,响应式图像标记语言都很容易适应自动化。 这是围绕自动化图像性能的两个次要问题:治理图像的创立--它们的编码、压缩和你用来填充srcset属性的备用起源--以及生成咱们面向用户的标记。在本模块中,你将理解一些治理图像的罕用办法,作为古代工作流程的一部分,无论是作为开发过程中的一个自动化阶段,还是通过为你的网站提供能源的框架或内容管理系统,或者通过专门的内容交付网络简直齐全抽象化。 自动化压缩和编码咱们不太可能花工夫手动确定每个独自图片的最佳编码和压缩级别的地位,也不会想这么做。只管放弃图像传输尺寸尽可能小很重要,但为每个图片微调压缩设置并从新保留备选源对于咱们日常工作中会减少很多工夫。 正如你在浏览各种图片格式和压缩类型时学到的,图像的最无效编码始终取决于其内容,正如你在响应式图片中学到的,你所需的备选尺寸将取决于这些图像在页面布局中所占据的地位。在古代工作流中,你将综合思考这些决策,而不是独自决定——为图像确定一组正当的默认值,以最好地适应它们所用于的上下文环境。 在为一组照片图像抉择编码时,AVIF在品质和传输尺寸方面是最佳抉择,但其反对无限,WebP提供了一个优化的古代备选计划,而JPEG是最牢靠的默认值。咱们须要为在页面布局中占据侧边栏的图像制作的备选尺寸与咱们在最高断点下占据整个浏览器视口的图像大不相同。压缩设置须要思考到多个后果文件中的含糊和压缩伪影,这样就没有太多的空间来为每个图像刻意缩小每个可能的字节,而须要换取更灵便和牢靠的工作流程。 至于解决自身,有大量的开源图像处理库提供批量转换、批改和编辑图像的办法,它们竞争速度、效率和可靠性。这些解决库容许你一次性对整个目录中的图像利用编码和压缩设置,而无需关上图像编辑软件,并以一种形式保留原始图像源,以便在须要时调整这些设置。它们旨在运行在各种上下文环境中,从本地开发环境到 Web 服务器自身,例如,针对压缩的 Node.js 的 ImageMin 能够通过一系列插件扩大以适应特定应用程序,而跨平台的 ImageMagick 和基于 Node.js 的 Sharp 从一开始就带有惊人的性能。 这些图像处理库使开发者有可能建设专门用于无缝优化图像的工具,作为你的规范开发流程的一部分--确保你的我的项目将始终以尽可能少的开销援用生产就绪的图像源。 本地开发工具和工作流程像Grunt、Gulp或Webpack这样的工作运行器和捆绑器能够用来优化图像资产和其余常见的性能相干的工作,如CSS和JavaScript的最小化。为了阐明这一点,让咱们来看看一个绝对简略的用例:你的我的项目中的一个目录蕴含了十几张摄影图片,打算用在一个面向公众的网站上。 首先,你须要确保这些图片的编码统一、高效。正如你在后面的模块中所学到的,WebP在品质和文件大小方面都是摄影图片的无效默认值。WebP失去了很好的反对,但不是广泛反对的,所以你也要包含一个渐进式JPEG模式的回退。而后,为了利用srcset属性来无效地交付这些资产,你须要为每种编码制作多种备用尺寸。 如果应用图像编辑软件实现此操作,这将是一项反复且耗时的琐事,然而像Gulp这样的工作运行器就是为自动化这种重复性工作而设计的。gulp-responsive插件(利用Sharp)是泛滥选项之一,它们都遵循相似的模式:收集源目录中的所有文件,从新编码它们,并依据你在图像格式和压缩中理解到的雷同标准化的“品质”简写进行压缩。而后将后果文件输入到咱们定义的门路中,筹备在面向用户的img元素的src属性中援用,同时保留原始文件。 const { src, dest } = require('gulp');const respimg = require('gulp-responsive');exports.webp = function() { return src('./src-img/*') .pipe(respimg({ '*': [{ quality: 70, format: ['webp', 'jpeg'], progressive: true }] })) .pipe(dest('./img/'));}有了这样一个过程,如果我的项目中有人不小心将一张编码为大量真彩色PNG的照片增加到蕴含你的原始图像源的目录中,就不会对生产环境造成任何挫伤--无论原始图像的编码如何,这项工作将产生一个高效的WebP和牢靠的渐进式JPEG回退,而且压缩级别能够很容易地进行即时调整。当然,这个过程也确保你的原始图像文件将被保留在我的项目的开发环境中,这意味着这些设置能够在任何时候调整,只有主动输入被笼罩。 为了输入多个文件,你要传递多个配置对象--除了减少一个宽度和一个像素值,其余都是一样的。 const { src, dest } = require('gulp');const respimg = require('gulp-responsive');exports.default = function() { return src('./src-img/*') .pipe(respimg({ '*': [{ width: 1000, format: ['jpeg', 'webp'], progressive: true, rename: { suffix: '-1000' } }, { width: 800, format: ['jpeg', 'webp'], progressive: true, rename: { suffix: '-800' } }, { width: 400, format: ['jpeg', 'webp'], progressive: true, rename: { suffix: '-400' }, }] }) ) .pipe(dest('./img/'));}在下面的例子中,原始图像(monarch.png)超过了3.3MB。这个工作产生的最大文件(monarch-1000.jpeg)约为150KB。最小的,monarch-400.web,只有32KB。 ...

March 7, 2023 · 2 min · jiezi

关于javascript:前端时间Dayjs

选型Moment.js功能强大、应用宽泛、中文文档详尽。不再保护,体积大,官网不举荐新我的项目应用。Luxon是由Moment.js的原开发者编写。没有中文文档。材料少。star数量:13.6KDate-fns反对 Tree shaking,能够依据须要进行按需引入。没有中文文档,材料少。star数量:31.1KDay.js是一个轻量级的 JavaScript 日期库,提供了相似 Moment.js 的 API,并且体积更小。它反对链式操作、格式化和持续时间计算。Day.js 还提供了插件零碎,能够依据须要扩大其性能。有中文文档。star数量:42.4K Day.js罕用APIlet dayjs = require('dayjs')// 1 format 格式化工夫console.log(dayjs('2018-04-04T16:00:00.000Z').format('YYYY-MM-DD HH:mm:ss'), 'format-format-format-format')// 2 isValid 校验是否是一个非法的日期var customParseFormat = require('dayjs/plugin/customParseFormat')console.log(dayjs('2022-01-33').isValid(), '非严格isValid')console.log(dayjs('xxx').isValid(), '非严格isValid')dayjs.extend(customParseFormat)console.log(dayjs('2022-02-31', 'YYYY-MM-DD', true).isValid(), '严格isValid')// 3 day 获取或设置星期几。传入 number 从0(星期天)到6(星期六)。 如果超出这个范畴,它会进位到其余周。console.log(dayjs().day(), '获取明天是周几')console.log(dayjs().day(3).format('YYYY-MM-DD'), '设置为周几')// 4 add 几天后console.log(dayjs().add(7, 'day').format('YYYY-MM-DD'), '几天后')// 5 locale 实例扭转语言 dayjs默认将一周的第一天是周日 周六是最初一天 将'zh-cn'作为参数传进去默认遵循中国地区require('dayjs/locale/zh-cn')console.log(dayjs().locale('zh-cn').startOf('week').format('YYYY-MM-DD'), 'startOf-startOf-startOf')console.log(dayjs().startOf('week').format('YYYY-MM-DD'), 'startOf-startOf-startOf')// 6 fromNow 间隔当初相差多长时间var relativeTime = require('dayjs/plugin/relativeTime')dayjs.extend(relativeTime)console.log(dayjs('1999-01-01').fromNow(true), 'fromNow-fromNow-fromNow')// 7 diff 返回指定单位下两个日期工夫之间的差别。const diffDate1 = dayjs('2019-01-25')const diffDate2 = dayjs('2018-06-05')console.log(diffDate1.diff(diffDate2, 'month'), 'Difference-Difference-Difference')// 8 valueOf 毫秒级工夫戳console.log(+dayjs('2019-01-25').valueOf(), 'Unix-Unix-Unix')// 9 daysInMonth 月份中天数console.log(dayjs('2019-02').daysInMonth(), 'daysInMonth-daysInMonth-daysInMonth')// 10 toObject 返回蕴含工夫信息的 Object。var toObject = require('dayjs/plugin/toObject')dayjs.extend(toObject)console.log(dayjs('2023-03-06').toObject(), 'toObject-toObject-toObject')// 11 isBefore Day.js对象是否在另一个提供的日期工夫之前。console.log(dayjs('2010').isBefore(dayjs('2011')), 'isBefore-isBefore-isBefore')// 12 isBetween 示意 Day.js对象是否在其余两个的日期工夫之间。var isBetween = require('dayjs/plugin/isBetween')dayjs.extend(isBetween)console.log(dayjs('2010-10-18').isBetween('2010-10-19', dayjs('2010-10-25')), 'isBetween-isBetween-isBetween')// 13 dayOfYear 示意 Dayjs的日期是年中第几天,或设置成是年中第几天。var dayOfYear = require('dayjs/plugin/dayOfYear')dayjs.extend(dayOfYear)console.log(dayjs('2023-03-06').dayOfYear(), 'dayOfYear-dayOfYear-dayOfYear')console.log(dayjs('2023').dayOfYear(65).format('YYYY-MM-DD'), 'dayOfYear-dayOfYear-dayOfYear')// 14 QuarterOfYear 减少了 .quarter() API 返回以后实例是哪个季度var quarterOfYear = require('dayjs/plugin/quarterOfYear')dayjs.extend(quarterOfYear)console.log(dayjs('2023-03-06').quarter())

March 6, 2023 · 1 min · jiezi

关于javascript:day26express

day26-express 概念:基于nodejs的http服务器封装好的框架 *一、应用步骤 下载:npm init ---->npm i express导出:const express = require('express')创立服务器:const app = express()监听端口号:app.listen(端口号)解决申请二、申请的解决 ***1.路由办法-----针对不同的申请形式,有不同的办法解决 get post put delete all(解决任意申请,需齐全匹配) use(解决任意申请,匹配结尾)2.门路匹配 齐全匹配 不齐全匹配---?---润饰后面字符最多呈现一次 不齐全匹配---+---润饰后面字符起码呈现一次 不齐全匹配---*---示意*占位的这个中央能够是任意内容 正则匹配---应用正则表达式代表门路 ***restful格调门路---门路/:id-则此时id必传;门路/:id?-此时id非必传 传统形式申请门路的get传递参数获取-----req.qurey restful格调传递参数获取-----req.params3.处理函数 应用一个函数解决此次申请 应用多个函数解决此次申请---最初一个函数后面的所有函数都须要增加第三个参数next,调用next函数能力执行下一步 将多个函数放在一个数组中,用数组解决申请 数组+函数 通过路由器对象解决 创立:router = express.Router() app用use让路由对象解决:app.use(门路,router) router解决跟app解决语法统一----router.get();router.post() 路由器模块化:利用use办法和路由器对象,将解决的具体代码放在其余文件中,不便分工合作 留神:残缺门路 - use门路 = router门路***4.申请信息 申请办法:req.method 客户端ip:req.ip 申请头:req.headers 申请门路:req.url***响应办法 res.end:没有响应头的内容 res.send:带有响应头的内容 res.json:数组或对象内容 res.redirect:跳转到其余路由 res.sendFile:读取页面并响应 内置变量:__dirname:代表以后文件所在文件夹的绝对路径 res.sendStatus:设置响应状态码*三、中间件 概念:在最初一次响应之前,所经验的那些函数就叫中间件-----中间件函数肯定有next1.内置中间件 动态资源托管:app.use(门路,express.static(动态资源文件夹)) 全局内置中间件-----获取post传递的数据 app.use(express.uelencoded({extended:false}))----将post来的数据放在req上,req.body 部分中间件---将代码放到部分的参数中,只在以后作用域无效2.自定义中间件 自定义获取post数据的中间件,中间件的req和最终执行函数中的req是同一个,所以能够在中间件给req增加属性,在最终路由的req就能获取到这个数据3.第三方中间件 下载模块:npm i body-parser 导入这个模块:const bodyParser = require('body-parser') 应用这个中间件:app.use(bodyParser.urlencoded({extended:false}))4.异样解决中间件 app.use((err,req,res,next) => {})----err是报错信息 必须放在所有路由上面---当下面的路由报错了会在这里捕捉到谬误并执行5.404中间件 app.use((req,res,next) => {}) 必须放最所有路由上面,当下面路由都没有匹配到门路时会执行

March 6, 2023 · 1 min · jiezi

关于javascript:JavaScript-中-Signals-的演变

最近,“ Signals ”一词在前端世界中引起了不小的探讨。 在看似很短的工夫内,它们如同在很多前端框架中都有呈现,从 Preact 到 Angular 但它并不是一个新事物。咱们能够追溯到20世纪60年代末的钻研。在其根底上,使第一个电子表格和硬件描述语言(如 Verilog 和 VHDL )得以实现的雷同建模。 甚至在 JavaScript 中,自从申明式 JavaScript 框架诞生以来,咱们就领有了 Signal。随着工夫的推移,它们曾经有了不同的名字,并在这些年里一直地流行起来。但当初咱们又来到了这里,当初是一个很好的机会,让咱们对其产生的起因以及如何应用有更多的理解。 开始有时咱们会诧异地发现,多个团队在完全相同的工夫内达成了相似的解决方案。在申明式 JavaScript 框架的起步阶段,有 3 个计划在 3 个月内相继公布。Knockout.js(2010年7月)、Backbone.js(2010年10月)、Angular.js(2010年10月)。 Angular 的「脏值查看」,Backbone 的 「模型驱动反复渲染」,Knockout 的「细粒度更新」。每个计划都有些许不同,但最终都成为了明天咱们更新 state 和治理 DOM 的根底。 Knockout.js 对本文的主题特地重要,因为它的「细粒度更新」是建设在咱们称之为 Signals 的根底上的。他们最后引入了两个概念:observable(状态)和 computed(副作用),并且在接下来的几年里在业界引入第三个概念 pureComputed(衍生状态)。 const count = ko.observable(0);const doubleCount = ko.pureComputed(() => count() * 2);// doubleCount 更新时执行 console.logko.computed(() => console.log(doubleCount()))狂野大西部 这些模式是在服务端 MVC 开发和过来几年的 jQuery 中学到的混合模式。其中一个特地常见的模式叫做数据绑定,Angular.js 和 Knockout.js 都有,只管实现形式略有不同。 数据绑定 是将局部状态(state)附加到视图树(view tree)某个特定局部的一个办法。能够做到的一个弱小的事件是使其成为双向的。因而,咱们能够让状态更新 DOM,反过来,DOM 事件自动更新状态,所有这些都是以一种简略的申明形式进行的。 ...

March 6, 2023 · 2 min · jiezi

关于javascript:vue-原生table组件封装

<template> <div class="zz-dynamic-table"> <table class="customTable" border cellpadding="0" cellspacing="0"> <thead> <tr v-for="(aitem, i) in newTheadData" :key="'a' + i"> <th :width="bitem.width ? bitem.width : 'auto'" :style="{ width: bitem.width ? bitem.width : 'auto', 'text-align': bitem.align ? bitem.align : 'center' }" v-for="(bitem, j) in aitem" :key="'b' + j" :rowspan="bitem.rowspan" :colspan="bitem.colspan" v-html="bitem.label" ></th> </tr> </thead> <tr v-for="(item, index) in tableData" :key="index"> <td v-for="(item1, key, index1) in item" :key="index1" :align="thArr[index1].align && key === thArr[index1].key ? thArr[index1].align : 'center'" > {{ item1 }} </td> </tr> </table> </div></template><script>export default { name: 'zz-dynamic-table', props: { theadData: { type: Array, default: () => [ { key: 'date', label: '日期', align: 'left' }, { label: '配送信息', children: [ { key: 'name', label: '姓名' }, { label: '地址', children: [ { key: 'province', label: '省份' }, { key: 'city', label: '市区' }, { key: 'address', label: '具体<br/>地址' } ] } ] }, { key: 'zip', label: '编码' } ] } }, data() { return { thArr: [], rows: 1, tableData: [ { date: '323232', name: 'wang', province: 'province', city: 'city', address: 'address', zip: 333 }, { date: '32323221', name: 'wang1', province: 'province1', city: 'city11', address: 'address1', zip: 555 } ], newTheadData: [] } }, created() { this.newTheadData = this.getTheadData(this.theadData) // console.log('newTheadData=', this.newTheadData, this.rows) this.thArr = this.treeToFlat(this.theadData, []) console.log('thArr=', this.thArr) }, methods: { treeToFlat(arr, res) { let result = res arr.forEach(item => { if (item.children?.length) { this.treeToFlat(item.children, result) } else { result.push(item) } }) return result }, //获取最终后果返进来 getTableData() { this.$nextTick(() => { let result = '' if (this.tableData && this.tableData.length) { result = JSON.stringify(this.tableData) } this.$emit('input', result) }) }, addRow() { this.tableData.push({}) }, //数组中是否有children字段 isHaveChildren(arr) { if (!arr) { return false } for (let i = 0; i < arr.length; i++) { let item = arr[i] if (item.children && item.children.length) { return true } } return false }, //获取该列合并的总数 getColCount(data) { let sum = 0 if (!data) { return sum } if (!data.children) { return sum } let _this = this let fn = function(arr) { if (!arr) { return sum } arr.forEach(item => { if (item.children) { fn(item.children) } else { sum++ } }) } fn(data.children) return sum }, //重组thead数据 getTheadData(p) { let params = JSON.parse(JSON.stringify(p)) if (!params) { return [] } let data = [], _this = this var fn = function(arr) { if (!arr) { return [] } // 是否领有多级表头 let rowData = [] if (_this.isHaveChildren(arr)) { arr.forEach(item => { if (item.children) { item.rowspan = 1 item.colspan = _this.getColCount(item) fn(item.children) } else { item.rowspan = arr.length item.colspan = 1 } rowData.push(item) }) } else { arr.forEach(item => { item.rowspan = 1 item.colspan = 1 rowData.push(item) }) } data.unshift(rowData) } if (this.isHaveChildren(params)) { //重组 this.rows = params.length fn(params) } else { //不重组 data.push(params) } return data } }, watch: { theadData(value) { this.newTheadData = this.getTheadData(value) } }}</script><style lang="less" scoped>.zz-dynamic-table { width: 100%;}table { width: 100%; border-color: #777; // border-color: red;}thead { background: #eee;}tr { width: 100%;}th { padding: 3px 2px; min-width: 10%;}td { padding: 3px 2px;}</style>

March 6, 2023 · 3 min · jiezi

关于javascript:动态数据中心扩散动效

成果 <template> <div id="login-box"></div></template><script>import { chartData } from './data'export default { data() { return { option: {} } }, mounted() { this.$nextTick(() => { this.initCharts() }) }, methods: { initCharts() { this.option = { backgroundColor: 'transparent', xAxis: { show: false, type: 'value' }, yAxis: { show: false, type: 'value' }, tooltip: { show: false }, series: [ { type: 'graph', zlevel: 5, draggable: false, coordinateSystem: 'cartesian2d', //应用二维的直角坐标系(也称笛卡尔坐标系) label: { normal: { show: false } }, data: chartData, links: [ { source: '数据中心', target: '分数据中心一' }, { source: '数据中心', target: '分数据中心二' }, { source: '数据中心', target: '分数据中心三' } ], lineStyle: { normal: { opacity: 1, color: '#53B5EA', curveness: 0.5, width: 2 } } }, { type: 'lines', coordinateSystem: 'cartesian2d', z: 1, zlevel: 2, animation: false, effect: { show: true, period: 8, trailLength: 0.01, symbolSize: 24, symbol: 'pin', loop: true, color: 'pink' }, lineStyle: { normal: { color: '#22AC38', width: 0, curveness: 0.5 //值越大,曲度越大 } }, data: [ { coords: [ [170, 200], [400, 200] ] }, { coords: [ [170, 200], [10, 380] ] }, { coords: [ [170, 200], [10, 10] ] } ] } ] } const myChart = this.$echarts.init(document.getElementById('login-box')) myChart.setOption(this.option) } }}</script>

March 6, 2023 · 1 min · jiezi

关于javascript:可视化搭建-定义联动协议

尽管底层框架提供了通用的组件值与联动配置,能够建设对组件任意 props 的映射,但这只是一个能力,还不是协定。 业务层是能够确定一个协定的,还要让这个协定具备拓展性。 咱们先从使用者角度设计 API,再看看如何依据已有的组件值与联动能力去实现。 设计联动协定首先,不同的业务方会定义不同的联动协定,因而该联动协定须要通过拓展的形式注入: import { createDesigner } from 'designer'import { onReadComponentMeta } from 'linkage-protocol'return <Designer onReadComponentMeta={onReadComponentMeta} />首先可视化搭建框架反对 onReadComponentMeta 属性,用于拓展所有已注册的组件元信息,而联动协定的拓展就是基于组件值与组件联动能力的,因而这种是最正当的拓展形式。 之后咱们就注册了一个固定的联动协定,它形如下: { "componentName": "input", "linkage": [{ "target": "input1", "do": { "value": "{{ $self.value + 'hello' }}" } }]}只有在组件实例上定义 linkage 属性,就能够失效联动。比方下面的例子: target: 联动指标。do: 联动成果,比方该例子为,组件 ID 为 input1 的组件,组件值同步为以后组件实例的组件值 + 'hello'。$self: 形容本人实例,比方能够从 $self.value 拿到本人的组件值,从 $self.props 拿到本人的 props。更近一步,target 还能够反对数组,就示意同时对多个组件失效雷同规定。 咱们还能够反对更简单的语法,比方让该组件能够同步其余组件值: { "componentName": "input", "linkage": [{ "deps": ["input1", "input2"] "props": { "text": "{{ $deps[0].value + deps[1].value }}" } }]}下面的例子示意,该组件实例的 props.text 同步为 input1 + input2 的组件值: ...

March 6, 2023 · 3 min · jiezi

关于javascript:面向对象编程

在编写软件时,你所做的大部分工作就是创立和连贯多个值和办法,让他们一起工作,以便提供应用程序的性能。面向对象编程能够帮忙你更容易地,并且是申明式地实现这些性能。 在这篇文章中,你将理解到在JavaScript中开始应用类和面向对象编程办法所须要的所有。 前置常识在浏览本篇文章之前,你须要把握JavaScript的基础知识。 面向对象编程面向对象编程(OOP)是一种编程范式,在大型、简单和踊跃保护的我的项目中,OOP每天都在被应用。 OOP使你更容易创立和治理你应用程序的许多局部,并在不使它们相互依赖的状况下将它们连接起来。接下来,让咱们看看OOP的四个次要概念。 形象OOP中的形象是指只向用户公开必要的性能,同时暗藏简单的外部工作,使程序更容易应用和了解。 举例来说,当你在手机上发送音讯时,所有将你的信息传递给对方的函数和逻辑都是暗藏的,因为你不须要晓得它们是如何工作的。 同样地,在编程中,如果你正在构建一个帮忙金融app验证用户身份和银行信息的API,应用你API的开发者不须要晓得你应用的是哪种数据库系统,也不须要晓得你如何调用你的数据库。他们惟一须要晓得的是要调用的函数,以及他们须要提供的参数。 形象有助于升高复杂性,减少可用性,并使应用程序的变动不那么具备破坏性。 封装封装是将相干代码捆绑在一个独立单元中的过程。封装使代码的其余局部无奈扭转应用程序捆绑局部的工作形式,除非你显式地进入该单元并扭转它们。 举例来说,如果你正在建设一个航班预订的API,把搜寻航班的代码和预订航班的代码离开是有意义的。这样一来,两个不同的开发者就能够无缝地在每个局部工作而不发生冲突,因为每个开发者都没有理由间接操作对方的代码。 封装有助你升高复杂性,减少代码可用性。 继承OOP中的继承升高了代码重复性,使你可能通过继承应用程序局部的属性和办法,在其余中央构建你的应用程序。 OOP中继承的一个重要劣势是升高了代码重复性。 多态在编程中,多态是一个术语,用来形容一个代码或程序,它能够通过依据给定的数据返回一个响应或后果来解决多个类型的数据。 举例来说,你有一个用来向产品目录增加产品的表单,并有三种不同类型的产品。通过多态,你能够创立一个单一类办法来格式化所有品种的产品,而后再将它们增加到数据库中。 多态能够帮忙你打消复杂性和不必要的if和switch语句,因为在编写简单的程序时,这些语句会变得简短。 接下来咱们来看看JavaScript对象。 JavaScript对象JavaScript中的对象是一个无序的键值对汇合,也就是属性和值。对象的键能够是字符串,值能够是任何类型。 接下来,咱们来看看如何在JavaScript中创建对象。 创建对象在JavaScript中创立一个对象相当容易: const car = { name: 'Ford', year: 2015, color: 'red', description: function () { return `${this.name} - ${this.year} - ${this.color}`; }}上述代码申明了一个car对象,对象属性包含name、year、color以及description函数。 拜访对象属性在JavaScript中有两种形式拜访对象属性。咱们接着往下看: 应用点符号 上面的例子展现了如何应用点合乎来拜访对象属性。 const country = { name: 'Spain', population: 4000000, description: function () { return `${this.name} - ${this.population}`; }}如果你有一个像下面所示的对象,你能够应用objectName.keyName的格局,它应该返回给定键的值: console.log(country.name); // returns 'Spain'应用数组符号 上面的例子展现了如何应用数组符号来拜访对象属性。 const job = { role: "Software Engineer", 'salary': 200000, applicationLink: "meta.com/careers/SWE-role/apply", isRemote: true,};如果你有一个像下面所示的对象,你能够应用objectName[keyName]的格局,它应该返回给定键的值: ...

March 6, 2023 · 4 min · jiezi

关于javascript:day25http和第三方模块的下载

day25-http和第三方模块的下载 一、http 1. 介绍 HTTP协定,叫超文本传输协定(Hypertext transfer protocol)。是一个规定,规定了浏览器和服务器之间通信的规定。 http的传输行为,共分为三个步骤:建设连贯进行传输断开连接2. 三次握手 目标:让客户端和服务端都能明确本人和对方是否能接管到音讯 第一次握手:客户端被动给服务端发送音讯,申请连贯 第二次握手: 服务器收到音讯后,给客户端回应一个音讯,示意曾经收到要连贯的申请 第三次握手: 客户端收到服务器的音讯后,给服务器再次发送音讯,示意收到服务器响应的音讯3. 传输 客户端给服务器端发送申请 服务器端给客户端做出响应 3.1 申请 申请行:申请形式;申请门路;协定以及版本 申请形式--get:获取、post:新增、put:批改、delete:删除 申请门路-- 残缺的url跳过协定和域名前面的局部 (服务器中的req.url) 协定以及版本 get:输出地址敲回车;表单默认提交;a标签跳转;引入文件 post:form设置post形式提交 申请头--- 申请行上面的那些键值对。指定这次申请的承受范畴、主机 名、缓存、数据格式。。。 申请空行---空格换行 申请主体--- 就是这次申请发送次要数据 post申请的申请主体肯定是 From Data,源数据是 键=值 let str = '' req.on('data', chunk => { str += chunk.toString() }) req.on('end', () => { console.log(str) }) get申请的数据在地址栏中显示,肯定是Query String Parameters require('queystring').parse(require('url').parse(req.url).query)3.2 响应 http规定,服务器接管申请后,要对客户端进行响应。http规定响应 信息必须遵循响应报文的规定。 3.2.1 响应行 (1)协定和版本 (2)响应状态码:每次申请响应的时候,会带一个数字,示意这次 申请的响应是什么状态 1xx:代表申请已被承受,须要持续解决 2xx:代表申请已胜利被服务器接管、了解、并承受 3xx:代表须要客户端采取进一步的操作能力实现请 4xx:代表了客户端看起来可能产生了谬误,障碍了服务器的解决 5xx:代表了服务器在解决申请的过程中有谬误或者异样状态产生 服务器设置响应状态码:res.writeHead(状态码, 状态形容) (3)响应状态形容:肯定是英文单词 3.2.2 响应头 设置响应头 - 防止中文乱码 res.setHeader('Content-Type','text/html;charset=utf8') 响应信息中的键值对组成的响应头 3.2.3 响应主体 响应给客户端的内容-------res.end(主体内容)4. 四次挥手(1)第一次挥手,客户端被动对服务器发动断开申请(2)第二次挥手,服务器响应收到申请(3)第三次挥手,服务器断开连接 (4)第四次挥手,客户端断开连接二、 第三方模块下载 ...

March 3, 2023 · 2 min · jiezi

关于javascript:如何在服务端渲染fabricjs

Fabric.js 是一个基于 Canvas 的 JavaScript 图形库,次要用于在浏览器中绘制图形和动画。要在服务端渲染 Fabric.js,须要应用 Node.js 和 Canvas 模块。 以下是一个简略的示例代码,用于在服务端应用 Fabric.js 渲染一个矩形: const { createCanvas } = require('canvas');const fabric = require('fabric').fabric;// 创立 Canvas 对象const canvas = createCanvas(400, 400);// 创立 Fabric.js 实例const rect = new fabric.Rect({ left: 100, top: 100, fill: 'red', width: 200, height: 200});// 将图形增加到 Canvas 中const ctx = canvas.getContext('2d');rect.render(ctx);// 将 Canvas 输入为 PNG 图片const fs = require('fs');const out = fs.createWriteStream(__dirname + '/rectangle.png');const stream = canvas.createPNGStream();stream.pipe(out);out.on('finish', () => console.log('The PNG file was created.'));上述代码中,应用 createCanvas 函数创立一个指定大小的 Canvas 对象,并应用 fabric.Rect 创立一个矩形。而后,应用 rect.render 办法将矩形渲染到 Canvas 上。最初,应用 createPNGStream 办法将 Canvas 输入为 PNG 图片,并将输入流写入到文件中。 ...

March 3, 2023 · 1 min · jiezi

关于javascript:Svelte框架介绍

一、Svelte简介Svelte是一个新兴的热门前端框架,作者是 Rich Harris,被称为前端界的【轮子哥】,有Ractive、Rollup 和 Buble开源作品 Svelte 即是一个前端 UI框架,同时也是一个 编译器。在《State of JS survey of 2020》报告中,它被预测为将来十年可能取代React和Vue等其余框架的新兴技术。在开源托管网站Github上,Svelte也取得了超过61k的关注,这仅次于明星框架React和Vue。 二、Svelte的长处事实上,作为一个前端框架,Svelte在语法、应用体验上没有什么特别之处。真正不同的中央,是Svelte对前端AOT(ahead-of-time,能够了解为预编译)的摸索。 如果大家对React、Vue 的设计思路比拟理解的话就会晓得,他们必须引入运行时 (runtime) 代码,用于虚构dom、diff 算法。而Svelte 的设计思路是【通过动态编译缩小框架运行时的代码量,即预编译】,Svelted齐全溶入JavaScript,利用所有须要的运行时代码都蕴含在bundle.js外面,因而不须要额定在引入运行时。 React 和 Vue 都是基于运行时的框架,当用户操作页面进行各种操作扭转组件的状态时,框架的运行时会依据组件状态(state)计算(diff)出哪些DOM节点须要被更新,从而更新视图。这就意味着,基于运行时框架自身所依赖的代码也会被打包到最终的构建产物中,后果是不可避免减少了打包后的体积。 三、Svelte的毛病 作为一个尚处在起步阶段的框架,Svelte 还有很多的有余,如果是在大型的商业我的项目中中应用 , 须要特地的审慎。 四、疾速上手 4.1 创立我的项目和其余前端框架一样,创立一个Svelte我的项目是非常简单的,命令如下。 npm create svelte@latest my-appcd my-appnpm installnpm run dev 而后在浏览器中关上 http://localhost:5173/ 就能拜访对应的页面,运行的成果如下图。如果须要批改端口号,能够关上package.json 文件,而后在启动命令里批改环境变量 PORT。 "scripts": { "dev": "PORT=4000 rollup -c -w",}, 4.2 less配置创立Svelte我的项目的时候,模板自身是不携带任何插件的,如果须要在 Svelte 组件中写 less,须要装置相干的依赖。 npm install svelte-preprocess-less less 而后,在 rollup.config.js 中增加相干的配置,如果没有 rollup.config.js 文件,能够新建一个。 import sveltePreprocess from 'svelte-preprocess';import { less as svelteLess } from 'svelte-preprocess-less';export default { plugins: [ ...

March 3, 2023 · 2 min · jiezi

关于javascript:鲁班软件使用明道云优化项目管理的全过程

一、对于鲁班软件鲁班软件成立于2001年,是推动中国建筑业走进工程量电算化时代的开拓者;同时给最近很火的元宇宙提供了要害数字工具,推动智慧城市、智慧楼宇、数字中国建设,工具包含鲁班工程治理数字平台和鲁班BIM/CIM开发者平台。 目前公司5大外围产品,数字基建、数字施工、数字造价、Motor和CIM;3大服务赋能,鲁班参谋、鲁班教育和鲁班研究院。鲁班教育次要是跟同济学院、四川大学单干,将BIM技术带入高校中,鲁班研究院次要是钻研行业的倒退方向,给大家输入一些报告。 鲁班软件在中国曾经辐射到23个省市,目前基建板块有130多个我的项目。在为建筑工程行业做数字化平台的时候,明道云这样的工具可能很好地帮忙咱们落地相干管理系统。 二、我的项目背景我是项目管理部的负责人,然而我常常困惑于公司有多少个我的项目在执行,多少个我的项目曾经交付,我的项目的进度如何,我的项目的老本是多少等等。公司曾经服务过这么多的我的项目,为行业做了那么多的数字化平台,却困惑于本身治理。 三、我的项目痛点接触明道云之后,咱们将本人的诉求通知了对接的参谋。首先就是统计很艰难,领导须要一份数据,大家就要连夜加班去赶数据,如果还要有不同维度的剖析,比方从经营、财务、销售、我的项目交付等不同维度一一剖析,那就要破费更多的工夫能力实现。其次各个部门收集上来的信息不同步,不晓得哪个数据才是最精确的,汇总起来十分艰难,且经验层层汇总后数据缺失较多。因而各部门的对于优化治理的呼声也是越来越高。 四、产品选型整顿好外部的需要文档后,咱们就开始了产品选型。在考查了低代码、零代码、传统项目管理成品软件后,咱们共选了七家供应商,通过两到三个月的试用,最终抉择了明道云。抉择明道云是因为市面上没有一款软件能满足我的所有需要,而明道云却能够满足我的绝大部分需要。 五、建设指标咱们的需要场景包含:我的项目信息收集、我的项目材料治理、我的项目数据汇总统计、人员合作、我的项目预警、撑持人员绩效考核,以上这些也是咱们建设项目管理平台的指标。 六、实施方案在施行过程中,咱们也遇到了一些艰难,尤其平台波及部门较多,通过20多年的积攒,每个部门都曾经造成了本人独有的一套治理办法,如何推动大家退出明道云进行共创成为一大难题。咱们与总经办、总裁办一起单干组建了一支搭建队伍,公布了实施方案,并欠缺了对应的考核机制,明确了我的项目管理系统的方向内容以及各个角色的职责,以此促成大家踊跃退出。 七、零碎搭建框架在整体交付过程当中,无非就是要抓好铁三角:进度、品质和老本。这就要求管理层必须及时理解我的项目的实时进度及经营状况,比方我的项目处在哪一阶段,回款状况如何,我的项目相干方变动状况以及后期的一些筹备材料。 在工程行业,材料治理也是一大难题,到我的项目最初补材料时候,你会发现有很多的缺失、脱漏、不合规的状况。所以咱们将交付治理治理利用分为了信息、过程、进度、沟通、材料几大模块。在售前零碎中能够进行任务分配,做一个材料台账,随着我的项目的进行,售前材料移后续会残缺的移交到交付共事的手上。 还有最重要的经营板块,咱们要理解到我的项目实时状况,包含项目前期的估算,每个月的收入状况、回款状况,评估我的项目资金流是否衰弱。 在整个系统实施过程中,也是围绕着进度、品质和老本进行零碎搭建。 八、自主搭建治理平台昨天简略统计了一下,目前咱们在明道云平台共产出了24个利用,用得比拟好的是售前零碎、交付治理、研发治理,其实也就是咱们想抓的全过程治理。从最开始的销售源头开始抓销售的签单率,每个类型产品的销售统计,再到施行阶段售前反对人员相干材料主动转接到交付零碎,解决方案、优良案例集锦的累积。 做软件不可避免地会呈现客户需要蔓延和一些bug,咱们将交付零碎与研发治理进行了数据联动,数据能够间接从交付治理利用中通过工作流流转到研发治理中。研发人员能够及时通晓我的项目目前的一些危险以及客户提出的新需要,并能够依据我的项目紧急情况来排研发资源,不须要每次再去组织一个会议探讨各个我的项目的优先级。 咱们还做了经营数据、人力资源、客户满意度三个利用,这些辅助利用能让咱们更好的治理我的项目。明道云有弱小的工作表、角色权限和视图能力,很好地撑持了咱们去做好企业的数字化经营,疾速地落地我的项目全流程管理系统。 九、试运行阶段售前管理系统包含了售前转施行过程的进度沟通材料、PMO的危险台等。在整个我的项目执行过程中,我的项目的进度跟踪是最艰难的,如果想要第一工夫理解到我的项目的状况,就须要一线人员及时反馈。管理层可能及时接管到音讯,能力疾速协调对应资源。像之前,每个我的项目状况都要层层上报,上报到某一层音讯曾经断了,重大断层,问题无奈解决。 这些利用当初还只是1.0版本,是咱们接触明道云到正式签约期间,用了一个多月的工夫打造的初版。当初,这些利用都还在试运行的过程中,董事长也对咱们提出了很高的要求,要尽快地将所有我的项目上线到明道云当中。咱们的迭代更新之路还很长,置信前面会跟明道云有更深层次的单干。十、试运行成绩我接触明道云一个多月来,最大的领会就是方便快捷。当初在公司内的经营会、周会、月度剖析会等各种会议上,只有领导须要看数据,哪怕是现场提一个维度,我立即就能够给他拉出他想看的数据维度及剖析报表,大大减少我的工作量。以前我常常要加班到12点,最初因为数据不精确还会被领导批评。 当初我间接给他做了一个驾驶舱,他想看的数据、剖析报表全副给他放在一个页面,看起来更加直观、便捷。在交付零碎中也搭建了一个领导看板,他想要看哪个我的项目,就能够点进去查看,理解我的项目的最新进度。并且咱们要求交付人员在交付过程中的数据全副要进入零碎,以此作为他们的绩效考核的一项根据。最初,感激明道云这款产品,让咱们的工作形式失去翻新的扭转。谢谢大家,我的分享到此结束。 本文来自鲁班软件项目管理经理余梦媛,在明道云2022年秋季搭档大会流动演讲,经校对编辑后整顿为演讲精髓。

March 2, 2023 · 1 min · jiezi

关于javascript:2023最全最新中国省市区县乡镇街道行政区划矢量边界经纬度geojsonshp数据免费下载

发现个能够收费下载全国 geojson 数据的网站,举荐一下。可下载的数据蕴含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据(可准确到乡镇/街道级)geojson 数据下载地址:https://geojson.hxkj.vip该我的项目 github 地址:https://github.com/TangSY/echarts-map-demo,喜爱的话,能够给个star哦一、通过API接口,实时获取最新中国省市区县街道级乡镇级geoJSON格局地图数据,可用于Echarts地图展现1、效果图展现 2、示例代码 downloadMapCode() {// 下载mapCode数据 let mapCode = [], cityMapCode = [], provinceMapCode = [], provinceList = [], cityList = [], districtList = []; provinceList = this.codeList.filter(item => { return item.level === 'province' }) cityList = this.codeList.filter(item => { return item.level === 'city' }) districtList = this.codeList.filter(item => { return item.level === 'district' }) districtList.forEach(item => { mapCode.push({ name: item.name, cityCode: item.code, fatherCode: `${item.code.substring(0, 4)}00`, children: [] }) }) // 筛选出直辖市上面的区县 let direct = mapCode.filter(item => { return item.fatherCode.includes('0000'); }) for (let i in cityList) { let children = [] for (let j in mapCode) { if (mapCode[j].fatherCode == cityList[i].code) { children.push(mapCode[j]) } } cityMapCode.push({ name: cityList[i].name, cityCode: cityList[i].code, fatherCode: `${cityList[i].code.substring(0, 2)}0000`, children: children }) } cityMapCode = cityMapCode.concat(direct); for (let i in provinceList) { let children = [] for (let j in cityMapCode) { if (cityMapCode[j].fatherCode == provinceList[i].code) { children.push(cityMapCode[j]) } } provinceMapCode.push({ name: provinceList[i].name, cityCode: provinceList[i].code, fatherCode: '100000', children: children }) } if (provinceMapCode.length === 0) return this.zip.file(`mapCode.json`, JSON.stringify(provinceMapCode)); this.downloadTips = '文件打包压缩中...'; this.zip.generateAsync({ type: "blob" }) .then((content) => { saveAs(content, "mapCode.zip"); }); }, // 下载全国地名和编码(不蕴含边界数据) downloadNameAndCode() { let opts = { subdistrict: 3, //返回下一级行政区 showbiz: false, //最初一级返回街道信息 }; let district = new AMap.DistrictSearch(opts); //留神:须要应用插件同步下发性能能力这样间接应用 district.search('中国', function (status, result) { if (status === 'complete') { getData(result.districtList[0]); } }); let _this = this function getData(data) { let districtList = data.districtList; let blob = new Blob([JSON.stringify(districtList)], { type: 'text/plain;charset=utf-8', }); let filename = '全国省市区县街道和编码(不蕴含边界数据)'; _this.$ba.trackEvent('echartsMap', '全国省市区县街道和编码(不蕴含边界数据)下载', filename); saveAs(blob, `${filename}.json`); //filename } }, echartsMapClick(params) {//地图点击事件 this.$ba.trackEvent('echartsMap', '点击地图', `${params.data.name}-${params.data.cityCode}`); if (params.data.level == 'street') return; //革除地图上所有覆盖物 for (var i = 0, l = this.polygons.length; i < l; i++) { this.polygons[i].setMap(null); } this.cityName = params.data.name; this.cityCode = params.data.cityCode; this.district.setLevel(params.data.level); //行政区级别 this.district.setExtensions('all'); //行政区查问 //依照adcode进行查问能够保证数据返回的唯一性 this.district.search(this.cityCode, (status, result) => { if (status === 'complete') { this.getData(result.districtList[0], params.data.level, this.cityCode); } }); }, loadMapData(areaCode) { AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => { //创立一个实例 var districtExplorer = window.districtExplorer = new DistrictExplorer({ eventSupport: true, //关上事件反对 map: this.map }); districtExplorer.loadAreaNode(areaCode, (error, areaNode) => { if (error) { console.error(error); return; } let mapJson = {}; mapJson.type = "FeatureCollection"; mapJson.features = areaNode.getSubFeatures(); this.loadMap(this.cityName, mapJson); this.geoJsonData = mapJson; }); }); },二、通过获取到的数据整顿了一系列联动数据,每天自动更新,收费下载 ...

March 1, 2023 · 2 min · jiezi

关于javascript:学习图片10响应式图片

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。本节,咱们来深刻理解一下响应式图片。 响应式图像标记能够分为两种状况:一种状况是指标是最无效的图像,另一种是须要对浏览器抉择的图像源进行明确管制的状况。别离能够将它们视为描述性和规范性语法。 在本模块中,咱们将学习这两种办法。首先,介绍srcset和sizes,以及如何依据浏览器理解用户、设施和浏览状况的状况做出最佳抉择。而后应用下<picture>元素,它能依据视口大小和浏览器反对的图像格式等因素对源抉择进行正当管制。 描述性语法描述性语法提供浏览器无关图像源及其如何应用的信息,但最终决策留给浏览器。这是迄今为止更常见的状况;对于绝大多数图像,咱们不会想要精密管制浏览器行为。浏览器领有比Web开发人员更多的信息,并且能够依据此信息做出简单的决策。 我信无奈精确预测用户的浏览上下文——对于他们的硬件、偏好和连贯速度的信息太多,无奈晓得。最好的状况是,咱们能够做出有依据的猜想,但无奈确定每个用户如何体验 Web。从开发人员的角度来看,响应式图像的外围用例是严格以指标为导向的:容许浏览器依据手头领有的信息收回最高效的图像申请。 为了使浏览器可能做出这些抉择,srcset容许咱们提供潜在源列表,以填充单个<img>,而sizes则容许咱们向浏览器提供无关如何出现该<img>的信息。在下一个模块中,咱们再来学习如何应用这些内容。 代码部署后可能存在的BUG没法实时晓得,预先为了解决这些BUG,花了大量的工夫进行log 调试,这边顺便给大家举荐一个好用的BUG监控工具 Fundebug。 交换有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。 本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

March 1, 2023 · 1 min · jiezi

关于javascript:day22闭包和继承

day22-闭包和继承一、闭包 闭包造成原理 闭包:是因为作用域嵌套造成的一种执行空间不被销毁的场景 闭包造成:通常是由大函数嵌套小函数,小函数应用大函数的变量,在大函数外跟小函数产生援用关系 平时函数调用在内存中的执行流程: js执行代码是在 调用栈(call stack) 内存中执行的,函数执行是先在调用栈中造成一个独立的空间,而后在这个空间中执行代码,当空间中的代码执行完结后,空间中的代码跟全局代码无关联,就会销毁这个空间,上面的代码进入调用栈执行,执行完结出栈 。。。 闭包: 全局定义b变量,接管部分中返回的小函数,只有全局变量还存在,部分中的小函数就会始终存在 ,小函数要存在,f1的空间就必须始终存在,f1的空间要始终存在,f1中的变量a就会始终存在,调用全局b函数,执行f1中的小函数,小函数中拜访的f1中的变量,屡次调用其实拜访的是同一个变量a闭包优缺点 长处:全局能够操作部分的变量;缩短了变量的生命周期;爱护了变量的公有性 毛病:闭包的执行空间不销毁,如果滥用闭包会造成内存泄露/溢出(代码停留在内存中不销毁,导 致内存满了,执行不了其余代码)----要销毁这个执行空间,能够将全局接管小函数的变量赋值为null闭包利用场景 a.在循环中执行异步代码,在异步代码中应用循环的变量 b.防抖 c.节流 d.函数柯里化防抖 当某些操作频繁被触发,而咱们只须要最初一次的时候就须要防抖 js中有一个关键字arguments--用于承受所有的实参 document.onmousemove = fn(1000, function (e) { document.querySelectorAll('span')[0].innerText = e.pageX document.querySelectorAll('span')[1].innerText = e.pageY }) function fn(time,handler) { var timer return function() { var _this = this var _arguments = arguments clearInterval(timer) timer = setTimeout(function() { handler.call(_this,..._arguments) },time) } }节流 当某些操作频繁被触发,不须要这么频繁的时候应用节流 document.onmousemove = fn(1000, function (e) { ...

February 28, 2023 · 1 min · jiezi

关于javascript:热点面试题聊聊对-this-的理解

前言欢送关注 『前端进阶圈』 公众号 ,一起摸索学习前端技术...... 前端小菜鸡一枚,分享的文章纯属个人见解,若有不正确或可待探讨点可随便评论,与各位同学一起学习~ 聊聊对 this 对象的了解?定义在执行上下文中的一个属性,它指向最初一次调用这个属性或办法的对象。通常有四种状况来判断。四种状况如下1. 函数调用模式:当一个函数不是一个对象的属性时,间接作为函数来调用时, 严格模式下指向 undefined, 非严格模式下,this 指向全局对象。 // 严格模式"use strict";var name = "window";var doSth = function () { console.log(typeof this === "undefined"); console.log(this.name);};doSth(); // true,// 报错,因为this是undefined// 非严格模式let name2 = "window2";let doSth2 = function () { console.log(this === window); console.log(this.name2);};doSth2(); // true, undefined2. 办法调用模式:如果一个函数作为一个对象的办法来调用时,this 指向以后这个对象 var name = "window";var doSth = function () { console.log(this.name);};var student = { name: "lc", doSth: doSth, other: { name: "other", doSth: doSth, },};student.doSth(); // 'lc'student.other.doSth(); // 'other'// 用call类比则为:student.doSth.call(student);// 用call类比则为:student.other.doSth.call(student.other);3. 结构器调用模式:如果一个函数通过 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象。 ...

February 28, 2023 · 2 min · jiezi

关于javascript:h5-移动端-关于适配-click事件的问题

在开发人脸识别sdk挪动端的时候,须要通过按钮点击申请数据并模仿点击input file的操作,以下代码看似没问题 document.querySelecter('.btn').addEventListener('click', async (e) => { await getSomeDataFromApi(); document.querySelector('.input-btn').click()})它在h5挪动端的确也没有问题,然而低版本的手机下其余平台下内嵌webview里,尤其是在低版本ios下,抖音,支付宝会导致模仿的点击事件没有触发,起因也没找到,一步步的剖析,因为click事件原本就是异步的,而后后面又加了语法糖async,沿着这个想法,我把外面获取数据的操作拿进去,后果低版本的还真就没有问题了,在这记录下,也有相似问题的小伙伴能够在这拍砖探讨。

February 27, 2023 · 1 min · jiezi

关于javascript:可视化搭建-组件值与联动

组件联动是指几个组件互相关联。也就是当一个组件状态变动时,其余组件能够响应。 组件联动是多对多关系的,且目标分为一次性与持续性: 多对多关系:即一个组件能够同时被多个组件联动;多个组件能够同时联动一个组件。一次性与持续性:一次性事件能够被笼罩,持续性事件会同时失效,且要思考叠加关系。肯定水平上,持续性事件能够笼罩一次性事件的场景:组件永远响应最初一个过去的事件即可。 接下来咱们引入 组件值 与 值联动 两个概念,来实现持续性联动性能。 组件值每个组件实例都有一个惟一的组件值。 咱们能够通过 getValue(componentId) 与 setValue(componentId, value) 拜访或更新组件值: const table = { componentName: "table", runtimeProps: ({ componentId, setValue }) => ({ // 给组件注入 onChange 函数,在其触发时更新以后组件实例的组件值 onChange: (value) => setValue(componentId, value), }),};也能够通过 componentMeta.value 申明组件值,比方上面的例子,让组件值与 props.value 同步: const table = { componentName: "table", // 申明 value 的值为组件 props.value 的返回值,并随着组件 props.value 的更新而更新 value: ({ selector }) => selector(({ props }) => props.value),};以上两种形式任选一种应用即可。 为什么一个组件实例只有一个组件值? 一个组件可能同时领有多个状态,比方该组件外部有一个输入框,还有一个按钮,可能输入框的值,与按钮的点击状态都会对其余组件产生联动成果。但这并不意味着一个组件实例须要多个组件值,咱们能够将组件值定义为对象,并正当布局不同的 key 形容不同维度的值: ...

February 27, 2023 · 2 min · jiezi

关于javascript:Loading-done

引子在后面界面开发的过程中,为了加强在与后端交互过程中的用户体验,通常会显示 Loading 动画。Loading 动画会在与后端交互完结的时候敞开。这是一个很惯例的需要,技术实现也不简单。 showLoading();axios.request(...) .then(...) .finally(() => hideLoading());Node.js 和大部分浏览器都在 2018 年实现了对 Promise.prototype.finally() 的反对。Deno 在 2020 年公布的 1.0 中也曾经反对 finally() 了。即便不反对,应用 await 也很容易解决。 showLoading()try { await axios.request(...);}finally { hideLoading();}而在更早的时候,jQuery 在 jqXHR 中就曾经通过 always() 提供了反对。 showLoading();$.ajax(...) .done(...) .always(() => hideLoading());拦截器中的 Loading ... done 逻辑接下来,为了所有接口调用的行为统一,也为了在一个中央解决雷同的事件以达到复用的目标,Loading ... done 的逻辑开始被写在一些拦截器中。这对单个近程接口调用来说,没有问题。但如果有这样一个业务逻辑会怎么样: function async doSomething() { const token = await fetchToken(); const auth = await remoteAuth(token); const result = await fetchBusiness(auth);}假如下面的每个调用都应用了 Axios,而 Axios 在拦截器中注入了 showLoading() 和 hideLoading() 的逻辑。那么这段代码会顺次弹出三个 Loading 动画。一个业务弹多个 Loading 动画的确是个不太好的体验。 ...

February 26, 2023 · 2 min · jiezi

关于javascript:reduce函数封装Promise队列

总结:其外围原理在于如果 return回一个新的Promise,下一个then解决的是这个Promise,会期待这个Promise产生扭转。 (function queue(args) { args.reduce((promise, cul) => { return promise.then((_) => { return new Promise((resolve) => { setTimeout(() => { console.log(cul); resolve(); }, 1000); }); }); }, Promise.resolve()); })([1, 2, 3, 4, 5, 6]);

February 26, 2023 · 1 min · jiezi

关于javascript:利用async与await实现loading动态加载

利用then会期待上一个Promise的解决的个性来模仿一个申请loading。效果图 CSS .div { width: 0%; padding: 10px 0; background-color: violet; text-align: center; transition: width 1s; }JavaScript function sleep(delay = 1000) { return new Promise((resolve, reject) => { // 提早期待,模仿异步申请 setTimeout(() => { resolve(); }, delay); }); } (async function show() { let args = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ]; let div = document.querySelector('.div'); for (let i = 0; i < args.length; i++) { await sleep(); // 获取进度,i=0 所以 +1 除以总长度 乘以 100 let progress = Math.round(((i + 1) / args.length) * 100); // 赋值给元素的宽度和给渲染元素进度 div.style.width = progress + '%'; div.innerHTML = progress + '%'; } })();

February 26, 2023 · 1 min · jiezi

关于javascript:基于threejswebgl的3D元宇宙云展厅

首先看看效果图: 基于 threejs 的 3D 展厅基于 threejs 开发的 3D 展厅,展品能够自在摆放。反对 gltf/glb 格局 github地址:https://github.com/mtsee/vr-hall 初始化实例// 实例化const vr = new VR3DHall({ debugger: true, // 开启调试模式,开启调试模式后能够选中展品,缩放,旋转,位移,console.log中能够查看到数据 maxSize: 25, // 画框最大尺寸 movieHight: 1.5, container: document.getElementById("root"), // 容器 cameraOption: { // 初始视角 position: { x: 0, y: 1.5, z: 0 }, lookAt: { x: 3, y: 1.5, z: 3 }, }, onClick: (item) => { console.log("你点击了", item); },});加载厅模型// 加载厅模型vr.loadHall({ url: "./assets/room1/msg.gltf", planeName: "meishu01", position: { x: 2, y: -0.2, z: 2 }, scale: 1, onProgress: (p) => { console.log("加载进度", p); },});加载其余模型和动画// 加载机器人vr.loadGLTF({ url: "./assets/robot/robot.glb", position: { x: 0, y: 0, z: 0 }, rotation: { x: 0, y: -Math.PI / 2, z: 0 }, scale: 0.2,}).then((gltf) => { // 创立动画 vr.createAnimate(gltf, { animateIndex: 0, duration: 5 });});加载展品数据/** * 画框数据 * @params { * id: '', // 惟一标识 * position: {x: 0, y: 0, z: 0}, // 模型地位 * rotation: {x: 0, y: 0, z: 0}, // 旋转角度 * view: {x: 0, y: 0, z: 0}, // 预览点的地位,挪动到这里,看向position * scale: {x: 0, y: 0, z: 0}, // 缩放比例 * name: '名字', // 名字 * desc: '形容阐明', // 形容阐明 * url: '资源url', // 资源url * type: 'picture', // 'gltf' | 'picture' | 'dot'; // gltf模型,图画模型,图画要自定义画框 * boxColor: '#fff', // 画框色彩 * } */export const data = [ { id: "1", // 惟一标识 position: { x: -0.6593699553026159, y: 1.3866967899666711, z: 7.067726292206915, }, scale: { x: 0.025612307671229958, y: 0.025612307671229958, z: 0.025612307671229958, }, rotation: { x: 0, y: 0, z: 0 }, view: { x: 0, y: 0, z: 0 }, // 预览点的地位,挪动到这里,看向position name: "名字", // 名字 desc: "形容阐明", // 形容阐明 url: "/assets/pictures/1.jpg", // 资源url type: "picture", // 'gltf' | 'picture' | 'dot'; // gltf模型,图画模型,图画要自定义画框 boxColor: "#fff", // 画框色彩 },]; // 加载画框数据vr.loadItems(data);导览// 切换到对应的展品ID的视角vr.viewItem(itemId);开启和敞开重力感应开启敞开重力感应必须在 callback 后执行 ...

February 25, 2023 · 2 min · jiezi

关于javascript:算法思维体操用JavaScript和Python自己实现reduceRight和map链表

引言咱们从一个链表的构造函数开始,“cons”,它接管一个必要参数“head”及一个可选参数“tail”(绝对于反对这样的实现的语言来说)。该构造函数返回一个链表的示意构造体,其中第一个元素为“head”,其余的元素被包裹在“tail“链表中。空链表的话用JavaScript中的undefined或Python中的None来示意。 举例来说,直到渺小变动,”cons(1, cons(2, cons(3, cons(4))))"结构了一个含有4个元素的链表,”1 2 3 4“。 为了便于查看链表中的内容,咱们定义了”listToString“办法来将链表转换为相应的字符串,其中链表元素之间用空格隔开。 ”myMap“办法接管一个一元函数”fn“和一个链表”list“。它循序遍历链表中的每一个元素,并返回一个各元素都被”fn“转化过了的链表。 ”myReduce"办法会对输出的链表从头到尾应用一个reducer函数“fn”,而后返回最终后果。比方,假如链表为“cons(1, cons(2, cons(3,)))”,“myReduce(fn, accm, list)”应该返回执行“fn(fn(fn(accm, 1), 2), 3)”失去的后果。 上述的三个办法都是应用递归实现的,奇妙使用了链表的递归结构。 第1局部:实现“myReduceRight"请实现“myReduceRight”办法。其相似于“myReduce”,不同之处在于它是从尾到头对输出的链表应用reducer函数“fn”的。比方,假如链表为“cons(1, cons(2, cons(3)))",”myReduceRight(fn, accm, list)"应该返回执行“fn(1, fn(2, fn(3, accm)))"失去的后果。 要求: 你须要应用递归来实现,而不是任何显式的for/while循环;你不能在你的实现中应用先前已定义好的”listToString“、”myMap“和”myReduce“办法;你不能批改原始链表。要查看你的实现的正确性,能够验证: ”myReduceRight(xTimesTwoPlusY, 0, exampleList)“应该失去“20”;“myReduceRight(unfoldCalculation, accm, exampleList)"应该示意为”fn(1, fn(2, fn(3, fn(4, accm))))";“myReduceRight(printXAndReturnY, 0, exampleList)"应该依照输出链表的逆序来打印内容。第2局部:实现”myMap2“请基于“myReduceRight"办法实现”myMap2“,其应该在功能性上同质于”myMap“。 对实现的根本要求: 你不能在你的实现中应用先前已定义好的”listToString“、”myMap“和”myReduce“办法;你不能批改任何函数的输入输出特色,包含”myReduceRight“的输入输出特色;你不能在借在”myReduceRight“中投机取巧来助力实现”myMap2“,例如向”myReduceRight“传递暗藏标记以示意非凡解决;你不能应用任何语言原生的非凡数据结构(举例,C++中的”std::vector",Java中的“ArrayList”,Python中的“list”)。如果你的实现满足以下尽可能多的要求,你将取得“加分”: 不要应用任何显式的递归调用。特地地,防止在实现中申明调用“myMap2”;不要在实现中应用任何显式的for/while循环。为此你须要探索下“myReduceRight”的奇妙用法;不要批改原始链表。以下是你能够遵循的几个方向: 列表翻转;在reducer办法中批改链表;奇妙地应用闭包和lambda函数来调整代码执行程序。特地地,思考思考延时执行,如(() -> doSomething)()。要查看你的实现的正确性,能够验证: “listToString(myMap2(plusOne, exampleList))”应该失去“2 3 4 5”;“myMap2(printAndReturn, exampleList)”应该依照正确的秩序打印链表内容(“1 2 3 4”别离各占据一行而不是“4 3 2 1”)。JavaScript代码模板:// Refer to README for detailed instructions.function cons(head, tail) { return { head: head, tail: tail, };}function listToString(list) { if (!list) { return ''; } if (!list.tail) { return list.head.toString(); } return list.head.toString() + ' ' + listToString(list.tail);}function myMap(fn, list) { if (!list) { return undefined; } return cons(fn(list.head), myMap(fn, list.tail));}function myReduce(fn, accm, list) { if (!list) { return accm; } return myReduce(fn, fn(accm, list.head), list.tail);}function myReduceRight(fn, accm, list) { // [BEGIN] YOUR CODE HERE return undefined; // [END] YOUR CODE HERE}function myMap2(fn, list) { // [BEGIN] YOUR CODE HERE return undefined; // [END] YOUR CODE HERE}function main() { let exampleList = cons(1, cons(2, cons(3, cons(4)))); let plusOne = (x) => x + 1; let xTimesTwoPlusY = (x, y) => x * 2 + y; let printXAndReturnY = (x, y) => { console.log(x); return y; }; let unfoldCalculation = (x, y) => 'fn(' + x + ', ' + y + ')'; let printAndReturn = console.log; console.log(listToString(exampleList), 'should be 1 2 3 4'); console.log(listToString(myMap(plusOne, exampleList)), 'should be 2 3 4 5'); console.log(myReduce(xTimesTwoPlusY, 0, exampleList), 'should be 26'); console.log( myReduce(unfoldCalculation, 'accm', exampleList), 'should be fn(fn(fn(fn(accm, 1), 2), 3), 4)' ); console.log(myReduceRight(xTimesTwoPlusY, 0, exampleList), 'should be 20'); console.log( myReduceRight(unfoldCalculation, 'accm', exampleList), 'should be fn(1, fn(2, fn(3, fn(4, accm))))' ); console.log('Below should output 4 3 2 1 each on a separate line:'); myReduceRight(printXAndReturnY, 0, exampleList); console.log(listToString(myMap2(plusOne, exampleList)), 'should be 2 3 4 5'); console.log('The two outputs below should be equal:'); console.log('First output:'); myMap(printAndReturn, exampleList); console.log('Second output:'); myMap2(printAndReturn, exampleList);}main();Python代码模板:# Refer to README for detailed instructions.from __future__ import print_functionclass LinkedList: def __init__(self, head, tail): self.head = head self.tail = taildef cons(head, tail=None): return LinkedList(head, tail)def listToString(list): if list is None: return "" if list.tail is None: return str(list.head) return str(list.head) + " " + listToString(list.tail)def myMap(fn, list): if list is None: return None return cons(fn(list.head), myMap(fn, list.tail))def myReduce(fn, accm, list): if list is None: return accm return myReduce(fn, fn(accm, list.head), list.tail)def myReduceRight(fn, accm, list): # [BEGIN] YOUR CODE HERE return None # [END] YOUR CODE HEREdef myMap2(fn, list): # [BEGIN] YOUR CODE HERE return None # [END] YOUR CODE HEREdef main(): exampleList = cons(1, cons(2, cons(3, cons(4)))) plusOne = lambda x: x + 1 xTimesTwoPlusY = lambda x, y: x * 2 + y def printXAndReturnY(x, y): print(x) return y def unfoldCalculation(x, y): return "fn(%s, %s)" % (str(x), str(y)) printAndReturn = print print(listToString(exampleList), "should be 1 2 3 4") print(listToString(myMap(plusOne, exampleList)), "should be 2 3 4 5") print(myReduce(xTimesTwoPlusY, 0, exampleList), "should be 26") print(myReduce(unfoldCalculation, "accm", exampleList), "should be fn(fn(fn(fn(accm, 1), 2), 3), 4)") print(myReduceRight(xTimesTwoPlusY, 0, exampleList), "should be 20") print(myReduceRight(unfoldCalculation, "accm", exampleList), "should be fn(1, fn(2, fn(3, fn(4, accm))))") print("Below should output 4 3 2 1 each on a separate line:"); myReduceRight(printXAndReturnY, 0, exampleList) print(listToString(myMap2(plusOne, exampleList)), "should be 2 3 4 5") print("The two outputs below should be equal:") print("First output:") myMap(printAndReturn, exampleList) print("Second output:") myMap2(printAndReturn, exampleList)if __name__ == "__main__": main()最终实现:JavaScript实现:// Refer to README for detailed instructions.function cons(head, tail) { return { head: head, tail: tail, };}function listToString(list) { if (!list) { return ''; } if (!list.tail) { return list.head.toString(); } return list.head.toString() + ' ' + listToString(list.tail);}function myMap(fn, list) { if (!list) { return undefined; } return cons(fn(list.head), myMap(fn, list.tail));}function myReduce(fn, accm, list) { if (!list) { return accm; } return myReduce(fn, fn(accm, list.head), list.tail);}function myReduceRight(fn, accm, list) { // [BEGIN] YOUR CODE HERE if (!list) { return accm; } // State-of-the-art trampoline trick to prevent recursion stack overflow const trampoline = (fun) => { return function trampolined(...args) { var result = fun(...args); while (typeof result == 'function') { result = result(); } return result; }; }; const reverseOperation = (origList) => { const reverseCons = (cons, acc = []) => { if (!cons) { return undefined; } acc.push(cons.head); if (cons.tail instanceof Object) { return reverseCons(cons.tail, acc); } else { return acc.reverse(); } }; const recursCons = (jsList = []) => { if (jsList.length <= 0) { return undefined; } else { return { head: jsList[0], tail: recursCons(jsList.slice(1)), }; } }; // IMMUTABLE const newList = Object.assign({}, origList); // Get the reversed version of Linklist in another plain representation const reversedJSList = trampoline(reverseCons)(newList, []); // Back assign the reversed plain representation to Linklist const reversedLinkList = trampoline(recursCons)(reversedJSList); return reversedLinkList; }; const innerReducer = (fn_, accm_, list_) => { if (!list_) { return accm_; } return innerReducer(fn_, fn_(list_.head, accm_), list_.tail); }; return trampoline(innerReducer)(fn, accm, reverseOperation(list)); // [END] YOUR CODE HERE}function myMap2(fn, list) { // [BEGIN] YOUR CODE HERE // State-of-the-art trampoline trick to prevent recursion stack overflow const trampoline = (fun) => { return function trampolined(...args) { var result = fun(...args); while (typeof result == 'function') { result = result(); } return result; }; }; const polishedFn = (cur, acc) => { let newAcc = {}; newAcc.tail = Object.keys(acc).length > 0 ? acc : undefined; newAcc.head = () => fn(cur); // delay to keep the map order return newAcc; }; let newList = Object.assign(list); const storeList = myReduceRight(polishedFn, {}, newList); const activateStore = (store) => { if (!store) return undefined; store.head = store.head instanceof Function ? store.head() : store.head; store.tail = activateStore(store.tail); return store; }; return trampoline(activateStore)(storeList); // [END] YOUR CODE HERE}function main() { let exampleList = cons(1, cons(2, cons(3, cons(4)))); let plusOne = (x) => x + 1; let xTimesTwoPlusY = (x, y) => x * 2 + y; let printXAndReturnY = (x, y) => { console.log(x); return y; }; let unfoldCalculation = (x, y) => 'fn(' + x + ', ' + y + ')'; let printAndReturn = console.log; console.log(listToString(exampleList), 'should be 1 2 3 4'); console.log(listToString(myMap(plusOne, exampleList)), 'should be 2 3 4 5'); console.log(myReduce(xTimesTwoPlusY, 0, exampleList), 'should be 26'); console.log( myReduce(unfoldCalculation, 'accm', exampleList), 'should be fn(fn(fn(fn(accm, 1), 2), 3), 4)' ); console.log(myReduceRight(xTimesTwoPlusY, 0, exampleList), 'should be 20'); console.log( myReduceRight(unfoldCalculation, 'accm', exampleList), 'should be fn(1, fn(2, fn(3, fn(4, accm))))' ); console.log('Below should output 4 3 2 1 each on a separate line:'); myReduceRight(printXAndReturnY, 0, exampleList); console.log(listToString(myMap2(plusOne, exampleList)), 'should be 2 3 4 5'); console.log('The two outputs below should be equal:'); console.log('First output:'); myMap(printAndReturn, exampleList); console.log('Second output:'); myMap2(printAndReturn, exampleList);}main();窍门:应用蹦床函数trampoline优化递归调用。打印后果:'1 2 3 4' 'should be 1 2 3 4''2 3 4 5' 'should be 2 3 4 5'26 'should be 26''fn(fn(fn(fn(accm, 1), 2), 3), 4)' 'should be fn(fn(fn(fn(accm, 1), 2), 3), 4)'20 'should be 20''fn(1, fn(2, fn(3, fn(4, accm))))' 'should be fn(1, fn(2, fn(3, fn(4, accm))))''Below should output 4 3 2 1 each on a separate line:'4321'2 3 4 5' 'should be 2 3 4 5''The two outputs below should be equal:''First output:'1234'Second output:'1234Python实现:# Refer to README for detailed instructions.from __future__ import print_functionimport copyimport typesclass LinkedList: def __init__(self, head, tail): self.head = head self.tail = taildef cons(head, tail=None): return LinkedList(head, tail)def listToString(list): if list is None: return "" if list.tail is None: return str(list.head) return str(list.head) + " " + listToString(list.tail)def myMap(fn, list): if list is None: return None return cons(fn(list.head), myMap(fn, list.tail))def myReduce(fn, accm, list): if list is None: return accm return myReduce(fn, fn(accm, list.head), list.tail)def myReduceRight(fn, accm, list): # [BEGIN] YOUR CODE HERE if list is None: return accm def reverseOperation(origList): # Get the reversed version of Linklist in another plain representation def reverseCons(cons, acc = []): if cons is None: return None acc.append(cons.head) if cons.tail != None: return reverseCons(cons.tail, acc) else: return acc[::-1] # Back assign the reversed plain representation to Linklist def recursCons(pyList = []): if len(pyList) <= 0: return None else: return cons(pyList[0], recursCons(pyList[1:])) newList = copy.deepcopy(origList) reversedPyList = reverseCons(newList, []); reversedLinkList = recursCons(reversedPyList); return reversedLinkList def innerReducer(fn_, accm_, list_): if list_ is None: return accm_ return innerReducer(fn_, fn_(list_.head, accm_), list_.tail) return innerReducer(fn, accm, reverseOperation(list)); # [END] YOUR CODE HEREdef myMap2(fn, list): # [BEGIN] YOUR CODE HERE def polishedFn(cur, acc): newAcc = cons(None) newAcc.tail = acc if isinstance(acc, LinkedList) else None newAcc.head = lambda: fn(cur) # delay to keep the map order return newAcc newList = copy.deepcopy(list) storeList = myReduceRight(polishedFn, {}, newList); def activateStore(store): if store is None: return None store.head = store.head() if isinstance(store.head, types.FunctionType) else store.head store.tail = activateStore(store.tail) return store return activateStore(storeList) # [END] YOUR CODE HEREdef main(): exampleList = cons(1, cons(2, cons(3, cons(4)))) plusOne = lambda x: x + 1 xTimesTwoPlusY = lambda x, y: x * 2 + y def printXAndReturnY(x, y): print(x) return y def unfoldCalculation(x, y): return "fn(%s, %s)" % (str(x), str(y)) printAndReturn = print print(listToString(exampleList), "should be 1 2 3 4") print(listToString(myMap(plusOne, exampleList)), "should be 2 3 4 5") print(myReduce(xTimesTwoPlusY, 0, exampleList), "should be 26") print(myReduce(unfoldCalculation, "accm", exampleList), "should be fn(fn(fn(fn(accm, 1), 2), 3), 4)") print(myReduceRight(xTimesTwoPlusY, 0, exampleList), "should be 20") print(myReduceRight(unfoldCalculation, "accm", exampleList), "should be fn(1, fn(2, fn(3, fn(4, accm))))") print("Below should output 4 3 2 1 each on a separate line:"); myReduceRight(printXAndReturnY, 0, exampleList) print(listToString(myMap2(plusOne, exampleList)), "should be 2 3 4 5") print("The two outputs below should be equal:") print("First output:") myMap(printAndReturn, exampleList) print("Second output:") myMap2(printAndReturn, exampleList)if __name__ == "__main__": main()备注:Python的trampoline蹦床函数实现有些简单,间接递归解决了。可参考文章Tail recursion in Python, part 1: trampolines)。打印后果:1 2 3 4 should be 1 2 3 42 3 4 5 should be 2 3 4 526 should be 26fn(fn(fn(fn(accm, 1), 2), 3), 4) should be fn(fn(fn(fn(accm, 1), 2), 3), 4)20 should be 20fn(1, fn(2, fn(3, fn(4, accm)))) should be fn(1, fn(2, fn(3, fn(4, accm))))Below should output 4 3 2 1 each on a separate line:43212 3 4 5 should be 2 3 4 5The two outputs below should be equal:First output:1234Second output:1234 ...

February 25, 2023 · 8 min · jiezi

关于javascript:常用的18个-JavaScript-3D-库和框架

JavaScript 能够说是最风行的编程语言之一,也是Web 开发人员必须学习的 3 种语言之一,JavaScript 简直能够做任何事件,更能够在包含物联网在内的多个平台和设施上运行。在WebGL库和SVG/Canvas元素的反对下,JavaScript变得惊人的弱小。简直能够为网络构建任何货色,包含基于浏览器的游戏和本地利用,许多最新的突破性性能都在3D上运行。 技术生态系统和浏览器一样产生了许多演变。曾经从简略的网页转向弱小的渐进式Web应用程序。明天,将向大家介绍18个JavaScript 3D库和框架,心愿你的下一个我的项目用的上它们: 1、Three.jsThree.js 是一个跨浏览器的JavaScript库和应用程序编程接口,用于应用WebGL在Web浏览器中创立和显示动画3D计算机图形。是最受欢迎的 3D WebGL 库之一,为有数 3D 体验提供反对。也是最好的 3D 库之一。它由一个外围小组治理,并在GitHub上收费公布。ThreeJS次要解决画布元素,SVG元素和用于渲染的WebGL库。 2、D3.jsD3.js(也称为 D3.数据驱动文档的缩写)是一个 JavaScript 库,用于在 Web 浏览器中生成动静、交互式数据可视化。它应用可缩放矢量图形(SVG),HTML5和级联样式表(CSS)规范。 3、AframeAFrame是一个用于构建虚拟现实体验的开源Web框架。这个javascript框架为开发人员提供了开发虚拟现实设计的能力,能够在浏览器上渲染。 4、Babylon.jsBabylonjs是一个JavaScript框架,它建设在Web图形库之上,用于在Web浏览器中渲染图形。 5、ZdogZdog是一个用于画布和SVG的3D JavaScript引擎。Zdog是一个伪3D引擎,其中几何体以3D模式存在,但出现为立体形态。 6、cannon.jsCannonjs是一个基于Web的物理引擎,旨在加强基于Web的游戏开发。它引入了简略的碰撞检测,各种身材形态、接触、摩擦和Web束缚。它还具备弱小的API,使你可能构建本人的想法。 7、PlayCanvasPlayCanvas是一个游戏引擎,它利用HTML5和WebGL来创立游戏和其余交互式3D组件。 8、LightGl.jsLightGl.js基于WebGL框架,被认为是在浏览器上渲染3D最快最轻的库。LightGl 提供了对代码库的大量管制。 9、Phoria.JsPhoriaJs 旨在应用 HTML5 画布元素渲染基于 Web 的静止成果,它不是基于WebGL的。 10、Cesium.JsCesiumJs应用WebGL进行硬件加速图形,它旨在在Web浏览器上创立3D地球仪和2D地图。 11、Scene.JsScene.Js 是一个基于 JavaScript 时间轴的动画库,用于创立动画网站。它容许创建对象挪动和地位的工夫程序。 12、XeoglXeogl是WebGl上的3D模型可视化,它提供了在xeolabs开发的浏览器上创立3D世界的工具。 13、ClayGLClayGL是一个易于应用的,可配置为高质量的图形,并基于WebGL图形库构建可扩大的Web3D应用程序。 14、DivSugarDivSugar 是一个基于 CSS 的库,用于渲染 3D 场景图、动画零碎和几何类。将3D动画集成到现有网页中非常容易。 15、Tilt.jsTiltjs是一个渺小的申请AnimationFrame驱动的60 + fps轻量级视差歪斜成果,用于jQuery。 16、Turbulenz_engineTurbulenz是一个模块化的3D和2D游戏框架,可能在基于HTML5的浏览器上创立游戏。 ...

February 24, 2023 · 1 min · jiezi

关于javascript:前端责任链设计模式案例分享

责任链模式是一种行为型设计模式,它能够将申请沿着一条解决链进行传递,直到有一个处理器可能解决该申请为止。在前端开发中,责任链模式通常用于解决用户输出事件,例如点击、滚动等。 上面是一个简略的前端责任链模式案例,假如有一个页面上有三个按钮,别离对应“保留”、“提交”和“勾销”操作。当用户点击某个按钮时,咱们须要顺次执行一些操作,例如数据验证、数据保留、数据提交等。 首先,咱们须要定义一个处理器接口,该接口蕴含一个解决办法和一个指向下一个处理器的指针: class Handler { constructor() { this.nextHandler = null; } setNext(handler) { this.nextHandler = handler; } handleRequest(request) { if (this.nextHandler !== null) { return this.nextHandler.handleRequest(request); } return null; }}接下来,咱们须要创立三个具体的处理器,别离对应“保留”、“提交”和“勾销”操作: class SaveHandler extends Handler { handleRequest(request) { if (request === 'save') { console.log('数据保留胜利'); return true; } else { return super.handleRequest(request); } }}class SubmitHandler extends Handler { handleRequest(request) { if (request === 'submit') { console.log('数据提交胜利'); return true; } else { return super.handleRequest(request); } }}class CancelHandler extends Handler { handleRequest(request) { if (request === 'cancel') { console.log('操作已勾销'); return true; } else { return super.handleRequest(request); } }}最初,咱们须要将这三个处理器链接起来,造成一个责任链。在这个责任链中,如果以后处理器无奈解决该申请,它会将申请传递给下一个处理器,直到有一个处理器可能解决该申请为止: ...

February 24, 2023 · 2 min · jiezi

关于javascript:HHDESK文本对比功能

比照文件夹和图片而言,文本的更改更加频繁且琐碎;个别词语的更改更是让人“健忘”。如果有一款工具可能直观的对文本进行比照,并且清晰的划分显示,那么便能够大量节约办公人员的精力和工夫。 1 文本比照性能简介版本更新,是每个软件的必经之路。尽管大多数软件会有更新布告供人参考,但比起使用手册来不够直观。上面便以2个版本的HHDESK使用手册为例,简略介绍一下HHDESK的文本比照性能。应用这个性能只须要一个步骤:点击文件比照,别离抉择须要比照的文本文档;能够看到,2个文档别离显示,并呈现标识。如图所示:红色背景局部为雷同内容的文本;灰色局部为内容有变动的文本;(若用户感觉内容没有变动,认为是软件显示谬误,请持续仔细检查,HHDESK齐全不会呈现这种谬误。) 红色局部为前一份文档有,而后一份文档删除的内容; 绿色局部为后一份文档所减少的内容。每一个更改的文本内容都清晰的标识进去,且有关系线相连,保障用户可能疾速找到批改点。(或者称它为“逻辑线”,便直白明了。)这样的比照浏览形式,更合乎逻辑性以及思维的完整性。 2 应用技巧2.1 拖动右边版块的进度条,以及鼠标滑轮,能够独自管制此板块页面滑动; 拖动左边版块的进度条以及鼠标滑轮,则是管制左右两个板块滑动;2.2 点击右侧箭头处图标,能够返回文本首页。

February 24, 2023 · 1 min · jiezi

关于javascript:JavaScript-如何验证-URL

前言当开发者须要为不同目标以不同模式解决URL时,比如说浏览器历史导航,锚点指标,查问参数等等,咱们常常会借助于JavaScript。然而,它的频繁应用促使攻击者利用其破绽。这种被利用的危险是咱们必须在咱们的JavaScript应用程序中实现URL验证的起因。 URL验证查看URL是否遵循正确的URL语法,也就是每个URL必须具备的构造。URL验证能够使咱们的应用程序免遭基于URL的破绽,比方歹意脚本注入和服务器端申请伪造(SSRF)。当咱们在获取近程资源时没有利用平安编码常规来验证用户提供的URL时,歹意行为者能够采纳SSRF攻打。 URL验证URL验证的存在是为了增强平安,避免可能存在的破绽,并打消运行代码时产生的任何谬误的机会。然而咱们应该在什么时候应用URL验证,在这个过程中咱们要验证什么呢?咱们应该在所有必须辨认和验证诸如网页、图片、gif和视频等资源的软件中施行URL验证。 一个典型的URL包含多个片段,比方协定、域名、主机名、资源名、URL源、端口等等。这些用来通知浏览器如何追踪指定的资源。咱们能够以不同的形式来验证URL: 应用正则字面量和构造函数URL构造函数isValidURL办法Input元素Anchor标签办法一个典型的URL验证计划接管来自用户的输出,而后对其进行解析,以辨认其各个组成部分。验证计划能够确保所有的URL组件合乎互联网规范。例如,如果须要,它能够查看URL是否应用平安协定。 主机名验证首先是将主机名分成独立的标签,以确保它们合乎顶级域名标准。一个典型的主机名由至多两个用点分隔的标签组成。例如,www.snyk.com 有 "www"、"snyk"和 "com"的标签。每个标签只能由一个字母数字字符或一个连字符组成,无论大小写。而后,验证计划能够确保主机名与URL的容许列表相匹配,以确保只容许指定的URL,并且容许的URL不会被谬误地取消资格。 默认状况下,URL中应用的大多数资源的门路都是容许的。然而,端口只能在1到65536的范畴内。任何超出这个范畴的货色都应该抛出一个谬误。咱们还能够查看数字IP地址,以判断它是一个IPV4地址还是IPV6地址。 最初,咱们也能够查看URL的用户名和明码。这个性能有助于恪守公司政策和凭证爱护。 当初,你曾经有了这些基础知识,让咱们来看看应用javascript的URL验证吧。 如何执行URL验证在JavaScript中,执行URL验证最简略的形式是应用new URL构造函数。除此之外,它还失去了Node.js运行时和大多数浏览器的反对。 根本语法如下: new URL (url)new URL (url , base)如果提供绝对URL,JavaScript只须要base元素。如果不提供绝对URL,默认为undefined。另外,如果提供一个具备相对URL的base元素,JavaScript会疏忽base元素。 为了验证URL,能够应用以下代码: function checkUrl (string) { let givenURL ; try { givenURL = new URL (string); } catch (error) { console.log ("error is", error); return false; } return true;}该函数用于查看URL的有效性。当URL无效时返回true,否则返回false。 如果你传递www.urlcheck.com给该函数会返回false。因为该参数并不是一个无效的URL。正确版本应该是https://urlcheck.com。另一个例子是mailto:John.Doe@example.com。这是一个无效的URL,但如果移除了冒号,JavaScript就不再认为它是一个URL了。第三个例子是ftp://。这不是一个无效URL,因为没有蕴含主机名。如果你增加两个点(..),就会变成无效URL。因为点会被认为是一个主机名,也就是说ftp://..变成了一个无效的URL。重要的是要记住,非常规的、但齐全无效的URL是存在的!它们可能对从事这些工作的开发人员来说是意外的,但在其余方面是齐全适合的。例如,以下两个URL都会返回真值: new URL("youtube://a.b.c.d");new URL("a://1.2.3.4@1.2.3.4");这些例子揭示咱们,开发者应该依附URL验证准则,而不是专一于常规。 如果你想确保无效的URL蕴含一些特定的URL计划,你能够应用以下函数: function checkHttpUrl(string) { let givenURL; try { givenURL = new URL(string); } catch (error) { console.log("error is",error) return false; } return givenURL.protocol === "http:" || givenURL.protocol === "https:";}该函数验证URL,而后查看URL是否应用HTTP或者HTTPS。在这里,ftp://..会被认为是有效的,因为它不蕴含HTTP或者HTTPS,而http://..仍旧无效。 ...

February 23, 2023 · 1 min · jiezi