We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在做组件库的时候,发现了一个自动引入组件的插件,简单研究了下
以 vite + vue3 的使用为例子
<script setup lang='ts'> import { ref } from 'vue' </script> <template> <div class="block"> <ComponentA msg="a" /> </div> </template>
// vite.config.ts import Components from 'unplugin-vue-components/vite' export default defineConfig({ plugins: [ Components({ /* options */ }), ], })
路径 src/core/unplugin.ts
async transform(code, id) { if (!shouldTransform(code)) return null try { const result = await ctx.transform(code, id) ctx.generateDeclaration() return result } catch (e) { this.error(e) } }
上面的 code 是每个单文件的 vue3 编译好的代码
import { defineComponent as _defineComponent } from "vue"; const _sfc_main = /* @__PURE__ */ _defineComponent({ __name: "App", setup(__props, { expose }) { expose(); const __returned__ = {}; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }); import { resolveComponent as _resolveComponent, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"; const _hoisted_1 = { class: "block" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_ComponentA = _resolveComponent("ComponentA"); return _openBlock(), _createElementBlock("div", _hoisted_1, [ _createVNode(_component_ComponentA, { msg: "a" }) ]); }
export default function transformer(ctx: Context, transformer: SupportedTransformer): Transformer { return async (code, id, path) => { ctx.searchGlob() const sfcPath = ctx.normalizePath(path) debug(sfcPath) const s = new MagicString(code) await transformComponent(code, transformer, s, ctx, sfcPath) s.prepend(DISABLE_COMMENT) const result: TransformResult = { code: s.toString() } if (ctx.sourcemap) result.map = s.generateMap({ source: id, includeContent: true }) return result } }
其中 transformComponent 的作用就是通过正则 取出 _resolveComponent 引入的组件名
export default async function transformComponent(code: string, transformer: SupportedTransformer, s: MagicString, ctx: Context, sfcPath: string) { let no = 0 const results: ResolveResult[] = [] for (const match of code.matchAll(/_resolveComponent[0-9]*\("(.+?)"\)/g)) { const matchedName = match[1] if (match.index != null && matchedName && !matchedName.startsWith('_')) { const start = match.index const end = start + match[0].length results.push({ rawName: matchedName, replace: resolved => s.overwrite(start, end, resolved), }) } } for (const { rawName, replace } of results) { debug(`| ${rawName}`) const name = pascalCase(rawName) ctx.updateUsageMap(sfcPath, [name]) const component = await ctx.findComponent(name, 'component', [sfcPath]) if (component) { const varName = `__unplugin_components_${no}` s.prepend(`${stringifyComponentImport({ ...component, as: varName }, ctx)};\n`) no += 1 replace(varName) } } }
stringifyComponentImport 方法的作用就是构造出 ComponentA import 代码
import { ${info.name} as ${info.as} } from '${info.from}' // => import ComponentA as ComponentA from 'ComponentA path'
import __unplugin_components_0 from 'xxxx/vite-vue3/src/components/ComponentA.vue'; import { defineComponent as _defineComponent } from "vue"; const _sfc_main = /* @__PURE__ */ _defineComponent({ __name: "App", setup(__props, { expose }) { expose(); const __returned__ = {}; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }); import { resolveComponent as _resolveComponent, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"; const _hoisted_1 = { class: "block" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_ComponentA = __unplugin_components_0; return _openBlock(), _createElementBlock("div", _hoisted_1, [ _createVNode(_component_ComponentA, { msg: "a" }) ]); }
插件的思路其实跟我们手动 import 的操作是一样的,帮我们做了这样的引入操作
The text was updated successfully, but these errors were encountered:
No branches or pull requests
在做组件库的时候,发现了一个自动引入组件的插件,简单研究了下
以 vite + vue3 的使用为例子
使用
原理
路径 src/core/unplugin.ts
上面的 code 是每个单文件的 vue3 编译好的代码
路径:src/core/transformer.ts
其中 transformComponent 的作用就是通过正则 取出 _resolveComponent 引入的组件名
stringifyComponentImport 方法的作用就是构造出 ComponentA import 代码
总结
插件的思路其实跟我们手动 import 的操作是一样的,帮我们做了这样的引入操作
The text was updated successfully, but these errors were encountered: