布局器嵌入系统后 希望能更深入的定制化业务交互,就需要了解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
xxxxxxxxxx
IframeUi.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)
xxxxxxxxxx
1 callback.js
MagicalCallback.prototype.after_start = function (param) {
}
2 api.js
getRightPanelItemListFromConstant();
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中即可
xxxxxxxxxx
1 callback.js
MagicalCallback.prototype.right_menu_list = function(param)
2 api.js
nodesToHtml(); //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(); 记得最后必须调用这个方法 否则不生效 动态的刷新一下
}
xxxxxxxxxx
iframe-ui.js中defaultJavascript决定了当前html对应的脚本逻辑,我们将其细化,按照需求控制某一部分的代码,因此我们开发出了大量操作iframe-ui.js中defaultJavascript变量的api
xxxxxxxxxx
1 callback.js
MagicalCallback.prototype.after_change_attr_callback = function(obj)
2 iframe-ui ->api
setVueMethod(); //控制vueMethod的组成部分
xxxxxxxxxx
constant.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
未完待续 可以咨询我们 获取一些案例场景