Skip to content
New issue

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

Project3:Element Factory #11

Open
miniflycn opened this issue Jul 28, 2022 · 10 comments
Open

Project3:Element Factory #11

miniflycn opened this issue Jul 28, 2022 · 10 comments

Comments

@miniflycn
Copy link
Member

miniflycn commented Jul 28, 2022

unstable 测试那段可能还会改,具体写PPT的时候考虑加什么,其他应该好了。

相关学习

level 1:表示最少预习内容
level 2:表示课程需要学会的东西
level 3:表示课外知识

@miniflycn
Copy link
Member Author

话说有人看懂了为啥要做element factory吗?

@blankzz
Copy link

blankzz commented Aug 9, 2022

感觉是为了关注点分离,通过 compile 工厂,最后使编码只需要关注 tpl 的模板文件了

@miniflycn
Copy link
Member Author

感觉是为了关注点分离,通过 compile 工厂,最后使编码只需要关注 tpl 的模板文件了

嗯,在这里tpl和json是可以互转的,所以也便于做配置化,当然这是从技术角度思考。还可以从业务角度想想,这么做是为了什么?

@chencl1986
Copy link

chencl1986 commented Aug 24, 2022

一、大致梳理一下项目逻辑:

  1. 使用自己开发的plugin插件,将*.tpl文件,编译成Vue可以识别的组件代码
  • 使用@vue/compiler-sfc中的parse方法,将*.tpl转换成ast
  • 使用自己开发的Generator,将ast中依赖的组件抽取出来,生成import Card from './elements/card.vue'代码
  • Generator生成的代码,与*.tpl中的模板再次组合,生成VueSFC代码,再用parse方法再解析一次,即为newParsed
  • newParsed.descriptor交给@vue/compiler-sfc中的compileScript方法,编译成Vue可以执行的代码
  1. 项目构建后,/workspace/main.js中的代码
import Delegator from './card.tpl'
import data from './data/data.mjs'
const app = createApp(Delegator, data.data.result[0])

Delegator会经由步骤一,编译成可执行的代码。

  1. 实现的效果
  • 开发人员只要编写card.tpl,就可以自动构建出想要的页面布局
  • 只要有合适的插件,card.tpl也可以替换成JSON格式

二、优缺点分析

  1. 优点
  • 可以快速、批量搭建页面,减少开发人力
  • 能在此基础上进一步开发可由用户(如运营人员)自己配置和生成页面的功能
  1. 缺点
  • 由于代码都是自动生成,能实现的功能,会强烈依赖于各个组件已实现的逻辑
  • 如果组件之间的交互设计不佳,会造成很多不可预期,且难以修改的问题
  • 如果遇到定制化需求,已有组件又不好迁移到其他项目,会需要重复开发UI相同,但功能定制的组件

@worldluoji
Copy link

项目中 element.mjs 文件里, prop.type === 7 ,这里魔鬼数字7是什么意思呢?

@miniflycn
Copy link
Member Author

miniflycn commented Aug 25, 2022

项目中 element.mjs 文件里, prop.type === 7 ,这里魔鬼数字7是什么意思呢?

看代码 + debug弄出来的,可以参考vue ast的类型定义:https://github.com/vuejs/core/blob/main/packages/compiler-core/src/ast.ts#L25

如果用ts更好些,可以直接这个定义文件

@shenxiang11
Copy link

shenxiang11 commented Aug 27, 2022

buildScript() {
        const code = new Code
        const resolve = this.options.resolve || ((elementName) => {
            // 找到模版或元件的各自路径
            if (elementName.indexOf('Tpl_') > -1) {
                return `./${elementName.slice(4)}.tpl`
            } else {
                return `./elements/${toHyphenCase(elementName)}.vue`
            }
        })
        this.depencencies.forEach(dep => {
            // 注入如下形式的导入
            // import List from './elements/list.vue'
            // import Tpl_card from './card.tpl'
            // .tpl 在 workspace 下,有对应的 vite 插件,会继续被 compile
            if (this.options.browser) {
                if (dep.indexOf('Tpl_') > -1) {
                    code.addLine(`const ${dep} = window.__${dep}__`)
                } else {
                    code.addLine(`import ${dep} from '${resolve(dep)}'`)
                }
            } else {
                code.addLine(`import ${dep} from '${resolve(dep)}'`)
            }
        })

        return code.toString()
    }

什么情况下会进这个 case:

code.addLine(`const ${dep} = window.__${dep}__`)

@miniflycn
Copy link
Member Author

buildScript() {
        const code = new Code
        const resolve = this.options.resolve || ((elementName) => {
            // 找到模版或元件的各自路径
            if (elementName.indexOf('Tpl_') > -1) {
                return `./${elementName.slice(4)}.tpl`
            } else {
                return `./elements/${toHyphenCase(elementName)}.vue`
            }
        })
        this.depencencies.forEach(dep => {
            // 注入如下形式的导入
            // import List from './elements/list.vue'
            // import Tpl_card from './card.tpl'
            // .tpl 在 workspace 下,有对应的 vite 插件,会继续被 compile
            if (this.options.browser) {
                if (dep.indexOf('Tpl_') > -1) {
                    code.addLine(`const ${dep} = window.__${dep}__`)
                } else {
                    code.addLine(`import ${dep} from '${resolve(dep)}'`)
                }
            } else {
                code.addLine(`import ${dep} from '${resolve(dep)}'`)
            }
        })

        return code.toString()
    }

什么情况下会进这个 case:

code.addLine(`const ${dep} = window.__${dep}__`)

这个方法是专门给 activity-page-editor 用的,主要因为纯浏览器编译的原因,只能通过 window.xxx 将模版的依赖插进去
https://github.com/FE-star/Plan-2022/tree/main/activity-page-editor

@Lafeu-p
Copy link

Lafeu-p commented Aug 28, 2022

感觉自己对DSL和schema没有太理解,这两个到底是什么呢,他们一般用什么来具体实现或表示呢,还有就是之间有什么关系,没接触过这些,感觉有点似懂非懂的感觉,麻烦老师解答下

@miniflycn
Copy link
Member Author

感觉自己对DSL和schema没有太理解,这两个到底是什么呢,他们一般用什么来具体实现或表示呢,还有就是之间有什么关系,没接触过这些,感觉有点似懂非懂的感觉,麻烦老师解答下

不好意思没看到。DSL = 特定领域语言,可以是任何东西,用于解决特定领域的问题。

你可以认为,我们这里的 Schema 是解决搭建的特定语言(DSL)。而我们项目指的 DSL 是给外包开发这一特定领域的 DSL。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants