UNPKG

tfp

Version:

A Web UI framework for TaskBuilder

296 lines (269 loc) 11.6 kB
export default class TFPComponentRender { constructor(__tfp, _dataModel, _level) { if(!__tfp) { throw new Error("请提供tfp对象!"); return; } if(!_dataModel) { throw new Error("请提供组件数据模型!"); return; } this._tfp = __tfp; this.dataModel = _dataModel; this.metadata = this._tfp.type(this.dataModel.type); this.level = 0; //组件相对页面组件的层次 if(_level) this.level = _level; } get cpt() { return this._tfp.components[this.dataModel.id]; } get isContainer() { return this._tfp.components[this.dataModel.id].isContainer; } getHtmlIndent() { return this.cpt.getHtmlIndent(); } getAttrHtml(retainStyleAttr) { let attrHtml = ""; let attrs = this.metadata.attrs; let arrAttr = []; for(let i=0;i<attrs.length;i++) { let attrInfo = attrs[i]; if(attrInfo.type=="group") { for(let j=0;j<attrInfo.items.length;j++) { arrAttr.push(attrInfo.items[j]); } } else { arrAttr.push(attrInfo); } } for(let i=0;i<arrAttr.length;i++) { let attrInfo = arrAttr[i]; if ((attrInfo.isHtmlAttr || attrInfo.attrName) && attrInfo.name in this.dataModel) { let attrVal = this.dataModel[attrInfo.name]; if (!attrVal || attrVal == 0 || attrVal == false || attrVal == "false") continue; //如果是特殊属性,则调用自定义方法获得属性html if (attrInfo.special && this.getCustomAttrHtml) { attrHtml += this.getCustomAttrHtml(attrInfo.name); continue; } if (typeof (attrVal) == "string" && ((attrVal.indexOf("{") >= 0 && attrVal.indexOf("}") > 0) || (attrVal.indexOf("#[") >= 0 && attrVal.indexOf("]") > 0))) { //如果不是设计时,并且不是组件值属性,则不渲染,但不包括在数据表格行里动态生成的组件 if (!(this._tfp.isDesigning && attrInfo.name == "value") && !retainStyleAttr) continue; } //设计时组件不能禁用,否则无法点击获得焦点 if (this._tfp.isDesigning && attrInfo.name == "disabled") continue; if (attrInfo.name == "disabled" || attrInfo.name == "readonly") { attrHtml += " " + attrInfo.name; if (attrVal == false || attrVal == "false") attrHtml += "=\"false\""; } else { var vvv = this.dataModel[attrInfo.name]; //HTML标签的属性名必须小写 if (attrInfo.attrName) attrHtml += " " + attrInfo.attrName.toLowerCase() + "=\"" + vvv + "\""; else attrHtml += " " + attrInfo.name.toLowerCase() + "=\"" + vvv + "\""; } } } //事件 if(!this._tfp.isDesigning && this.metadata.events) { for(var i=0;i<this.metadata.events.length;i++) { let eventInfo = this.metadata.events[i]; //如果不是HTML事件,则忽略 if(eventInfo.isNotHtmlEvent) continue; //input type=text 的onchange事件在代码里修改值不会触发,需要在各个组件里处理 //页面加载事件不能直接写在body标签的属性里,因为需要等tfp组件解析完毕 if(eventInfo.name.toLowerCase()=="onchange" || (this.cpt.type=="Page" && eventInfo.name.toLowerCase()=="onload")) continue; for(let propName in this.dataModel) { //事件名称忽略大小写 if(eventInfo.name.toLowerCase()==propName.toLowerCase()) { let eventFunc = this.dataModel[propName]; //如果事件处理函数内有数据绑定表达式,则不渲染,但不包括在数据表格行里动态生成的组件 if (!retainStyleAttr && ((eventFunc.indexOf("{") >= 0 && eventFunc.indexOf("}") > 0) || (eventFunc.indexOf("#[") >= 0 && eventFunc.indexOf("]") > 0))) continue; if (eventInfo.eventArgs != "") if (eventFunc.indexOf("(") < 0 || eventFunc.indexOf(")") < 0) eventFunc += "()"; attrHtml += " " + eventInfo.name.toLowerCase() + "=\"" + eventFunc + "\""; break; } } } } return attrHtml; } /** * 获得组件的样式HTML * @param {Boolean} isGetHead [description] * @param {[type]} retainStyleAttr 是否在组件的HTML标签的属性中保留CSS样式代码, * 例如移动端数据表格组件的数据行里的子组件,因为是动态生成的,没有唯一的id * @return {[type]} [description] */ getStyleHtml(isGetHead, retainStyleAttr) { let styleHtml = ""; if(this.dataModel.styles) { for(let styleName in this.dataModel.styles) { styleHtml += " "+styleName+":"+this.dataModel.styles[styleName]+";"; } } if (this.dataModel.style && !((this.dataModel.style.indexOf("{") >= 0 && this.dataModel.style.indexOf("}") > 0) || (this.dataModel.style.indexOf("#[") >= 0 && this.dataModel.style.indexOf("]") > 0))) { styleHtml += this.dataModel.style; } if(this.getCustomStyleHtml) styleHtml += this.getCustomStyleHtml(); if(this._tfp.isDesigning) { styleHtml += "user-select:none;"; //设计时,如果容器组件没有设置边框,则为其添加一个轮廓线,以便查看 //不能直接设置border样式,因为会造成面板组件的内容宽度和高度与实际不一致 //导致设计时可能会出现滚动条,而实际运行时没有 if((this.isContainer || this.dataModel.components) && styleHtml.indexOf("border:")<0 && styleHtml.indexOf("border-width:")<0) styleHtml += "outline:#cccccc dashed 1px;"; } //如果是在后台编译时获得样式信息,则将组件样式抽取到页面头部style标签中,以便统一查看 if(isGetHead) { // } else if(this._tfp.isDesigning || retainStyleAttr) { styleHtml = " style=\""+styleHtml+" \""; } else { styleHtml = ""; } return styleHtml; } getComponentsHtml(getComponentsHtml, indent, retainStyleAttr) { let html = ""; if(!indent) indent = ""; for(var i=0;i<this.dataModel.components.length;i++) { let cdm = this.dataModel.components[i]; let Render = this._tfp.renders[cdm.type]; if(!Render) continue; let render = new Render(this._tfp, cdm, this.level+1); html += render.getHtml(getComponentsHtml, indent, retainStyleAttr); } return html; } getHtml(tagName, getComponentsHtml, parentIndent, retainStyleAttr) { if(!tagName) return ""; let indent = this.getHtmlIndent(); //有些容器组件由多级html元素构成,他们子组件的代码缩进 //需要根据父组件的容器元素的代码缩进进行相应的增加 if(parentIndent) { indent = parentIndent+"\t"; this.indent = indent; } let cptHtml = indent+"<"+tagName+" id=\""+this.dataModel.id + "\" class=\""; if (this._tfp.curPage.dataModel.client != "mini") { cptHtml += "tfp-" + this.dataModel.type.toLowerCase().replace("_", "-"); if (this.getSpecialClass) cptHtml += this.getSpecialClass(); } else { cptHtml += "w-" + this.dataModel.id + " wx-" + this.dataModel.type.toLowerCase().replace("_", "-"); } if (this.dataModel.class && !((this.dataModel.class.indexOf("{") >= 0 && this.dataModel.class.indexOf("}") > 0) || (this.dataModel.class.indexOf("#[") >= 0 && this.dataModel.class.indexOf("]") > 0))) { cptHtml += " " + this.dataModel.class; } cptHtml += "\""; cptHtml += this.getAttrHtml(retainStyleAttr)+this.getStyleHtml(false, retainStyleAttr); if(this.getBodyHtml) { cptHtml += ">"; cptHtml += this.getBodyHtml(getComponentsHtml, retainStyleAttr); cptHtml += "</"+tagName+">\r\n"; } else if(this.isContainer || this.dataModel.components) { cptHtml += ">\r\n"; if(getComponentsHtml && this.dataModel.components) { cptHtml += this.getComponentsHtml(getComponentsHtml, indent, retainStyleAttr); } cptHtml += indent+"</"+tagName+">\r\n"; } else { cptHtml += "/>\r\n"; } return cptHtml; } getComponentsWX(getComponentsHtml, indent, retainStyleAttr, otherOptions) { let wx = { "wxjson": "", "wxjs": "", "wxml": "", "wxss": "" } if (!indent) indent = ""; if (this.dataModel.components) { for (var i = 0; i < this.dataModel.components.length; i++) { let cdm = this.dataModel.components[i]; let Render = this._tfp.renders[cdm.type]; if (!Render) continue; let render = new Render(this._tfp, cdm, this.level + 1); var wx0 = render.getWX(getComponentsHtml, indent, retainStyleAttr, otherOptions); wx.wxjson += wx0.wxjson; wx.wxjs += wx0.wxjs; wx.wxml += wx0.wxml; wx.wxss += wx0.wxss; } } return wx; } getWX(tagName, getComponentsHtml, parentIndent, retainStyleAttr, otherOptions) { if (!tagName) return ""; let indent = this.getHtmlIndent(); //有些容器组件由多级html元素构成,他们子组件的代码缩进 //需要根据父组件的容器元素的代码缩进进行相应的增加 if (parentIndent) { indent = parentIndent + "\t"; this.indent = indent; } var cpt_wx = { "wxjson": "", "wxjs": "", "wxml": "", "wxss": "" } cpt_wx.wxml += indent + "<" + tagName + ""; if (otherOptions && otherOptions.gridContainer) cpt_wx.wxml += " id=\"" + this.dataModel.id + "_{{index}}\""; else cpt_wx.wxml += " id=\"" + this.dataModel.id + "\""; cpt_wx.wxml += " class=\""; cpt_wx.wxml += "w-" + this.dataModel.id + " "; if (this._tfp.curPage.dataModel.client != "mini") { cpt_wx.wxml += "tfp-" + this.dataModel.type.toLowerCase().replace("_", "-"); if (this.getSpecialClass) cpt_wx.wxml += this.getSpecialClass(); } else { cpt_wx.wxml += "wx-" + this.dataModel.type.toLowerCase().replace("_", "-"); } if (this.dataModel.class && !((this.dataModel.class.indexOf("{") >= 0 && this.dataModel.class.indexOf("}") > 0) || (this.dataModel.class.indexOf("#[") >= 0 && this.dataModel.class.indexOf("]") > 0))) { cpt_wx.wxml += " " + this.dataModel.class; } cpt_wx.wxml += "\""; cpt_wx.wxml += this.getAttrHtml(retainStyleAttr, otherOptions) + this.getStyleHtml(false, retainStyleAttr, otherOptions); if (this.getBodyWX) { cpt_wx.wxml += ">"; var body_wx = this.getBodyWX(getComponentsHtml, retainStyleAttr, otherOptions); cpt_wx.wxml += body_wx.wxml; cpt_wx.wxml += "</" + tagName + ">\r\n"; cpt_wx.wxjs += body_wx.wxjs; } else if (this.isContainer || this.dataModel.components) { cpt_wx.wxml += ">\r\n"; if (getComponentsHtml && this.dataModel.components) { var coms_wx = this.getComponentsWX(getComponentsHtml, indent, retainStyleAttr, otherOptions); cpt_wx.wxml += coms_wx.wxml; cpt_wx.wxjs += coms_wx.wxjs; } cpt_wx.wxml += indent; cpt_wx.wxml += "</" + tagName + ">\r\n"; } else { cpt_wx.wxml += "/>\r\n"; } return cpt_wx; } }