Open miniflycn opened 2 years ago
话说有人看懂了为啥要做element factory吗?
感觉是为了关注点分离,通过 compile 工厂,最后使编码只需要关注 tpl 的模板文件了
感觉是为了关注点分离,通过 compile 工厂,最后使编码只需要关注 tpl 的模板文件了
嗯,在这里tpl和json是可以互转的,所以也便于做配置化,当然这是从技术角度思考。还可以从业务角度想想,这么做是为了什么?
一、大致梳理一下项目逻辑:
使用自己开发的plugin
插件,将*.tpl
文件,编译成Vue
可以识别的组件代码
@vue/compiler-sfc
中的parse
方法,将*.tpl
转换成ast
Generator
,将ast
中依赖的组件抽取出来,生成import Card from './elements/card.vue'
代码Generator
生成的代码,与*.tpl
中的模板再次组合,生成Vue
的SFC
代码,再用parse
方法再解析一次,即为newParsed
newParsed.descriptor
交给@vue/compiler-sfc
中的compileScript
方法,编译成Vue
可以执行的代码项目构建后,/workspace/main.js
中的代码
import Delegator from './card.tpl'
import data from './data/data.mjs'
const app = createApp(Delegator, data.data.result[0])
Delegator
会经由步骤一,编译成可执行的代码。
实现的效果
card.tpl
,就可以自动构建出想要的页面布局card.tpl
也可以替换成JSON
格式二、优缺点分析
优点
缺点
项目中 element.mjs 文件里, prop.type === 7 ,这里魔鬼数字7是什么意思呢?
项目中 element.mjs 文件里, prop.type === 7 ,这里魔鬼数字7是什么意思呢?
看代码 + debug弄出来的,可以参考vue ast的类型定义:https://github.com/vuejs/core/blob/main/packages/compiler-core/src/ast.ts#L25
如果用ts更好些,可以直接这个定义文件
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}__`)
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
感觉自己对DSL和schema没有太理解,这两个到底是什么呢,他们一般用什么来具体实现或表示呢,还有就是之间有什么关系,没接触过这些,感觉有点似懂非懂的感觉,麻烦老师解答下
感觉自己对DSL和schema没有太理解,这两个到底是什么呢,他们一般用什么来具体实现或表示呢,还有就是之间有什么关系,没接触过这些,感觉有点似懂非懂的感觉,麻烦老师解答下
不好意思没看到。DSL = 特定领域语言,可以是任何东西,用于解决特定领域的问题。
你可以认为,我们这里的 Schema 是解决搭建的特定语言(DSL)。而我们项目指的 DSL 是给外包开发这一特定领域的 DSL。
unstable
测试那段可能还会改,具体写PPT的时候考虑加什么,其他应该好了。相关学习
level 1
:表示最少预习内容level 2
:表示课程需要学会的东西level 3
:表示课外知识level3
(在一家低代码公司做的小方案,用模版语言生成React Component,这个项目演示了 parse 和 generator 可以做些啥)level1
(error event)level2
(怎么捕获错误)level2
(错误上报后总是会发现Script Error.咋办)level1
(try catch)level1
(Promise reject)level1
level2
level3
https://github.com/FE-star/exercise1https://github.com/FE-star/exercise2