组态渲染元素中通过自定义的importCssJs动态加载js并且直接使用定义的类、函数,在编辑、运行模式下有区别,与编辑器等其他全局js变量冲突

1. js文件(leaflet.js内容末尾追加以下代码)中定义类和函数,用于被调用测试

JavaScript
ht.ui.TestClass = function() {
    console.log('here is ht.ui.TestClass');
}
ht.Default.def('ht.ui.TestClass', ht.ui.DropDownTemplate, {
    initDropDownView: function(master, datas, value) {
        var self = this,
            htmlView = new ht.ui.HtmlView(),
            mapDiv = self._mapDiv = document.createElement("div"),
            map = self._map = L.map(mapDiv, {
                zoomAnimation: false,
                trackResize: false
            }).setView([39.9123, 116.3913], 15);
        mapDiv.style.width = '100%';
        mapDiv.style.height = '100%';
        // mapDiv.style.boxShadow = master.getBoxShadow();
        L.tileLayer('http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}', {
            attribution: 'www.aiotos.net',
            maxZoom: 18,
            minZoom: 3
        }).addTo(map);
        map.on('click', function(e) {
            var latlng = e.latlng;
            self._latlng = latlng.lat + "," + latlng.lng;
            self.stop();
        });
        htmlView.setContent(mapDiv);
        htmlView.setPreferredSize(400, 200);
        return htmlView;
    },
    getDropDownValue: function() {
        return this._latlng;
    },
    afterOpen: function(v) {
        var self = this,
            map = self._map;
        self.getDropDownView().validate();
        self._map.invalidateSize();
        if (v) {
            self._latlng = v;
            var latlng = v.split(",");
            map.setView([latlng[0], latlng[1]], 15);
            self._marker = new L.marker([latlng[0], latlng[1]]);
            self._marker.addTo(map).bindPopup('Here!').openPopup();
        }
    }
});

2. 编辑模式运行的.html启动页面中添加动态加载:

JavaScript
importCssJs.js('custom/libs/leaflet/leaflet/leaflet.js', true, () => {
    mytest()    //测试js文件中追加的自定义函数
    console.log(new ht.ui.TestClass()); //测试js文件中追加的自定义类
    console.log(L);   //测试js本就是leaflet.js,有全局变量L,类似jquery的$
});

 

运行时(并未执行到渲染元素的代码)能正常访问到自定义函数、自定义类和该js类的对象:

 3. 仅在渲染元素中动态加载添加2中的代码:

 编辑状态下运行,不论是刷新页面还是只在编辑器中刷新加载图纸(已移除html中加入的测试代码防止干扰)结果能正常访问到自定义函数、自定义类,但是对该js的leaflet内置的全局对象L,提示未定义无法访问!

 4. 在3的基础上其他都不动,只是图纸预览运行,并非编辑器状态:

 结果跟2一样,能正常访问到自定义函数、自定义类和该js类的对象!

问题

以及揪出问题在编辑状态下编辑器动态加载leaflet.js,在加载完毕后调用其定义的变量L,竟然发现是undefined!!渲染元素代码任何不动,直接运行模式一切正常!

分析

查看leaflet.js代码(不需看源码,看目前正在加载的编译后的执行js即可)!

js中(function(){}()),(function(){})(),$(function(){});之间的区别;js闭包库

多处打印,对比编辑状态刷新加载图纸和运行状态页面刷新,发现问题出在function(t,i)函数体内的那一串条件判断上,一层层的?:表达式,对比编辑状态和运行状态,哪个条件判断不一致。

从左到右依次判断,发现问题出现在typeof define上!编辑状态有此定义,但是运行状态没有,且编辑状态下的定义在vs/loader.js中:

 

这就好理解,为什么编辑状态下和运行状态下不一样,因为全局命名定义发生了污染!!!

解决方案,渲染元素中加一句代码即可

JavaScript
if(!runningMode()) define = null;

完整的渲染元素代码:

JavaScript
if (!cache.obj) {
    function init() {
        function updateMarker(coordString){
            if(coordString && coordString.split(',') && coordString.split(',').length >= 2){
                cache.inputControl && cache.inputControl.ca('value',coordString) && cache.inputControl.iv()
                if(cache.marker) cache.map.removeLayer(cache.marker);
                cache.marker = L.marker(coordString.split(','));
                cache.marker.addTo(cache.map);
            }
        }

        /*这句极为重要,编辑状态下define在vs/loader.js中有定义造成在leaflet.js中命名冲突,但是运行状态下不存在,所以需要渲染元素中设置define为null即可!*/
        if(!runningMode()) define = null;
        
        let obj = cache.obj = document.createElement('div');
        importCssJs.css('custom/libs/leaflet/leaflet/leaflet.css');
        importCssJs.loadArr('js',[//importCssJs对于逐个.js()加载,以及.loadArr()传入数组加载,对于script之间保持同步一个个顺次加载而不是并行加载!此外.loadArr()的回调函数参数,就是让列表中最后一个js加载完毕来回调!
            'custom/libs/leaflet/leaflet/leaflet.js',
            'custom/libs/leaflet/leaflet-plugins/leaflet-tilelayer-colorizr.js'
        ],true,()=>{/*第二个参数这里一定要为true或者false,效果有区别:传入true时在渲染元素重入(尤其是编辑状态重新加载图纸)时,新创建的div dom元素,能经过对应新加载对应的js去操作处理,
        每次重新加载图纸都会提示报错Can only have one anonymous define call per script file,但是运行正常;传入false时,不会重新加载js,利用此前浏览器缓存的对象,在回调函数中同样会调用
        到L.map传入div dom元素的对象,虽然不报错,但是效果显示不正常,地图尺寸区域不会铺满div!*/
            if(!cache.map){
                cache.inputControl = d(data.dm(),data.ca('inputControl'));

                //leaflet实例化
                let map = cache.map = L.map(obj, {
                    center: data.ca('coord').split(','),
                    renderer: L.svg(),
                    zoom: data.ca('zoom'),
                    zoomControl: false, // + -号放大缩小
                    attributionControl: false // 右下角leaflet.js图标
                });

                //地图瓦片地图图层地址
                /*L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                    attribution:'© OpenStreetMap contributors'    //添加可选参数
                }).addTo(map)*/
                //关联地图并且背景染色样式(L.tileLayer.colorizr是重写后的)
                let titleLayer = cache.titleLayer = L.tileLayer.colorizr(data.ca('mapurl'), {
                    maxZoom: 18,
                    minZoom: 3,
                    // /*这个方法用来调整所有的图片上的rgb值,pixel是图片原有的rgb值*/
                    // colorize: function(pixel) {
                    //     pixel.r += 13;
                    //     pixel.g += 17;
                    //     pixel.b += 25;
                    //     return pixel;
                    // }
                });
                titleLayer.addTo(map);

                updateMarker(data.ca('coord'));

                //标定点鼠标事件点击弹出显示内容
                function onMapClick(e) {
                    data.ca('coord', e.latlng.lat + ',' + e.latlng.lng);
                    
                    // L.marker(data.ca('coord').split(',')).addTo(map);
                    // L.popup().setLatLng(e.latlng)
                    //     .setContent("You clicked the map at " + e.latlng.toString())
                    //     .openOn(map);
                }
                map.on('click', onMapClick);   
            }
        });
        
        data.dm().md(e => {
            if(e.data == data){
                // //event格式:
                // {
                //     property: 'name',//发生变化的属性
                //     oldValue: 'oldValue',//旧值
                //     newValue: 'newValue',''新值
                //     data: data//发生变化的data
                // }
                switch(e.property){
                    case 'a:zoom':
                        cache.map && cache.map.setZoom(data.ca('zoom'));
                        break;
                    case 'a:coord':
                        let coordtmp = e.newValue;
                        coordtmp && cache.map.flyTo(coordtmp.split(','));

                        updateMarker(coordtmp);
                        break;
                    case 'a:mapurl':
                        cache.titleLayer.setUrl(data.ca('mapurl'));
                        break;
                }
            }else if(cache.inputControl && e.data == cache.inputControl){
                switch(e.property){
                    case 'a:value':
                        data.ca('coord',e.newValue);
                        break;
                }
            }
        })

        return obj;
    }

    var obj = cache.obj = init()
    
    obj.layoutHTML = function () {
        gv.layoutHTML(data, obj, runningMode());
    }
}

return cache.obj;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IOTOS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值