diff --git a/README.md b/README.md index 7acae0d..c5913a2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -# LCG-VCC +# VCC -VCC是Low Code Generator中独立的Vue组件代码编辑器。可以独立运行。 +VCC(Vue Compontent Creator)是Low Code Generator中独立的Vue组件代码编辑器。可以独立运行。 + +> 当前已经升级至Vue3 + Vite。 **通过它可以通过拖拽快速完成Vue组件代码骨架的搭建。详见后文视频介绍链接。** @@ -101,9 +103,9 @@ new Vue({ npm i ``` -再进行启动: +再进行启动(Vite): ``` -npm run serve +npm run vite ``` 运行完成后,就可以访问[http://localhost:8008/](http://localhost:8008/)预览效果了. @@ -114,6 +116,22 @@ npm run serve [【拖拽式Vue组件代码生成平台(LCG)介绍视频-哔哩哔哩】https://b23.tv/FInuZ8](https://b23.tv/FInuZ8) [【LCG近期功能更新介绍-哔哩哔哩】https://b23.tv/SAHwVq](https://b23.tv/SAHwVq) +## 贡献 + +1. Fork 仓库 +2. 创建分支 (`git checkout -b my-new-feature`) +3. 提交修改 (`git commit -am 'Add some feature'`) +4. 推送 (`git push origin my-new-feature`) +5. 创建 PR + +## 欢迎 fork 和反馈 + +如有建议或意见,欢迎在 github [issues](https://github.com/sahadev/vue-component-creater-ui/issues) 区提问 + +## 协议 + +本仓库遵循 [MIT 协议](http://www.opensource.org/licenses/MIT) + ## 有疑问? 可以通过sahadev@foxmail.com给我发送邮件,我会及时回复的。 @@ -122,4 +140,6 @@ npm run serve +如果遇到群二维码过期的情况,可以加我微信:SAHADEV-smile,我拉你入群。加我微信时请备注VCC。 + 另外我也特别希望可以和大家一起做这个项目。这个项目目前主要面对的是前端开发者。后期可以面向后端开发者与产品与UE。 diff --git a/index.html b/index.html index 14f25c6..0e64358 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,8 @@ - Vite App + 拖拽式Vue组件代码生成编辑器(VCC) + `); - }); - - scripts.push(` - - - - diff --git a/src/libs/main-panel.js b/src/libs/main-panel.js index 185517b..ce7cc4b 100644 --- a/src/libs/main-panel.js +++ b/src/libs/main-panel.js @@ -11,6 +11,7 @@ import { getRawComponentContent, getRawComponentKey, isObject } from '@/utils/co import { createNewCodeGenerator } from "@/libs/code-generator-factory"; import EventEmitter from 'eventemitter3' import { cloneDeep } from 'lodash-es'; +import scope from 'css-scoped'; /** * 主控制面板辅助类,用于代码的生成与绘制 @@ -44,8 +45,6 @@ export class MainPanelProvider { console.groupCollapsed('---> for code generator warn <---'); - const readyForMoutedElement = this.createMountedElement(); - // 生成原始代码 let code = this.codeGenerator.outputVueCodeWithJsonObj(rawDataStructure); @@ -61,6 +60,8 @@ export class MainPanelProvider { const { template, script, styles, customBlocks } = parseComponent(code); + this.loadStyle(styles); + let newScript = script.content.replace(/\s*export default\s*/, "") const componentOptions = (new Function(`return ${newScript}`))(); @@ -69,6 +70,7 @@ export class MainPanelProvider { if (this.editMode) { // 渲染当前代码 + const readyForMoutedElement = this.createMountedElement(); createBaseApp(componentOptions).mount(readyForMoutedElement); // 拍平数据结构 @@ -99,6 +101,21 @@ export class MainPanelProvider { this.reRender(); } + loadStyle(styles) { + if (styles.length > 0) { + const scopedStyle = styles[0]; + + this.styleNodeName = `cssScoped${Date.now()}`; + + const scopedCss = scope(scopedStyle.content.replace(/::v-deep/g, ''), this.styleNodeName); + const styleNode = document.createElement('style'); + styleNode.innerText = scopedCss; + + // 这个会导致越来越卡 + document.head.appendChild(styleNode); + } + } + /** * 初始化代码编译 */ @@ -122,6 +139,10 @@ export class MainPanelProvider { */ createMountedElement() { const renderControlPanel = this.getControlPanelRoot(); + + if (this.styleNodeName) { + renderControlPanel.setAttribute('class', this.styleNodeName); + } return renderControlPanel; } diff --git a/src/script/compileComponent.js b/src/script/compileComponent.js index 58e2c2b..5894c70 100644 --- a/src/script/compileComponent.js +++ b/src/script/compileComponent.js @@ -95,12 +95,22 @@ function convert2Map(jsonObj) { } } +function findProperty(properties, findWhoStructure) { + return properties.find(item=>{ + if(item.key.name === findWhoStructure){ + return true; + } + }) +} + // 对JS代码进行编译 function compileJsCode(code, onEncounterDuplicateDeclared = () => { }) { const ast = espree.parse(code, { ecmaVersion: 6, sourceType: "module" }); // 提取data中返回的对象结构, 如果文件引入了其它文件, 则body[0]为import语句。 if (ast.body[0].declaration) { - const dataAst = ast.body[0].declaration.properties[0].value.body.body[0].argument; + const properties = ast.body[0].declaration.properties; + const dataProperty = findProperty(properties, 'data'); + const dataAst = dataProperty.value.body.body[0].argument; const newCode = escodegen.generate(dataAst); // 这里编译的组件内部应当只包含data和method,不应该包含其它属性 diff --git a/src/utils/get-imports.js b/src/utils/get-imports.js deleted file mode 100644 index 046931d..0000000 --- a/src/utils/get-imports.js +++ /dev/null @@ -1,18 +0,0 @@ -export default function(code, { imports }) { - return { - name: 'get-imports', - - visitor: { - ImportDeclaration(path) { - imports.push({ - variables: path.node.specifiers.map(spec => ({ - local: spec.local.name, - imported: spec.imported ? spec.imported.name : 'default' - })), - module: path.node.source.value - }); - path.remove(); - } - } - }; -} diff --git a/src/utils/get-pkgs.js b/src/utils/get-pkgs.js deleted file mode 100644 index 4b95956..0000000 --- a/src/utils/get-pkgs.js +++ /dev/null @@ -1,40 +0,0 @@ -import parsePackageName from 'parse-package-name'; - -export default async function(code, imports, scripts) { - const replacements = []; - - for (const [index, item] of imports.entries()) { - const moduleName = `__npm_module_${index}`; - const pkg = parsePackageName(item.module); - const version = pkg.version || 'latest'; - scripts.push({ - path: pkg.path ? `/${pkg.path}` : '', - name: moduleName, - module: - pkg.name === 'vue' && !pkg.path - ? `vue@${version}/dist/vue.esm.js` - : `${pkg.name}@${version}` - }); - let replacement = '\n'; - for (const variable of item.variables) { - if (variable.imported === 'default') { - replacement += `var ${ - variable.local - } = ${moduleName}.default || ${moduleName};\n`; - } else { - replacement += `var ${variable.local} = ${moduleName}.${ - variable.imported - };\n`; - } - } - if (replacement) { - replacements.push(replacement); - } - } - - if (replacements.length > 0) { - code = replacements.join('\n') + code; - } - - return code; -} diff --git a/src/utils/iframe.js b/src/utils/iframe.js deleted file mode 100644 index 3079425..0000000 --- a/src/utils/iframe.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * From: https://github.com/egoist/codepan/blob/2c22bb3d7a7a4e31fd99fc640d320f7ec24d2951/src/utils/iframe.js - */ -import { Loading } from 'element-ui'; -class Iframe { - constructor({ container, el, sandboxAttributes = [] }) { - if (!el) { - throw new Error('Expect "el" to mount iframe to!'); - } - this.$container = container; - this.$el = el; - this.sandboxAttributes = sandboxAttributes; - } - - setHTML(obj) { - let html; - - if (typeof obj === 'string') { - html = obj; - } else { - const { head = '', body = '' } = obj; - html = `${head}${body}`; - } - - // 关闭上一个实例引起的loading - if (this.loadingInstance) { - this.loadingInstance.close(); - } - - this.loadingInstance = Loading.service({ - target: this.$container, - text: '渲染中,请稍后...' - }); - - const iframe = this.createIframe(); - iframe.addEventListener('load', () => { - this.loadingInstance.close(); - }) - - this.$el.parentNode.replaceChild(iframe, this.$el); - iframe.contentWindow.document.open(); - iframe.contentWindow.document.write(html); - iframe.contentWindow.document.close(); - - this.$el = iframe; - } - - createIframe() { - const iframe = document.createElement('iframe'); - iframe.setAttribute('sandbox', this.sandboxAttributes.join(' ')); - iframe.setAttribute('scrolling', 'yes'); - iframe.style.width = '100%'; - iframe.style.height = '100%'; - iframe.style.border = '0'; - return iframe; - } -} - -export default (...args) => new Iframe(...args); diff --git a/src/utils/params.js b/src/utils/params.js deleted file mode 100644 index d04db44..0000000 --- a/src/utils/params.js +++ /dev/null @@ -1,55 +0,0 @@ -import qs from 'query-string'; -import deepmerge from 'deepmerge'; - -const DEFAULT_PARAMS = { - pkgs: ['https://static.imonkey.xueersi.com/vue-code-creater/resource/vue.js', 'https://static.imonkey.xueersi.com/vue-code-creater/resource/element-ui/index.js'], - css: ['https://static.imonkey.xueersi.com/vue-code-creater/resource/element-ui/index.css'], -}; - -let params = DEFAULT_PARAMS; - -function getArr(str) { - if (Array.isArray(str)) { - return str; - } - if (typeof str === 'string') { - return str.split(','); - } - return []; -} - -export function clear() { - params = DEFAULT_PARAMS; -} - -export function parse(str) { - try { - merge(JSON.parse(str)); - } catch (e) { - console.error('error', e.message); - } -} - -export function queryParse(str) { - const query = qs.parse(str); - const pkgs = getArr(query.pkg); - const css = getArr(query.css); - const options = { pkgs, css }; - - if (query.cdn) { - options.cdn = query.cdn; - } - if (query.vue) { - options.vue = query.vue; - } - - merge(options); -} - -export function get() { - return deepmerge(DEFAULT_PARAMS, params); -} - -export function merge(opts) { - params = deepmerge(params, opts); -} diff --git a/vite.config.js b/vite.config.js index bbaee64..f2739b4 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,6 +1,5 @@ import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; -import ViteRequireContext from "@originjs/vite-plugin-require-context"; import path from "path"; @@ -8,7 +7,6 @@ import path from "path"; export default defineConfig({ plugins: [ vue(), - ViteRequireContext(), ], resolve: { alias: [