1.å¦ä½å¨vueä¸ä½¿ç¨tsç示ä¾ä»£ç
2.vue/compiler-sfc源码分析学习--part2:如何处理script--day5
3.vueVue3中使用函数调用组件内函数和创建组件超详细+源码
4.Loader源码分析-Vue Loader v15
5.直播带货源码,vue中点击按钮平滑滚动到页面某个div位置
6.为 Vue3 🔥 学点 TypeScript, 什么是声明文件(declare)? [🦕全局声明篇]
å¦ä½å¨vueä¸ä½¿ç¨tsç示ä¾ä»£ç
æ¬æä»ç»äºå¦ä½å¨vueä¸ä½¿ç¨tsç示ä¾ä»£ç ï¼å享ç»å¤§å®¶ï¼å ·ä½å¦ä¸ï¼
注æï¼æ¤æ并ä¸æ¯ævueæ¹ä¸ºå ¨é¨æ¿æ¢ä¸ºtsï¼èæ¯å¯ä»¥å¨åæ¥ç项ç®ä¸æ¤å ¥tsæ件ï¼ç®ååªæ¯å®è·µé¶æ®µï¼åts转åè¿ç¨ä¸çè¿æ¸¡ã
tsæä»ä¹ç¨ï¼
ç±»åæ£æ¥ãç´æ¥ç¼è¯å°åçjsãå¼å ¥æ°çè¯æ³ç³
为ä»ä¹ç¨tsï¼
TypeScriptç设计ç®çåºè¯¥æ¯è§£å³JavaScriptçâçç¹âï¼å¼±ç±»åå没æå½å空é´ï¼å¯¼è´å¾é¾æ¨¡ååï¼ä¸éåå¼å大åç¨åºãå¦å¤å®è¿æä¾äºä¸äºè¯æ³ç³æ¥å¸®å©å¤§å®¶æ´æ¹ä¾¿å°å®è·µé¢å对象çç¼ç¨ã
typescriptä¸ä» å¯ä»¥çº¦ææ们çç¼ç ä¹ æ¯ï¼è¿è½èµ·å°æ³¨éçä½ç¨ï¼å½æ们çå°ä¸å½æ°åæ们ç«é©¬å°±è½ç¥éè¿ä¸ªå½æ°çç¨æ³ï¼éè¦ä¼ ä»ä¹å¼ï¼è¿åå¼æ¯ä»ä¹ç±»åä¸ç®äºç¶ï¼å¯¹å¤§å项ç®çç»´æ¤æ§æå¾å¤§çæåãä¹ä¸è³äºä½¿å¼åè æ¬èµ·ç³å¤´ç ¸èªå·±çèã
Angular: æ们为ä»ä¹éæ©TypeScript?
TypeScript éä¼ç§çå·¥å ·
TypeScript æ¯ JavaScript çè¶ é
TypeScript 使å¾æ½è±¡æ¸ æ°å¯è§
TypeScript 使代ç æ´å®¹æé 读åç解
æ¯çï¼æç¥éè¿çèµ·æ¥å¹¶ä¸ç´è§ã让æç¨ä¸ä¸ªä¾åæ¥è¯´ææçææã让æ们æ¥ççè¿ä¸ªå½æ°jQuery.ajax()ãæ们è½ä»å®çç¾åä¸å¾å°ä»ä¹ä¿¡æ¯?
æ们å¯ä¸è½ç¡®å®çæ¯è¿ä¸ªå½æ°æ两个åæ°ãæ们å¯ä»¥çæµè¿äºç±»åãä¹è®¸ç¬¬ä¸ä¸ªæ¯å符串ï¼ç¬¬äºä¸ªæ¯é 置对象ãä½è¿åªæ¯çæµï¼æ们å¯è½éäºãæ们ä¸ç¥éä»ä¹é项è¿å ¥è®¾ç½®å¯¹è±¡(å®ä»¬çå称åç±»å)ï¼æè 该å½æ°è¿åä»ä¹ã
å¨ä¸æ£æ¥æºä»£ç æææ¡£çæ åµä¸ï¼æ们ä¸å¯è½è°ç¨è¿ä¸ªå½æ°ãæ£æ¥æºä»£ç 并ä¸æ¯ä¸ä¸ªå¥½çéæ©ââæ¥æå½æ°åç±»çç®çï¼æ¯å¨ä¸ç¥éå¦ä½å®ç°å®ä»¬çæ åµä¸ä½¿ç¨å®ä»¬ãæ¢å¥è¯è¯´ï¼æ们åºè¯¥ä¾èµäºä»ä»¬çæ¥å£ï¼èä¸æ¯ä»ä»¬çå®ç°ãæ们å¯ä»¥æ£æ¥ææ¡£ï¼ä½è¿å¹¶ä¸æ¯æ好çå¼åç»éªââå®éè¦é¢å¤çæ¶é´ï¼èä¸ææ¡£ç»å¸¸è¿æã
å æ¤ï¼å°½ç®¡å¾å®¹æé 读jQuery.ajax(url,settings)ï¼çæ£ç解å¦ä½è°ç¨è¿ä¸ªå½æ°ï¼æ们éè¦é 读å®çå®ç°æå®çææ¡£ã
以ä¸æ¯ä¸ä¸ªç±»åçæ¬ï¼
å®ç»äºæ们æ´å¤çä¿¡æ¯ã
è¿ä¸ªå½æ°ç第ä¸ä¸ªåæ°æ¯ä¸ä¸ªå符串ã
设置åæ°æ¯å¯éçãæ们å¯ä»¥çå°ææå¯ä»¥ä¼ éå°å½æ°ä¸çé项ï¼ä¸ä» æ¯å®ä»¬çå称ï¼è¿å æ¬å®ä»¬çç±»åã
å½æ°è¿åä¸ä¸ªJQueryXHR对象ï¼æ们å¯ä»¥çå°å®çå±æ§åå½æ°ã
ç±»ååç¾åè¯å®æ¯æªç±»ååçç¾åé¿ï¼ä½æ¯:stringï¼:JQueryAjaxSettingsåJQueryXHR并ä¸æ¯æ··ä¹±çã å®ä»¬æ¯æé«ä»£ç çå¯ç解æ§çéè¦ææ¡£ãæ们å¯ä»¥æ´æ·±å ¥å°ç解代ç ï¼èä¸å¿ æ·±å ¥å°å®ç°æ读åææ¡£ä¸ã æç个人ç»éªæ¯ï¼æå¯ä»¥æ´å¿«å°é 读类åå代ç ï¼å 为类åæä¾äºæ´å¤çä¸ä¸ææ¥ç解代ç ã
æèª Angular: æ们为ä»ä¹éæ©TypeScript?
ts好å¦åï¼
TypeScriptçä¸ä¸ªè®¾è®¡äº®ç¹å°±æ¯å®å¹¶æ²¡ææå¼JavaScriptçè¯æ³å¦èµ·çç¶ï¼èæ¯åæäºJavaScriptçè¶ éï¼è¿ä¸ªåå³åºè¯¥è®°å¨Andersä¸ï¼ï¼è¿æ ·ä»»ä½åæ³çJavaScriptçè¯å¥å¨TypeScriptä¸é½æ¯åæ³çï¼ä¹å°±æ¯è¯´å¦ä¹ ææ¬å¾ä½ï¼å¦æä½ å¯¹JavaScriptææ¯è¾æ·±å ¥çäºè§£ï¼é£ä¹å ¶å®å¯ä»¥å¾å¿«çä¸æTypeScriptï¼å 为å®ç设计é½æ¯é对JavaScriptç使ç¨ä¹ æ¯åæ¯ä¾ã
ä¸äºç®åçä¾åï¼ä¸çå³æï¼
åºç¡ç±»å
let isDone: boolean = false; // å¸å°å¼
let decLiteral: number = 6; // æ°å
let name: string = "bob"; // å符串
let list: number[] = [1, 2, 3]; // æ°ç»
...
...
æ¥å£
function printLabel(labelledObj: { label: string }) { console.log(labelledObj.label);
} let myObj = { size: , label: "Size Object" };
printLabel(myObj);
ç±»åæ£æ¥å¨ä¼æ¥çprintLabelçè°ç¨ã printLabelæä¸ä¸ªåæ°ï¼å¹¶è¦æ±è¿ä¸ªå¯¹è±¡åæ°æä¸ä¸ªå为labelç±»å为stringçå±æ§ã éè¦æ³¨æçæ¯ï¼æä»¬ä¼ å ¥ç对象åæ°å®é ä¸ä¼å å«å¾å¤å±æ§ï¼ä½æ¯ç¼è¯å¨åªä¼æ£æ¥é£äºå¿ éçå±æ§æ¯å¦åå¨ï¼å¹¶ä¸å ¶ç±»åæ¯å¦å¹é ã
å½ç¶è¿æä¸äºé«çº§çç¨æ³ï¼è¿éå°±ä¸åè¿å¤çä»ç»äºï¼äºè§£æ´å¤
å¦ä½å¨vue项ç®ä¸åºç¨tsï¼
1ãé¦å å®è£ ts
npm install --save-dev typescript npm install --save-dev ts-loader
2ãå¨æ ¹ç®å½å»ºtsconfig.jsonæ件
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"lib": ["dom","es"],
"target": "es5"
},
"include": ["./src/**/*"] }
3ãå¨é ç½®ä¸æ·»å ts-loader
{
test: /\.tsx?$/,
loader: 'ts-loader', exclude: /node_modules/, options: {
appendTsSuffixTo: [/\.vue$/],
}
}
4ãæåæ .ts åç¼æ·»å ä¸å°±OKäºï¼å¨webpack.base.conf.jsæ件ä¸
ç°å¨å°±å¯ä»¥å¨æ们åæ¬ç项ç®ä¸ä½¿ç¨tsæ件äºã
å¦ä½å®è·µï¼
1ãå¦ä½å¨jsä¸å¼ç¨tsæ件ï¼
ç±äºjsæ件没æç±»åæ£æµï¼å½æ们ætsæ件å¼å ¥çæ¶åï¼tsæ件ä¼è½¬åæjsæ件ï¼æ以å¨jsæ件ä¸å¼ç¨tsæ件çæ¹æ³ç±»åæ£æµæºå¶ä¸ä¼çæãä¹å°±æ¯è¯´åªæå¨tsæ件å æä¼æç±»åæ£æµæºå¶ã
é£ä¹æä¹å¨jsæ件ä¸ä½¿ç¨ç±»åæ£æµæºå¶å¢ï¼å°ç¼èªå·±å°è£ äºä¸å¥typeCheckçdecoratoræ¹æ³ï¼ä» ä¾åèï¼ç¨æ³å¦ä¸ï¼
@typeCheck('object','number') deleteItem(item,index) { }
æ£æµdeleteItemæ¹æ³åæ°ï¼ item为objectç±»åï¼index为numberç±»åï¼å¦æç±»åä¸å¹é å°ä¼æåºå¼å¸¸
é¨å代ç ç®ä¸ï¼
const _check = function (checked,checker) {
check: for(let i = 0; i < checked.length; i++) { if(/(any)/ig.test(checker[i])) continue check; if(_isPlainObject(checked[i]) && /(object)/ig.test(checker[i])) continue check; if(_isRegExp(checked[i]) && /(regexp)/ig.test(checker[i])) continue check; if(Array.isArray(checked[i]) && /(array)/ig.test(checker[i])) continue check; let type = typeof checked[i]; let checkReg = new RegExp(type,'ig') if(!checkReg.test(checker[i])) { console.error(checked[i] + 'is not a ' + checker[i]); return false;
}
} return true;
} /
*** @description æ£æµç±»å
* 1.ç¨äºæ ¡æ£å½æ°åæ°çç±»åï¼å¦æç±»åé误ï¼ä¼æå°é误并ä¸åæ§è¡è¯¥å½æ°ï¼
* 2.ç±»åæ£æµå¿½ç¥å¤§å°åï¼å¦stringåStringé½å¯ä»¥è¯å«ä¸ºå符串类åï¼
* 3.å¢å anyç±»åï¼è¡¨ç¤ºä»»ä½ç±»ååå¯æ£æµéè¿ï¼
* 4.å¯æ£æµå¤ä¸ªç±»åï¼å¦ "number array",两è åå¯æ£æµéè¿ãæ£åæ£æµå¿½ç¥è¿æ¥ç¬¦ ï¼
*/
export function typeCheck() { const checker = Array.prototype.slice.apply(arguments); return function (target, funcName, descriptor) { let oriFunc = descriptor.value;
descriptor.value = function () { let checked = Array.prototype.slice.apply(arguments); let result = undefined; if(_check(checked,checker) ){
result = oriFunc.call(this,...arguments);
} return result;
}
}
};
tsçç±»åæ£æµé åtypeCheckåºæ¬ä¸å·²ç»æ»¡è¶³äºæ们çéè¦ã
2ãå¦ä½å¨tsä¸å¼ç¨jsæ件ï¼
ç±äºjsæ件ä¸æ²¡æç±»åæ£æµï¼æ以tsæ件å¼å ¥jsæ件æ¶ä¼è½¬å为anyç±»åï¼å½ç¶æ们ä¹å¯ä»¥å¨ .d.tsæ件ä¸å£°æç±»åã
å¦ global.d.ts æ件
å½ç¶æçæ¶åæ们éè¦ä½¿ç¨ä¸äºåºï¼ç¶è并没æ声ææ件ï¼é£ä¹æ们å¨tsæ件ä¸å¼ç¨çæ¶åå°±ä¼æ¯undefinedãè¿ä¸ªæ¶åæ们åºè¯¥æä¹åï¼
æ¯å¦ææ³è¦å¨util.tsæ件ä¸ç¨ âquery-string'çæ¶åæ们就ä¼è¿æ ·å¼ç¨ï¼
import querystring from 'query-string';
ç¶èå½ä½ æå°querystring çæ¶åæ¯undefinedãå¦ä½è§£å³å¢ï¼å°ç¼çæ¹æ³ä¹ä» ä¾åè
æ°å»ºmodule.jsæ件
import querystring from 'query-string'; export const qs = querystring;
utile.ts æ件
import { qs } from './module.js';
解å³äºãæå°qsä¸åæ¯undefinedï¼å¯ä»¥æ£å¸¸ä½¿ç¨qsåºäºå¦ã
è³æ¤æ¬æå°±å°tså¨vueä¸çé ç½®ä»ç»ç»æï¼æ¤æåªä»£è¡¨ä¸ªäººçæ³ï¼èèå°é¡¹ç®çæ©å±æ§ï¼æ以没æå ¨é¨æ¿æ¢ætsï¼åªæ¯å°è¯æ§å¨vueä¸å¼å ¥tsï¼è¿æå¾å¤éè¦æ¹è¿çå°æ¹ï¼å¦æææ´å¥½ç建议åæè§å¯ä»¥èç³»æï¼
vue/compiler-sfc源码分析学习--part2:如何处理script--day5
在vue/compiler-sfc源码分析学习系列的part2中,我们深入探讨了script部分的处理。今天是系列的最后一天,我们将重点关注script的生成和转换。
首先,html登录注册源码源码setup返回语句部分主要判断了使用的是template、inlineTemplate还是render函数。对于常规template,我们进入了第一部分逻辑,返回的`returned`包含了变量、函数、类等,但不包括defineProps、defineEmits和defineExpose这些特殊处理。
对于inline或render函数的处理,虽然重要,但这里暂且不表,留待后续章节。在`export default`部分,除了boolean类型和带有默认值的函数,其余类型定义会被移除,以符合非setup语法的双龙票指标源码要求。
接着,代码将解析后的数据整理成非setup语法糖形式,包括合并非setup块的export和导入。这部分,我们直接展示了最终的script代码,以直观展示转换过程。
在代码中,有几个关键点值得注意,特别是辅助函数的加入,如mergeDefaults,用于合并默认值。最后,总结部分重申,今天是script处理的尾声,主要工作是将setup语法糖转化为直观的代码,尤其是处理props部分的复杂性。
vueVue3中使用函数调用组件内函数和创建组件超详细+源码
在uniapp项目中,结合vue3和typescript,你可能会遇到不想频繁在视图层引入组件的困扰。传统的组件应用方式需要每次使用时都进行应用,即使不使用也需引入。为了解决这个问题,伪溯源码燕窝你可能尝试通过函数调用直接创建和操作组件。
首先,你可能会查阅到使用`createApp`方法,创建组件实例并传递参数,就像父组件传递数据给子组件。例如:
然而,直接在`createApp`中调用组件方法可能并不直接有效。此时,你可以考虑转向函数式组件(h)和`render`函数。将组件的方法挂载到vue原型链上,以便在外部函数中调用。例如在`toast.ts`中:
typescript
// toast.ts
Vue.prototype.$toast = function(message) {
// 实现 toast 方法...
};
然后在项目中这样使用:
显示提示
最后,记得分享你的发现,关注个人博客和开源项目,加入技术交流群组,与他人交流学习,共同进步。如果你在过程中遇到问题,欢迎留言,大家会一起探讨解答。
Loader源码分析-Vue Loader v
vue-loader 是什么
简单来说,vue-loader 的美尔贝源码作用是将 .Vue 文件编译成 .js 文件,这样就可以在浏览器中运行,同时也可以在 node 环境中使用 vue-server-render 进行运行。
vue-loader 的改动
相较于之前的版本,vue-loader 进行了许多重要的改动,具体细节可以参考官方的迁移指南。
vue-loader 的编译过程
vue-loader 的处理流程可以大致分为以下几个部分:
vue-loader 入口函数
vue-loader 的入口代码并不多,我将入口函数的流程绘制了一个简单的 UML 图,通过这个图可以快速对流程有一个初步的了解。
vue-loader 入口函数主要做了以下几件事:
通过上面的 UML 图可以看出,.vue 文件初次编译时会走生成 code 的流程,那么生成的 code 究竟是什么呢?
通过调试 vue-loader,将 code 打印出来,仔细观察图中红色框中的部分。
可以发现在几句 import 中,都是从 source.vue 获取对象,并且路径上携带了参数,这些参数就是 resourceQuery,type 有三种不同类型,分别是 template | script | styles。
这些 import 会继续触发新一轮的 vue-loader 执行,于是接下来就到了途中 resourceQuery 有 type 的情况。
下面是15个指标源码进行了适当删减后的源码,保留了上述涉及到的代码,对代码本身感兴趣的可以浏览。
parse .vue 组件解析
parse 方法内部处理了 vue SFC 文件,前面提到过,编译的方法默认是通过 vue-template-compiler 处理。
主要是通过 compiler.parseComponent 函数对 .vue 文件进行编译。
那么 vue-template-compiler 究竟是什么呢?
在了解 vue-template-compiler 之前,我对 vue 的编译过程有些了解,既然它们都是处理 vue SFC 文件,那么它们会不会是同一份代码呢?抱着疑问的态度,我们先看看 vue-template-compiler 的 readme.md。
This package is auto-generated. For pull requests please see src/platforms/web/entry-compiler.js.
在 readme.md 中可以看到官方对它的说明,实际上 vue-template-compiler 是一份自动生成的代码,它本质就是 vue 中的 sfc/parse。
但今天的主角并不是 vue-template-compiler,也不是 sfc/parse,我会在后面的篇章中对 vue build 的过程做一个详细的解读。
parse 流程 vue-loader 推导策略
在 vue-loader 入口函数分析中已经可以了解到,入口函数最终会生成一个 code,这个 code 包含了几个 import 语句,import 语句都含有 vue 标识并且标明了不同的分块类型。
这些 import 语句会被 VueLoaderPlugin 捕捉并做推导策略处理。
VueLoaderPlugin
老规矩,先来看 VueLoaderPlugin 的代码。
代码删减后及其简单,就一件事:注入 pitcher-loader,用于处理 vue 分块 loader 推导。
pitcher-loader
VueLoaderPlugin 的主要作用就是注入 pitcher-loader,由此可知,实际处理推导过程的是 pitcher-loader,VueLoaderPlugin 只不过是一个 loader 的注入器。
那么 pitcher-loader 是怎么做 loader 推导的呢?
前面提到入口函数生成的 code,code 中包含 import 语句。
这些 import 语句会触发 pitcher-loader,pitcher 根据 resourceQuery 来区分不同块,并生成不同的 loader request。
loader 推导流程总结
把上述过程汇聚成一张 UML 图,通过这张图可以对整个流程有一个清晰的认识。
vue-loader 的整体过程可以划分为以下几个部分:
直播带货源码,vue中点击按钮平滑滚动到页面某个div位置
直播带货源码,vue中点击按钮实现页面平滑滚动至特定div位置,操作简便高效。具体实现步骤如下:
1. 在HTML结构中添加目标div元素。
<div id="targetDiv">目标内容</div>
2. 在Vue实例中定义一个方法,用于触发滚动行为。
<script>
export default {
methods: {
scrollToTarget() {
// 获取目标div元素
const targetDiv = document.getElementById('targetDiv');
// 使用smooth属性实现平滑滚动
targetDiv.scrollIntoView({ behavior: 'smooth' });
}
}
};
</script>
3. 在Vue组件的模板中添加按钮,并绑定点击事件调用上述方法。
<button @click="scrollToTarget">滚动到目标</button>
4. 在需要触发滚动行为的时机(如按钮点击)调用scrollToTarget方法,即可实现页面平滑滚动至指定div位置。
以上介绍的直播带货源码中的vue实现点击按钮平滑滚动至特定div位置的技巧,简单易懂,适合快速集成到项目中。更多细节及优化方案,欢迎关注后续文章进行深入了解。
为 Vue3 🔥 学点 TypeScript, 什么是声明文件(declare)? [🦕全局声明篇]
学习 TypeScript 为 Vue 3 加油,探索声明文件 (declare) 的奇妙世界,特别是全局声明篇的内容。本篇将深入探讨声明文件的用途、位置以及如何在项目中运用。
声明文件,即 .d.ts 文件,是 TypeScript 用于在 JavaScript 代码中添加类型注释的关键。通过它们,我们可以明确指定变量、函数和类的类型,确保代码的可读性、可维护性和错误的早期检测。
在使用声明文件时,我们使用关键字 `declare` 来声明全局变量的类型。例如,在 Vue 3 的源码中,可以看到 `__DEV__` 等变量被明确标注为 `boolean` 类型。这样的注释使得 TypeScript 编译器在处理任何使用这些变量的 TypeScript 文件时,能够识别它们的类型,从而避免因类型未知而产生的警告或错误。
声明文件通常被放置在项目根目录下,遵循命名规则以 `.d.ts` 结尾,以确保它们能够被 TypeScript 编译器正确识别。当项目中使用到的库或框架没有对应的声明文件时,可以通过 npm 安装如 `@types/jquery` 这样的声明文件,以获得对第三方 JavaScript 库的支持。这些声明文件通常由社区贡献者或库的官方维护者提供,并位于 `node_modules/@types` 目录下。
声明文件对纯 JavaScript 项目同样大有裨益。即使项目仅使用 JavaScript,安装声明文件并配置好开发环境(例如使用 VSCode),可以利用声明文件中的类型信息进行代码提示,提升开发效率。
在某些情况下,可能需要自行编写声明文件。这通常发生在找不到对应于特定库或自定义组件的声明文件时。编写声明文件涉及定义全局变量、函数和类的类型,确保它们在 TypeScript 项目中被正确识别和使用。
全局声明是声明文件的一个重要部分,它通过 `declare` 关键字来标注全局变量的类型。例如,`declare namespace` 可以用于声明一个全局命名空间,表示后面的变量将被定义为对象。
实践上,通过修改已存在的全局声明,我们可以根据实际需求调整类型定义。例如,可以使用 TypeScript 提供的系统变量声明文件作为基础,进行必要的修改以适应具体项目需求。这涉及到对变量类型、函数签名和接口的定义,确保与实际使用的代码保持一致。
总之,掌握声明文件的使用,尤其是全局声明,对于提升 Vue 3 项目中 TypeScript 的开发体验至关重要。通过合理运用声明文件,可以有效提高代码的质量、减少错误,并提升团队协作的效率。
希望这篇关于全局声明篇的 TypeScript 学习之旅能够激发您对 TypeScript 和 Vue 3 集成的兴趣。实践是检验真理的唯一标准,多写多练,您将很快掌握这一强大工具,为项目带来显著的改进。分享了两个使用 TypeScript 的项目示例,希望能为您的项目提供一些灵感。
如果您在学习过程中有任何疑问,欢迎通过微信与我联系,我将很乐意将您引入一个热情的开发者社群。虽然微信群可能已满员,但已有成员可以邀请新成员加入。