好家伙,
完整代码已开源
https://github.com/Fattiger4399/ph-questionnaire.git
本片我们来讲述
如何将dsl的数据渲染为视图
dsl: { component: 'div', wid: 0, props: { }, style: { background: ' #FFF8DC' }, children: [ { wid: 1,//序号 component: 'ph-radio', //组件名 props: { //组件数据接口 No: 1, title: "我是输入框", options_1: "选项一一", options_2: "选项二二" }, style: { top: '300px', left: '300px', zIndex: '1', border: "2px dashed red" },//组件配置项 attrs: { }, events: { } }, ]复制
h
函数是 Vue.js 中的一个辅助函数,通常用于创建虚拟 DOM 元素(VNode)。
在 Vue.js 中,h
函数实际上是 createElement
函数的别名
createElement
函数是 Vue.js 内部用来创建虚拟 DOM 元素(VNode)的核心函数。
h
函数接收三个参数
代码如下:
<script> export default { data() { return { a: true } }, props: ['dsl', 'model'], render(h) { let dsl = this.dsl; return this.generator(h, dsl); }, methods: { adddraggable() { }, select(e) { console.log(e); }, generator(h, dsl) { //h(tagName,props,children) //当前元素,元素属性,子元素 return h(dsl.component, this.generateProps(h, dsl), this.generateChildren(h, dsl)); }, generateProps(h, dsl) { let self = this; let result = { } result.props = { ...dsl.props } result.attrs = { ...dsl.attrs } result.style = { ...dsl.style } if (self.model.selected) { if (self.model.selected.wid == dsl.wid) { // 获取所有的按钮元素 const allElements = document.getElementById('editor.div') console.log(allElements) } } if (dsl.events) { result.on = { click: function (e) { // console.log(e, dsl.wid, this); e.preventDefault(); self.$emit('select', { e, dsl }); }, }; } return result; },/** * 该函数用于生成child节点 * @param {*} h * @param {*} dsl */ generateChildren(h, dsl) { let result = dsl.children && dsl.children.map((child) => this.generator(h, child)) || []; // (A&&B)||C if (dsl.text) result.push(dsl.text) // console.log(result) return result; } }, mounted() { } } </script>复制
解释
本质上是对props属性递归处理后,使用vue的h函数将dsl全部渲染出来
让我们把重点放在这句上
return h(dsl.component, this.generateProps(h, dsl), this.generateChildren(h, dsl));复制
generator
方法用于生成 Vue 元素,根据传入的 dsl
配置信息,设置元素的属性、样式、事件等,并返回生成的元素。
generateProps
方法用于生成元素的属性,包括 props
、attrs
和 style
,同时根据条件判断是否添加事件监听器。
generateChildren
方法用于生成元素的子元素,遍历 dsl
中的 children
,对每个子元素调用 generator
方法生成对应的 Vue 元素,并返回所有子元素的数组。
最终效果如下: