布局器嵌入系统后 希望能更深入的定制化业务交互,就需要了解API(主动调用)和回调(被动通知)
xxxxxxxxxx在js方法中任意地方都可以 var api = new MagicalApi();即可使用api.getHtml();等各种方法可以主动调用api的所有接口方法您也可以直接使用MAGICAL_CODER_API来调用api.js里的各个方法,MAGICAL_CODER_API是我们内置的布局器的全局变量
xxxxxxxxxx可参考 magicaldrag/assets/drag/js/user/api.js
请访问 http://lowcode.magicalcoder.com/magicaldrag/assets/drag/js/user/api.js 查看 因为是持续更新的
xxxxxxxxxx布局器会在处理的环节 触发callback的方法,在方法里加入您的逻辑来干预布局器行为即可由于布局器会持续不断升级,但是我们的api 回调等会向前兼容,如果您直接把业务代码写在callback.js更新代码会覆盖callback.js,要么就需要自己合并,耗费时间。
xxxxxxxxxx正确的做法是:1 重写callback.js提供的方法 新建一个您自己的my-callback.js 在里面重写callback.js提供的方法例如我们在user\demo\my-callback-xxx.js写的各种示例比如 保存按钮点击MagicalCallback.prototype.save_html = function (param) {//加入你自己的逻辑:保存到数据库等等}//布局器加载完成 会自动调用此方法MagicalCallback.prototype.after_start = function (param) {//您可以根据浏览器的入参,来初始化获取数据库保存的数据,可以使用param.api.insertHtml(...)来初始化布局器}2 在index-xxx.html的callback.js后紧跟着引入此文件 这样就把callback.js的部分方法重写了 记得参数和名称一定要一致例如:<script type="text/javascript" src="assets/drag/js/user/callback.js"></script><script type="text/javascript" src="assets/drag/js/user/my-callback.js"></script>
xxxxxxxxxx原理:浏览器在加载完callabck.js后 加载到save_html那么当我们让浏览器继续加载我们的my-callback.js的MagicalCallback.prototype.save_html = function (param) {//加入你自己的逻辑:保存到数据库等等}则callback.js中的MagicalCallback.prototype.save_html = function (param) {}就失效了,转而让my-callback.js中的save_html 生效
xxxxxxxxxx代码目录:magicaldrag/assets/drag/js/user/calllback.js
xxxxxxxxxx请访问 http://lowcode.magicalcoder.com/magicaldrag/assets/drag/js/user/callback.js 查看 因为是持续更新的
xxxxxxxxxx在js方法中任意地方都可以 var api = new MagicalApi(); 您也可以直接使用MAGICAL_CODER_API来调用api即可使用api.getIframeUi().api();等各种方法可以主动调用api的所有接口方法,注意当前仅有vue的ui支持此类api,因为jquery的比较简单,都是根据用户在标签上配置的各类属性,在预置好脚本中提前这些属性从而达到某种目的
xxxxxxxxxx可参考 magicaldrag/assets/drag/js/user/ui/xxx/xxx/iframe-ui.js
xxxxxxxxxxIframeUi.prototype.api = function(){var _t = this;var api = {//设置vueData数据值setVueData:function(fieldName,filedValue){_t.vueData[fieldName]=filedValue;},removeVueData:function(fieldName){delete _t.vueData[fieldName];},getVueData:function(fieldName){return _t.vueData[fieldName];},//设置vueMethod数据值setVueMethod:function(functionName,functionContent){_t.vueMethod[functionName]=functionContent;},removeVueMethod:function(functionName){delete _t.vueMethod[functionName];},getVueMethod:function(functionName){return _t.vueMethod[functionName];},//设置vueMounted数据值/*** @param mountedFunctionContent 'function(){...}'*/setVueMounted:function(mountedFunctionContent){_t.vueMounted = mountedFunctionContent;},resetVueMounted:function(){_t.vueMounted='function(){}';},getVueMounted:function(){return _t.vueMounted;},resetAll:function(){_t.vueData = {};_t.vueMethod = {"focus":"function (e) {try {_t.fastKey.focusElem(e);}catch(e) {}}"};_t.vueMounted = 'function(){}';}}return api;}
xxxxxxxxxx下面就让我们来看一下各类场景如何使用callback和api实现各种需求
xxxxxxxxxx首先我们知道 属性都在constant.js的this.rightPanel中控制的,也就是说 只要我们在布局器加载完毕后(1),使用ajax向后端请求数据,然后去更新constant.js中this.rightPanel的结构就能解决问题(2)
xxxxxxxxxx1 callback.jsMagicalCallback.prototype.after_start = function (param) {}2 api.jsgetRightPanelItemListFromConstant();
xxxxxxxxxx当页面初始化之后,我们从数据库获取数据后,一次性更改当前布局器页面 某一个属性的下拉值假设我们有属性配置:"el-input":[{type:this.type.SELEC,attrName:'type',options:[{"text":"输入框","textarea":"文本框"}],"myId":"el-input-type",.....},]我们来改变options的下拉值MagicalCallback.prototype.after_start = function (param) {var api = param.api;$.getJSON("后端地址",{},function(data){//根据此方法获取el-input的这条满足条件的配置var list = api.getRightPanelItemListFromConstant({key:"el-input",query:{attrName:"type"}});console.log(list);for(var i=0;i<list.length;i++){list[i].options=data.options;}})}
xxxxxxxxxx当点击中间区域某个控件,我们从数据库获取数据后,及时更改当前布局器页面 某一个属性的下拉值假设我们有属性配置:"el-input":[{type:this.type.SELEC,attrName:'type',options:[{"text":"输入框","textarea":"文本框"}],"myId":"el-input-type",.....},]我们来改变options的下拉值MagicalCallback.prototype.pre_build_attrs = function (param) {var focusNode=param.focusNode,notifyContinueCallback=param.notifyContinueCallback;if(focusNode.magicalCoder.identifier=='el-input'){$.getJSON("后端地址",{}.function(data){//根据此方法获取el-input的这条满足条件的配置var list = api.getRightPanelItemListFromConstant({key:"el-input",query:{attrName:"type"}});console.log(list);for(var i=0;i<list.length;i++){list[i].options=data.options;}notifyContinueCallback();})}}
xxxxxxxxxx当我们右键菜单时,会回调callback.js中的right_menu_list回调,并且传入当前聚焦节点,再把当前结构转成html调用ajax保存给后台 下次记得初始化后 再加载到constant.js张的this.components中即可
xxxxxxxxxx1 callback.jsMagicalCallback.prototype.right_menu_list = function(param)2 api.jsnodesToHtml(); //json节点转成html
xxxxxxxxxx我们需要callback.js中right_menu_list/*** @version 2.2.6* focusNodes:[] 当前聚焦的json数据 您可以得知当前哪些结构被点击聚焦了* 右键菜单定制* actionName: 动作事件名称 title:中文标题 handler 处理函数* @return [{actionName:"saveTo",title:"另存为",handler:function(focusNodes){//ajax保存吧}}];* 如果您希望另存为组件 那么就要把focuseNode转成html存储 var html = api.nodesToHtml(focusNodes);*/MagicalCallback.prototype.right_menu_list = function(param){var focusNodes = param.focusNodes;var api = new MagicalApi();return [{actionName:"saveTo",title:"另存为我的组件",handler:function(focusNodes){var html = api.nodesToHtml(focusNodes);//注意布局器外部使用layui框架打造,您可以使用layui的所有组件layer.open({content: '<input placeholder="请输入组件名称">',yes: function(index, layero){//ajax把html存一下数据库}});}}]}//下次加载布局器我们要把我们的自定义组件加载进来MagicalCallback.prototype.after_start = function (param) {var api = param.api;var constant = api.getConstant();var conponents = constant.getComponents();//下面流程就是ajax从后端拿出数据库 动态改变constant.js的内容 然后刷新一下即可 大家可以自己尝试实现一下 有问题联系我们//1 ajax 请求后端把上次用户存储的自定义组件html 名称都拿过来 巴拉巴拉 然后找到components变量 到constant.js里看看吧//2 找到指定位置 push进去即可//3 api.rebuildLeftComponents(); 记得最后必须调用这个方法 否则不生效 动态的刷新一下
}
xxxxxxxxxxiframe-ui.js中defaultJavascript决定了当前html对应的脚本逻辑,我们将其细化,按照需求控制某一部分的代码,因此我们开发出了大量操作iframe-ui.js中defaultJavascript变量的api
xxxxxxxxxx1 callback.jsMagicalCallback.prototype.after_change_attr_callback = function(obj)2 iframe-ui ->apisetVueMethod(); //控制vueMethod的组成部分
xxxxxxxxxxconstant.js"el-button":[{type:this.type.SELECT ,clearAttr:true ,oneLine:true ,change:this.change.ATTR ,title:'测试行为' ,attrName:'testMethod',options:[{"m1":"弹窗您好","m2":"弹窗MagicalCoder","m3":"加载后弹窗"}]}]callback.js :MagicalCallback.prototype.after_change_attr_callback = function (obj) {//test 下面是一个示例 当按钮右侧下拉变化 我们来动态修改它的脚本实现逻辑 达到动态控制方法的目的 而对使用软件的人来说 仅仅配置一个下拉属性if(obj.node.magicalCoder.identifier == 'el-button'){var api = new MagicalApi();if(obj.name=='testMethod'){//增加方法名obj.node.attributes['@click']=obj.value;var iframeUi = api.getIframeUi();//先删除上一次的方法iframeUi.api().removeVueMethod(obj.originValue);iframeUi.api().resetVueMounted();//给予当前期望的方法if(obj.value=='m1'){iframeUi.api().setVueMethod(obj.value,"function(){vueData.input='您好';alert('您好');}");}else if(obj.value=='m2'){iframeUi.api().setVueMethod(obj.value,"function(){vueData.input='您好';alert('magicalCoder');}");}else if(obj.value == 'm3'){iframeUi.api().setVueMethod(obj.value,"function(){vueData.input='m3';alert('m3');}");iframeUi.api().setVueMounted("function(){alert('加载成功')}");}//切记要刷新一下才能让脚本立即生效api.refreshWorkspace();}}//test
}
xxxxxxxxxx当我们把按钮属性切换时,再到脚本内查看 便能看到 脚本已经变化
xxxxxxxxxx未完待续 可以咨询我们 获取一些案例场景