FE-star / Plan-2022

2022年新一代前端课程
49 stars 20 forks source link

Project3:Element Factory #11

Open miniflycn opened 2 years ago

miniflycn commented 2 years ago

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

相关学习

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

miniflycn commented 2 years ago

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

blankzz commented 2 years ago

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

miniflycn commented 2 years ago

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

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

chencl1986 commented 2 years ago

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

  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可以执行的代码
  2. 项目构建后,/workspace/main.js中的代码

    import Delegator from './card.tpl'
    import data from './data/data.mjs'
    const app = createApp(Delegator, data.data.result[0])

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

  3. 实现的效果

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

二、优缺点分析

  1. 优点

    • 可以快速、批量搭建页面,减少开发人力
    • 能在此基础上进一步开发可由用户(如运营人员)自己配置和生成页面的功能
  2. 缺点

    • 由于代码都是自动生成,能实现的功能,会强烈依赖于各个组件已实现的逻辑
    • 如果组件之间的交互设计不佳,会造成很多不可预期,且难以修改的问题
    • 如果遇到定制化需求,已有组件又不好迁移到其他项目,会需要重复开发UI相同,但功能定制的组件
worldluoji commented 2 years ago

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

miniflycn commented 2 years ago

项目中 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 commented 2 years ago
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 commented 2 years ago
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 commented 2 years ago

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

miniflycn commented 2 years ago

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

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

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