NutUIv3版本已经发布一年了,内外部开发者都在各自不同的业务场景下开发和使用,我们自豪的同时压力也是翻倍,我们正在积极努力解决开发者的各种问题,扩展组件功能,尽可能满足开发者的需求。今年以来,新增了多个技术栈(React)、组件级UI定制、国际化、代码智能提示能力。本文将介绍代码智能提示(Vscode插件)的功能,并为大家详细解析NutUI-Vscode的实现。直观体验什么是CodeSmartTips?为了让大家有一个直观的认识,我们来仔细看看下面两张gif图~组件库没有任何代码提示。组件库有了智能提示后,不知道大家看到上面两张图有什么感想。?显然,我们使用智能提示后,无论是快速查看文档还是查看组件属性,查阅起来都会非常方便。当然,开发效率肯定有明显的提升。那么,就让我们自己来体验一下吧~使用指南Tips:NutUI官网-开发工具支持,这里也简单介绍一下~在vscode中安装nutui-vscode-extension插件,安装vetur插件.如果你不知道这个插件,这里有一个介绍。安装好以上两个插件后,重启我们的vscode,就可以愉快的体验NutUI的智能提示功能了。是不是太简单了~体验完了,要不要跟着?我一起熟悉它的原理。既然是开发vscode插件,首先要熟悉它的开发、调试、发布流程。文件已发送给您。看完这里,熟悉了基本的vscode开发流程,跟着我一步步揭开这个智能提示功能的神秘面纱吧~360全方位解读快速查看组件文档从上图可以看出,当我们在使用NutUI开发的时候,当我们写完一个组件nut-button,当鼠标悬停在组件上时,会出现一个提示,点击提示打开Button组件的官方文档。我们可以快速查看对应的API来使用它进行开发。首先我们需要在vscode生成的工程中找到对应的钩子函数activate,在里面注册一个Provider,然后通过provideHover解析定义的类型文件。constfiles=['vue','typescript','javascript','react'];exportfunctionactivate(context:vscode.ExtensionContext){context.subscriptions.push(vscode.languages.registerHoverProvider(files,{provideHover}));}接下来我们看看provideHover是如何实现的?constLINK_REG=/(?<={constline=document.lineAt(position);//根据鼠标位置读取当前行constcomponentLink=line.text.match(LINK_REG)??[];//匹配以nut开头的字符串-constcomponentBigLink=line.text.match(BIG_LINK_REG)??[];constcomponents=[...newSet([...componentLink,...componentBigLink.map(kebabCase)])];//匹配当前Hover行中包含的组件site}=componentMap[item];返回新的vscode.MarkdownString(`[NutUI->$(references)请查看${bigCamelize(item)}组件官方文档](${DOC}${site})\n`,true);});返回新的vscode.Hover(文本);}};通过vscode提供的API和对应的正则匹配,获取当前Hover行包含的组件,然后通过遍历返回不同组件对应的MarkDownString,最后返回vscode.Hover对象。细心的你可能已经发现了,里面还包含一个componentMap,它是一个对象,里面包含了所有组件的官网链接地址和props信息。其大致内容如下:exportinterfaceComponentDesc{site:string;道具?:字符串[];}exportconstcomponentMap:Record={actionsheet:{site:'/actionsheet',props:["v-model:visible=''"]},address:{site:'/address',props:["v-model:visible=''"]},addresslist:{site:'/addresslist',props:["data=''"]}...}为了让各个组件及时更新同步,componentMap对象的生成会通过本地脚本执行,然后自动注入。每次插件更新发布时都会执行,保证与当前组件及对应信息的一致性。这里的组件及其包含的信息需要从项目目录中获取。这里的实现与后面介绍的一些内容类似。可以先想想实现方法。具体实现细节后面会详细讲解~组件自动完成我们使用NutUI组件库进行项目开发。当我们输入nut-时,编辑器会显示出我们当前组件库中包含的所有组件。当我们使用上下键快速选中其中一个组件并回车时,编辑器会自动帮我们完成选中的组件,并带出当前选中组件的其中一个道具,方便我们快速定义。这里的实现,我们还需要在vscode的钩子函数activate中注册一个Provider。vscode.languages.registerCompletionItemProvider(files,{provideCompletionItems,resolveCompletionItem})其中provideCompletionItems需要输出当前组件库包含的组件completionItems,用于自动补全。constprovideCompletionItems=()=>{constcompletionItems:vscode.CompletionItem[]=[];Object.keys(componentMap).forEach((key:string)=>{completionItems.push(newvscode.CompletionItem(`nut-${key}`,vscode.CompletionItemKind.Field),newvscode.CompletionItem(bigCamelize(`nut-${key}`),vscode.CompletionItemKind.Field));});returncompletionItems;};resolveCompletionItem定义了光标选择当前自动完成组件触发的动作,这里我们需要重新定义光标的位置。constresolveCompletionItem=(item:vscode.CompletionItem)=>{constname=kebabCase(item.label).slice(4);const描述符:ComponentDesc=componentMap[name];constpropsText=descriptor.props?描述符。道具:'';consttagSuffix=`${item.label}>`;item.insertText=`<${item.label}${propsText}>${tagSuffix}`;item.command={title:'nutui-move-cursor',command:'nutui-move-cursor',arguments:[-tagSuffix.length-2]};归还物品;};其中arguments表示游标的位置参数,一般我们自动完成选择后,游标会在props的引号内,方便定义。我们结合当前完成字符串的规则,这里光标的位置是比较确定的。就是闭合标签的字符串长度-tagSuffix.length,然后是前2个字符的位置。即参数:[-tagSuffix.length-2]。最后需要在activate钩子函数中注册nutui-move-cursor命令的执行,在moveCursor中执行光标移动。这实现了我们的自动完成功能。constmoveCursor=(characterDelta:number)=>{constactive=vscode.window.activeTextEditor!.selection.active!;constposition=active.translate({characterDelta});vscode.window.activeTextEditor!.selection=新的vscode。Selection(position,position);};exportfunctionactivate(context:vscode.ExtensionContext){vscode.commands.registerCommand('nutui-move-cursor',moveCursor);}什么?这些还不够吗?还有更聪明的吗?我不需要阅读组件文档,我仍然可以轻松开发它。emm~~~,当然请听下面vetur智能提示的讲解提到vetur,熟悉Vue的同学一定不陌生,它是Vue官方开发的一款插件,具有代码高亮等功能以及识别Vue文件。借助它,我们可以让自己的组件库中的组件自动识别道具,并给出与官网相同的详细描述。vetur的详细介绍见这里。如上,当我们使用组件Button时,它会自动提示组件中定义的所有属性。当你按上下键快速切换时,右侧会显示当前选中属性的详细说明,这样我们不用看文档,就可以看到详细说明和默认值这里的每一个属性,这样的开发太爽了~仔细看了文档,我们可以了解到vetur已经为我们提供了配置项,我们只需要简单的配置一下,像这样://packag.json{..."vetur":{"tags":"dist/smartips/tags.json","attributes":"dist/smartips/attributes.json"},...}需要包含tags.json和attributes.json在我们的包目录中。我们还可以查看当前两个文件的内容://tags.json{"nut-actionsheet":{"attributes":["v-model:visible","menu-items","option-tag","option-sub-tag","choose-tag-value","color","title","description","cancel-txt","close-abled"]},...}//属性.json{"nut-actionsheet/v-model:visible":{"type":"boolean","description":"属性说明:遮罩层可见,默认值:false"},"nut-actionsheet/menu-items":{"type":"array","description":"属性描述:列表项,默认值:[]"},"nut-actionsheet/option-tag":{"type":"string","description":"属性描述:设置列表项标题显示参数,默认值:'name'"},...}显然,这两个文件也是需要的我们使用脚本来生成与上面提到的相同,其中涉及组件及其相关信息。为了保持一致并保持一份,我们这里通过各个组件源码下的doc.md文件获取。因为,这个文件包含了组件的props及其详细描述和默认值。Componentpropsdetails标签、属性、componentMap都需要获取这些信息。我们先来看看doc.md中包含了什么?##简介##基本用法...###道具|领域|说明|类型|默认||------|------------------------------------------------------------------|------|------||尺码|设置头像大小,可选值有:large、normal、small,支持直接输入数字|字符串|正常||形状|设置头像的形状,可以选择的值有:方形,圆形|字符串|round|...各个组件的md文档。我们在预览的时候使用vite提供的插件vite-plugin-md生成对应的html,这个插件引用了markdown-it这个模块。因此,如果我们现在要解析md文件,还需要使用markdown-it模块提供的parseAPI//FunctiongetSourcesletsources=MarkdownIt.parse(data,{});//data表示内容文档的,sources代表解析列表显示。这里解析的是Token列表。在Token中,我们只关心类型。因为我们要的是props,这部分对应的Token类型就是table_open和table_close之间包含的部分。考虑文档中的多个表。这里我们总是取第一个,这是我们开发人员在写文档的时候需要注意的。得到中间部分后,我们只需要在此基础上再次过滤,选择tr_open和tr_close之间的中间部分,然后用type=inline过滤中间部分。最后,取Token对象中的内容字段。然后根据以上三个文件的不同要求做相应的处理。constgetSubSources=(sources)=>{让sourcesMap=[];conststartIndex=sources.findIndex((source)=>source.type===TYPE_IDENTIFY_OPEN);constendIndex=sources.findIndex((source)=>source.type===TYPE_IDENTIFY_CLOSE);sources=sources.slice(startIndex,endIndex+1);while(sources.filter((source)=>source.type===TR_TYPE_IDENTIFY_OPEN).length){让trStartIndex=sources.findIndex((source)=>source.type===TR_TYPE_IDENTIFY_OPEN);让trEndIndex=sources.findIndex((source)=>source.type===TR_TYPE_IDENTIFY_CLOSE);sourcesMap.push(sources.slice(trStartIndex,trEndIndex+1));sources.splice(trStartIndex,trEndIndex-trStartIndex+1);}返回sourcesMap;};好了,以上就是分析的全部内容。总结一下,无非几点:1.创建一个基于vscode的项目,在它提供的hooks中注册不同行为的命令和语言,并实现相应的行为2.结合vetur和configure包。json3。对于地图json文件,需要提供相应的生成脚本来保证信息的一致性。这里解析md,需要用到markdown-it提供的parse函数。最后,从直观体验到实际使用再到实现原理分析,本文带你一步步体验NutUI与VSCode结合给你带来的好处,让你在开发中有全新的体验,同时也让我们的组件库越来越充满魅力。接下来就让我们一起努力,让它发挥出更强大的价值吧~相关文档NutUI官网:https://nutui.jd.com/#/NutUI-React版:https://jelly.jd.com/article/61d3b7c47cbc44b32c1427c9NutUI-UI定制:https://jelly.jd.com/article/623af906f25db001d3f9dc26VSCode:https://code.visualstudio.com/docs期待您的使用和反馈??~