1.ESnext 夜点心:带问号的源码语法糖
2.ES6及ESNEXT
3.vscode如何配置才能单步调试用typescript写的node.js程序的一种可行方法
4.Vue 3源码解析--响应式原理
5.你还不会写vite插件吗?没关系,我教你啊!源码
ESnext 夜点心:带问号的源码语法糖
ECMAScript 的两个带有问号的语法糖分别为 optional chaining 和 Nullish coalescing operator。前者被称为「可选链式取值」,源码通过简化对象安全取值逻辑,源码减少判断值是源码三大框架源码否为 null 或 undefined 的条件语句书写。原逻辑为,源码简化后则为,源码二者等价。源码
可选链式取值语法结构如下:这些写法大同小异(后面的源码三种写法的. 不要忘了哦),本质都是源码帮助我们减少一些判断值是否是 null 或者 undefined 的条件语句的书写。
Nullish coalescing operator 为「空位合并运算符」,源码语法形式为exp1 exp2,源码仅会在 exp1 的源码值为 null 或 undefined 时计算并返回 exp2 的值。例如,源码我们需要在界面上展示一个数值,在数值不存在的时候展示 '--',使用 value '--' 即可满足需求,而 value || '--' 不能满足此需求,因为 value 等于 0 时也展示了 '--'。
更多例子和语法细节如下:
两个带问号的语法糖在浏览器支持方面并不理想,五大浏览器的最新版都有一半尚未支持它们,nodeJS 对这两个特性目前也不支持。但在实际开发中,通过使用 babel 的转码插件或 Typescript 3.7 的支持,仍可简化源码。
ES6及ESNEXT
一.let与const
块级作用域,const定义之后不可改变,影视源码本地接口变量提升。
二.箭头函数
箭头函数的特点:this是在定义时决定的,普通函数this是在调用时决定的。箭头函数不能用在构造函数,构造函数里this会指向新创建出来的对象,箭头函数里this指向是在定义时决定的。
三.类
四.模版字符串
五.解构
5.1 数组的解构
5.2 对象的解构
5.3 解构的原理:针对可迭代对象的Iterator接口,通过遍历器获取对应的值进行赋值
5.4 Iterator接口,为各种不一样的数据解构提供统一的访问机制。任何数据解构只要有Iterator接口,就能通过遍历操作,依次按顺序处理数据结构内的所有成员。es6 for of相当于遍历器,在遍历数据结构时,自动寻找该接口
六. 遍历
6.1 for in缺点:会遍历原型链上的可枚举属性;适合遍历对象,不适合遍历数组
6.2 for of可迭代对象(Array、Set、String、TypedArray,arguments对象,NodeList对象)上创建迭代循环,调用自定义迭代钩子。优点:仅遍历当前对象;可中断
七. Object
7.1 Object.keys返回一个给定对象的自身可枚举属性组成的数组
7.2 Object.values返回一个给定对象可枚举属性值的数组
7.3 Object.entries返回一个给定对象自身可枚举属性的键值对数组
7.4 Object.getOwnPropertyNames返回自身拥有的枚举或不可枚举属性名称字符串数组
7.5 Object.getOwnPropertyDescriptor属性描述符,是一个对象,包含以下内容: configurable: 若为false,则任何删除目标属性或修改属性特性(writable, configurable,enumerable)的行为将被视为无效,故一般设置为true; writable: 若为false,则修改该属性的操作都无效(不会报错,严格模式下会报错),付款单页源码默认false; enumerable: 是否能够在for-in或者Object.keys遍历出来
7.6 Object.create()创建一个新的对象,将第一个参数作为新对象都protp属性的值。
7.7 Object.assign浅拷贝,类似于{ ...a, ...b}
八. 数组
8.1 Array.flat()按照指定深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为新数组返回
8.2 Array.includes判断数组是否含有指定值,含有返回true,否则返回false;含有两个参数
8.3 Array.find返回数组中满足提供的测试函数的第一个元素值,否则返回undefined.
8.4 Array.from创建一个新数组实例,数组的元素由可迭代对象的值组成
8.5 Array.of创建一个具有可变数量参数的数组新实例,而不考虑参数的数量或类型
九. 异步编程: async await yield
十. Babel
是一个工具链,将ES+版本的代码转换为向后兼容的js语法,以便能运行在当前和旧版本的浏览器中。抽象语法树(AST)处理过程中每一步都涉及到创建或操作抽象语法树。每一层都有相同的结构,这样的每一层结构被叫做节点,一个AST树有单一或多个节点构成,组合在一起可以描述用于静态分析的程序语法。Babel的处理步骤:解析parse, 转换transform, 生成generate。接收代码并输出AST,接收AST并对其遍历,对节点进行添加、更新及移除操作。这是最复杂的过程,需要插件介入,把最终的AST转化成字符串形式的代码,同时会创建源码映射(source maps)。
补充知识点: Proxy将Object对象的同城配送系统源码下载某些明显属于语言内部的方法放到Reflect对象上。Reflect对象的方法与Proxy对象的方法一一对应,Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
vscode如何配置才能单步调试用typescript写的node.js程序的一种可行方法
为在VSCode中单步调试用TypeScript编写的Node.js程序,提供了一种实用的配置步骤。
步骤如下:
首先,确保项目中安装了TypeScript编译器tsc,并在`tsconfig.json`中配置好目标为`"esnext"`,模块类型为`"commonjs"`,启用`sourceMap`,并将输出文件目录设为`"build"`。
在VSCode中,利用任务功能创建一个监视源代码并自动编译的默认任务。通过`Ctrl+Alt+P`(Mac下为`Command+Shift+P`)打开任务管理器,选择`tsc: watch`,这将在`.vscode`目录下生成`task.json`。
执行任务时,再次打开任务管理器,选择`Tasks: Run Build Task`,确保项目编译成功。接下来,配置`launch.json`文件,关键部分包括设置入口文件路径为`"program": "${ workspaceFolder}/index.ts"`,根据`tsconfig.json`的linux常用源码在哪下载`outDir`配置`"outFiles"`。
创建好`launch.json`后,选择`"ts-node Debugger"`配置,点击运行按钮(F5)或三角形图标开始调试。在需要的地方设置断点,确认断点生效和调试工具栏的显示。
通过以上步骤,你应该能成功在VSCode中配置并单步调试TypeScript Node.js项目。完成配置后的体验应该会让你的工作流程更加顺畅。
Vue 3源码解析--响应式原理
Vue 3响应式核心原理解析
Vue 3相对于Vue 2改动较大的模块是响应式reactivity,性能提升显著。其核心改变是采用ES 6的Proxy API代替Vue2中Object.defineProperty方法,实现响应式。Proxy API定义为用于定义基本操作自定义行为的原生对象,如属性查找、赋值、枚举、函数调用等。Proxy对象作为目标对象的代理,拦截所有对外操作,允许对操作进行拦截、过滤或修改。通过Proxy,可以实现对象限制操作,如禁止删除和修改属性,以及监听数组变化。
Proxy API基本语法包括目标对象和handler对象,后者定义了执行各种操作时代理的行为。常见使用方法展示了如何生成代理对象及其撤销操作。Proxy共有接近个handler,分别对应不同操作,如禁止操作、属性修改校验等。结合这些handler,可以实现对象限制功能。
在Vue 3中,响应式对象通过ref/reactive方法实现,利用Proxy API简化响应式逻辑。ref方法的主要逻辑在源码中体现,通过Proxy的特性实现双向数据绑定能力,无需配置,利用原生特性轻松实现。具体运行原理涉及ref方法、toReactive方法、createReactiveObject方法等,最终创建响应式对象。
Vue 3响应式的核心在于Proxy API的利用,尤其是handler的set方法,实现双向数据绑定逻辑,这与Vue 2中的Object.defineProperty方法形成显著区别。Proxy的特性简化了复杂逻辑,使得响应式对象的创建和管理更加高效、直观。
ref()方法的运行原理涉及创建响应式对象的过程,从接收参数到创建Proxy对象,实现了对深层嵌套对象属性的监听和修改。在创建响应式对象的流程中,通过Base Handlers和Collection Handlers分别处理不同类型的对象,确保响应式对象的高效创建和管理。
在Vue 3源码中,所有响应式代码集中在vue-next/package/reactivity目录下。ref方法的实现主要在reactivity/src/ref.ts中,展示了如何利用Proxy API简化响应式逻辑。通过toReactive方法创建响应式对象,再通过createReactiveObject方法实现深层属性监听和修改。
createReactiveObject方法内部实现包括创建Proxy对象,分别处理基础对象和集合对象(如Map、Set等),避免重复创建响应式对象,同时利用Proxy handler实现属性监听和修改功能。Proxy handler包括get、set等方法,分别对应属性读取和修改逻辑,确保响应式流程的高效执行。
总结而言,Vue 3响应式核心原理解析展示了Proxy API的高效应用,简化了响应式逻辑,实现了复杂操作的轻松实现。通过深入理解Proxy API及其在Vue 3响应式实现中的应用,开发者可以更高效地构建响应式应用,提升用户体验和性能。
你还不会写vite插件吗?没关系,我教你啊!
前言
大家好,我是易师傅,在现如今Vite工具快开始盛行之下,我们是不是可以去做一件有意义的事呢,比如写一个vite插件,你觉得怎么样?
刚好我们可以趁vite插件生态还未很成熟阶段,做一个让自己顺心,让领导赏心,让社区开心的插件,与之携手共进。
如果大家对vite感兴趣可以去看看专栏:?《Vite从入门到精通》
通过本文你可以学到如何创建一个vite插件模板
vite插件的各个钩子作用
vite插件的钩子执行顺序
如何写一个自己的插件
了解vite插件1.什么是vite插件vite其实就是一个由原生?ESModule?驱动的新型Web开发前端构建工具。
vite插件就可以很好的扩展vite自身不能做到的事情,比如文件的压缩、对commonjs的支持、打包进度条等等。
2.为什么要写vite插件相信在座的每位同学,到现在对webpack的相关配置以及常用插件都了如指掌了吧;
vite作为一个新型的前端构建工具,它还很年轻,也有很多扩展性,那么为什么我们不趁现在与它一起携手前进呢?做一些于你于我于大家更有意义的事呢?
快速体验要想写一个插件,那必须从创建一个项目开始,下面的vite插件通用模板大家以后写插件可以直接clone使用;
插件通用模板github:体验入口
插件github:体验入口
建议包管理器使用优先级:pnpm>yarn>npm>cnpm
长话短说,直接开干~
创建vite插件通用模板1.初始化1.1创建一个文件夹并且初始化:初始化按照提示操作即可
mkdirvite-plugin-progress&&cdvite-plugin-progress&&pnpminit1.2安装typescript
pnpmitypescript@types/node-D1.3配置tsconfig.json
{ "compilerOptions":{ "module":"ESNext","target":"esnext","moduleResolution":"node","strict":true,"declaration":true,"noUnusedLocals":true,"esModuleInterop":true,"outDir":"dist","lib":["ESNext"],"sourceMap":false,"noEmitOnError":true,"noImplicitAny":false},"include":["src/*","*.d.ts"],"exclude":["node_modules","examples","dist"]}1.4安装vite
//进入package.json{ ..."devDependencies":{ "vite":"*"}...}2.配置eslint和prettier(可选)安装eslint
pnpmieslint@typescript-eslint/parser@typescript-eslint/eslint-plugin--save-dev配置.eslintrc:配置连接
安装prettier(可选)
pnpmiprettiereslint-config-prettiereslint-plugin-prettier--save-dev配置.prettierrc:配置连接
3.新增src/index.ts入口importtype{ PluginOption}from'vite';exportdefaultfunctionvitePluginTemplate():PluginOption{ return{ //插件名称name:'vite-plugin-template',//pre会较于post先执行enforce:'pre',//post//指明它们仅在'build'或'serve'模式时调用apply:'build',//apply亦可以是一个函数config(config,{ command}){ console.log('这里是config钩子');},configResolved(resolvedConfig){ console.log('这里是configResolved钩子');},configureServer(server){ console.log('这里是configureServer钩子');},transformIndexHtml(html){ console.log('这里是transformIndexHtml钩子');},}}其中的vite插件函数钩子会在下面详细详解~
到这里,那么我们的基本模版就建好了,但是我们现在思考一下,我们应该怎么去运行这个插件呢?
那么我们就需要创建一些examples例子来运行这个代码了;
4.创建examples目录我这里创建了三套项目demo,大家直接copy就行了,这里就不详细介绍了
vite-react
vite-vue2
vite-vue3
如果你的插件需要多跑一些demo,自行创建项目即可;
那么下面我们就需要配置examples下的项目与当前根目录的插件做一个联调了(下面以examples/vite-vue3为例)。
5.配置examples/vite-vue3项目修改examples/vite-vue3/package.json
{ ..."devDependencies":{ ..."vite":"link:../../node_modules/vite","vite-plugin-template":"link:../../"}}上面意思就是说:
要把examples/vite-vue3项目中的vite版本与根目录vite-plugin-template的版本一致;
同时要把examples/vite-vue3项目中的vite-plugin-template指向你当前根目录所开发的插件;
引入插件:examples/vite-vue3/vite.config.ts
importtemplatefrom'vite-plugin-template';exportdefaultdefineConfig({ ...plugins:[vue(),template()],...});安装:cdexamples/vite-vue3&&pnpminstall
cdexamples/vite-vue3&&pnpminstall注意:examples/vite-vue2和examples/vite-react的配置与这一致
思考:
到这里,我们再思考一下,我们把examples/vite-vue3中的项目配置好了,但是我们应该怎么去运行呢?
直接去examples/vite-vue3目录下运行pnpmrunbuild或者pnpmrundev?
这样显然是不能运行成功的,因为我们的根目录下的src/index.ts是没法直接运行的,所以我们需要把.ts文件转义成.js文件;
那么我们怎么处理呢?
那么我们不得不去试着用用一个轻小且无需配置的工具tsup了。
6.安装tsup配置运行命令tsup是一个轻小且无需配置的,由esbuild支持的构建工具;
同时它可以直接把.ts、.tsx转成不同格式esm、cjs、iife的工具;
安装tsup
pnpmitypescript@types/node-D0在根目录下的package.json中配置
pnpmitypescript@types/node-D.开发环境运行开发环境运行:实时监听文件修改后重新打包(热更新)
pnpmitypescript@types/node-D2运行examples中的任意一个项目(以vite-vue3为例)
pnpmitypescript@types/node-D3注意:
如果你的插件只会在build时运行,那就设置"example:vue3":"cdexamples/vite-vue3&&pnpmrunbuild";
反之就运行pnpmrundev
输出:
到这里你就可以边开发边运行了,尤雨溪看了都说爽歪歪~
8.发布安装bumpp添加版本控制与tag
pnpmitypescript@types/node-D4配置package.json
pnpmitypescript@types/node-D5开发完插件后运行发布
pnpmitypescript@types/node-D6那么到这里,我们的vite插件模板就已经写好了,大家可以直接克隆vite-plugin-template模板使用;
如果你对vite的插件钩子和实现一个真正的vite插件感兴趣可以继续往下面看;
vite的插件钩子hooks们1.vite独有的钩子enforce:值可以是pre?或?post,pre会较于post先执行;
apply:值可以是build或serve?亦可以是一个函数,指明它们仅在build或serve模式时调用;
config(config,env):可以在vite被解析之前修改vite的相关配置。钩子接收原始用户配置config和一个描述配置环境的变量env;
configResolved(resolvedConfig):在解析vite配置后调用。使用这个钩子读取和存储最终解析的配置。当插件需要根据运行的命令做一些不同的事情时,它很有用。
configureServer(server):主要用来配置开发服务器,为dev-server(connect应用程序)添加自定义的中间件;
transformIndexHtml(html):转换index.html的专用钩子。钩子接收当前的HTML字符串和转换上下文;
handleHotUpdate(ctx):执行自定义HMR更新,可以通过ws往客户端发送自定义的事件;
2.vite与rollup的通用钩子之构建阶段options(options):在服务器启动时被调用:获取、操纵Rollup选项,严格意义上来讲,它执行于属于构建阶段之前;
buildStart(options):在每次开始构建时调用;
resolveId(source,importer,options):在每个传入模块请求时被调用,创建自定义确认函数,可以用来定位第三方依赖;
load(id):在每个传入模块请求时被调用,可以自定义加载器,可用来返回自定义的内容;
transform(code,id):在每个传入模块请求时被调用,主要是用来转换单个模块;
buildEnd():在构建阶段结束后被调用,此处构建结束只是代表所有模块转义完成;
3.vite与rollup的通用钩子之输出阶段outputOptions(options):接受输出参数;
renderStart(outputOptions,inputOptions):每次bundle.generate和bundle.write调用时都会被触发;
augmentChunkHash(chunkInfo):用来给chunk增加hash;
renderChunk(code,chunk,options):转译单个的chunk时触发。rollup输出每一个chunk文件的时候都会调用;
generateBundle(options,bundle,isWrite):在调用bundle.write之前立即触发这个hook;
writeBundle(options,bundle):在调用bundle.write后,所有的chunk都写入文件后,最后会调用一次writeBundle;
closeBundle():在服务器关闭时被调用
4.插件钩子函数hooks的执行顺序(如下图)5.插件的执行顺序别名处理Alias
用户插件设置enforce:'pre'
vite核心插件
用户插件未设置enforce
vite构建插件
用户插件设置enforce:'post'
vite构建后置插件(minify,manifest,reporting)
手撸一个vite插件下面以vite打包进度条插件为例;
插件地址:github如果您觉得不错欢迎star?
该插件已被vite官方收集至官方文档:链接地址
因为文章的重点不在于这个插件的详细实现过程,所以本文只会贴上源代码供大家参考,详细介绍会在下一篇文章中讲解,请大家拭目以待吧!
inde.ts
pnpmitypescript@types/node-D7cache.ts
pnpmitypescript@types/node-D8最后该系列会是一个持续更新系列,关于整个《Vite从入门到精通》专栏,我主要会从如下图几个方面讲解,请大家拭目以待吧!!!
宝贝们,都看到这里了,要不点个赞呗?
原文:/post/