簡體   English   中英

如何使用RequireJS分解大型Javascript文件

[英]How to Break up large Javascript file with RequireJS

我是Java語言的新手,因此需要JS-我目前正在使用Openlayers 3示例進行自我教學,其中,我剛剛附加了一個大型JS文件。 看到這種情況變得非常不規則時,我閱讀了RequireJS並認為我應該養成從一開始就做事的習慣。 “這是我遇到問題的地方”。

[不是我想這很重要,但是我使用的是Asp.net MVC]基本上,我希望將文件分解為較小的相關模塊,例如

  • Map [由所有模塊使用並啟動基礎層地圖]
  • 繪制[處理點/多邊形等,並作為另一層添加到地圖中]
  • 地理位置[包含用於繪制的地理位置功能]
  • 等等等

...提供了一次激活所有層的靈活性,或者通過易於管理的JS代碼選擇了少數幾個層。

我曾嘗試過將這些代碼分解為單獨的JS文件([map / draw / Geolocation]),但都以失敗告終,因為我覺得我沒有掌握requireJS方法( 以免進一步混淆讀者和我自己,我我忽略了嘗試 )。

這是有效的基本代碼:

require.config({
    baseUrl: "/Scripts",
    paths: {
        //jquery: "/lib/jquery-1.11.1.min",
        ol: [
            "http://openlayers.org/en/v3.8.1/build/ol",
            "/lib/ol"
        ],
        domReady: "/lib/domReady"
    },
    //map: { main: { test: "/Modules/Test/scripts/test" } },
    //The shim section is to tell RequireJS about any dependencies your files have before they can be used.  
    //Here, we are saying if we call “ol” to load that module, we have to load “jquery” first.
    //shim: {
        //ol: ["jquery"]
    //},
    //packages: [
    //    {
    //name: 'test',
    //location: 'http://...
    //main: 'main'                
    //}]
});

我想分手的文件:

define(["ol"], function (ol) {

    $(document).ready(function () {

        //****************
        //------MAP-------

        //Setup Map Base
        // creating the view
        var view = new ol.View({
            center: ol.proj.fromLonLat([5.8713, 45.6452]),
            zoom: 19
        });

        // creating the map
        var map = new ol.Map({
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                })
            ],
            target: "map",
            controls: ol.control.defaults({
                attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
                    collapsible: false
                })
            }),
            view: view
        });

        //****************
        //-----DRAW------

        var features = new ol.Collection();
        var featureOverlay = new ol.layer.Vector({
            source: new ol.source.Vector({ features: features }),
            style: new ol.style.Style({
                fill: new ol.style.Fill({
                    color: "rgba(255, 255, 255, 0.2)"
                }),
                stroke: new ol.style.Stroke({
                    color: "#ffcc33",
                    width: 2
                }),
                image: new ol.style.Circle({
                    radius: 7,
                    fill: new ol.style.Fill({
                        color: "#ffcc33"
                    })
                })
            })
        });
        featureOverlay.setMap(map);

        var modify = new ol.interaction.Modify({
            features: features,
            // the SHIFT key must be pressed to delete vertices, so
            // that new vertices can be drawn at the same position
            // of existing vertices
            deleteCondition: function (event) {
                return ol.events.condition.shiftKeyOnly(event) &&
                    ol.events.condition.singleClick(event);
            }
        });
        map.addInteraction(modify);

        var draw; // global so we can remove it later
        function addInteraction() {
            draw = new ol.interaction.Draw({
                features: features,
                type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
            });
            map.addInteraction(draw);
        }

        var typeSelect = document.getElementById("type");


        /**
         * Let user change the geometry type.
         * @param {Event} e Change event.
         */
        typeSelect.onchange = function (e) {
            map.removeInteraction(draw);
            addInteraction();
        };

        addInteraction();

        //****************
        //---GEOLOCATION---//

        // Common app code run on every page can go here
        // Geolocation marker
        var markerEl = document.getElementById("geolocation_marker");
        var marker = new ol.Overlay({
            positioning: "center-center",
            element: markerEl,
            stopEvent: false
        });
        map.addOverlay(marker);

        // LineString to store the different geolocation positions. This LineString
        // is time aware.
        // The Z dimension is actually used to store the rotation (heading).
        var positions = new ol.geom.LineString([],
            /** @type {ol.geom.GeometryLayout} */ ("XYZM"));

        // Geolocation Control
        var geolocation = new ol.Geolocation( /** @type {olx.GeolocationOptions} */({
            projection: view.getProjection(),
            trackingOptions: {
                maximumAge: 10000,
                enableHighAccuracy: true,
                timeout: 600000
            }
        }));

        var deltaMean = 500; // the geolocation sampling period mean in ms

        // Listen to position changes
        geolocation.on("change", function (evt) {
            var position = geolocation.getPosition();
            var accuracy = geolocation.getAccuracy();
            var heading = geolocation.getHeading() || 0;
            var speed = geolocation.getSpeed() || 0;
            var m = Date.now();

            addPosition(position, heading, m, speed);

            var coords = positions.getCoordinates();
            var len = coords.length;
            if (len >= 2) {
                deltaMean = (coords[len - 1][3] - coords[0][3]) / (len - 1);
            }

            var html = [
                "Position: " + position[0].toFixed(2) + ", " + position[1].toFixed(2),
                "Accuracy: " + accuracy,
                "Heading: " + Math.round(radToDeg(heading)) + "°",
                "Speed: " + (speed * 3.6).toFixed(1) + " km/h",
                "Delta: " + Math.round(deltaMean) + "ms"
            ].join("<br />");
            document.getElementById("info").innerHTML = html;
        });

        geolocation.on("error", function () {
            alert("geolocation error");
            // FIXME we should remove the coordinates in positions
        });

        // convert radians to degrees
        function radToDeg(rad) {
            return rad * 360 / (Math.PI * 2);
        }

        // convert degrees to radians
        function degToRad(deg) {
            return deg * Math.PI * 2 / 360;
        }

        // modulo for negative values
        function mod(n) {
            return ((n % (2 * Math.PI)) + (2 * Math.PI)) % (2 * Math.PI);
        }

        function addPosition(position, heading, m, speed) {
            var x = position[0];
            var y = position[1];
            var fCoords = positions.getCoordinates();
            var previous = fCoords[fCoords.length - 1];
            var prevHeading = previous && previous[2];
            if (prevHeading) {
                var headingDiff = heading - mod(prevHeading);

                // force the rotation change to be less than 180°
                if (Math.abs(headingDiff) > Math.PI) {
                    var sign = (headingDiff >= 0) ? 1 : -1;
                    headingDiff = -sign * (2 * Math.PI - Math.abs(headingDiff));
                }
                heading = prevHeading + headingDiff;
            }
            positions.appendCoordinate([x, y, heading, m]);

            // only keep the 20 last coordinates
            positions.setCoordinates(positions.getCoordinates().slice(-20));

            // FIXME use speed instead
            if (heading && speed) {
                markerEl.src = "/OrchardLocal/Media/Default/Map/geolocation_marker.png"; //"data/geolocation_marker_heading.png";F:\DeleteMeThree\_Orchard-19x\src\Orchard.Web\Modules\Cns.OL\Contents/Images/geolocation_marker.png
            } else {
                //alert(markerEl.src); PETE: Not sure if this is std OL practice, but this is achieved by already having an element
                //called "geolocation_marker" in the dom as an img, which this uses? Strange to me
                markerEl.src = "/OrchardLocal/Media/Default/Map/geolocation_marker.png"; //I added img via media module - ridiculous?!
            }
        }

        var previousM = 0;
        // change center and rotation before render
        map.beforeRender(function (map, frameState) {
            if (frameState !== null) {
                // use sampling period to get a smooth transition
                var m = frameState.time - deltaMean * 1.5;
                m = Math.max(m, previousM);
                previousM = m;
                // interpolate position along positions LineString
                var c = positions.getCoordinateAtM(m, true);
                var view = frameState.viewState;
                if (c) {
                    view.center = getCenterWithHeading(c, -c[2], view.resolution);
                    view.rotation = -c[2];
                    marker.setPosition(c);
                }
            }
            return true; // Force animation to continue
        });

        // recenters the view by putting the given coordinates at 3/4 from the top or
        // the screen
        function getCenterWithHeading(position, rotation, resolution) {
            var size = map.getSize();
            var height = size[1];

            return [
                position[0] - Math.sin(rotation) * height * resolution * 1 / 4,
                position[1] + Math.cos(rotation) * height * resolution * 1 / 4
            ];
        }

        // postcompose callback
        function render() {
            map.render();
        }

        //EMP
        //$("#geolocate").click(function () {
        //    alert("JQuery Running!");
        //});

        // geolocate device
        var geolocateBtn = document.getElementById("geolocate");
        geolocateBtn.addEventListener("click", function () {
            geolocation.setTracking(true); // Start position tracking

            map.on("postcompose", render);
            map.render();

            disableButtons();
        }, false);
    });
})

考慮到將來我將有更多模塊要附加,使用RequireJS分解此代碼的最佳方法是什么,以提高效率和編碼功能/維護。

非常感謝您的指導/想法,WL歡呼

每個require模塊( defined using define )都應該返回一個function/object 有問題的拆分不會,而是僅拆分代碼。 考慮一些假設的模塊存儲區,並將每段代碼(或函數)放入模塊中。 然后將代碼分組到require js模塊中並返回該模塊的接口。

讓我嘗試用一​​個例子進一步解釋。

main.js

$(document).ready(function(){
  $("#heyINeedMap").click(function(){
    require(['map'],function(Map){
      Map.render($target);
    });  
  });
});

要么

$(document).ready(function(){
  require(['map','geolocation'],function(Map,Geolocation){
      window.App.start = true;
      window.App.map = Map;              //won't suggest, but you can do.
      window.App.geolocation = Geolocation; 

      //do something.
      $("#lastCoords").click(function(){
        var coords = App.geolocation.getLastSavedCoords();
        if(!!coords){
          coords = App.geolocation.fetchCurrentCoords();
        }
        alert(coords);
      });
  });
});

map.js

define(['jquery'],function($){
  var privateVariableAvailableToAllMapInstances = 'something';
  var mapType = 'scatter';
  return function(){
    render: function(el){
      //rendering logic goes here
    },
    doSomethingElse: function(){
      privateVariable = 'some new value';
      //other logic goes here
    },
    changeMapType: function(newType){
      mapType = newType;
      //...
    }
  }
});

geolocation.js

//Just assuming that it needs jquery & another module called navigation to work.
define(['jquery','navigation'], function($,Gnav){
  return {
    var coordinates = Gnav.lastSavedCoords;
    fetchCurrentCoords: function(){
      //coordinates = [79.12213, 172.12342];  //fetch from API/something
      return coordinates;
    },
    getLastSavedCoords: function(){
      return coordinates;
    }
  }
});

希望這對如何進行提供了一個思路。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM