成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

angularjs+requirejs實(shí)現(xiàn)按需加載的全面實(shí)踐

TerryCai / 1494人閱讀

摘要:想同時(shí)實(shí)現(xiàn)這些目標(biāo),就必須有一套按需加載的機(jī)制,頁(yè)面上展現(xiàn)的內(nèi)容和所有需要依賴的文件,都可以根據(jù)業(yè)務(wù)邏輯需要按需加載。最近都是基于做開發(fā),所以本文主要圍繞提供的各種機(jī)制,探索全面實(shí)現(xiàn)按需加載的套路。注意必須設(shè)置,否則變化以后,不截獲。

在進(jìn)行有一定規(guī)模的項(xiàng)目時(shí),通常希望實(shí)現(xiàn)以下目標(biāo):1、支持復(fù)雜的頁(yè)面邏輯(根據(jù)業(yè)務(wù)規(guī)則動(dòng)態(tài)展現(xiàn)內(nèi)容,例如:權(quán)限,數(shù)據(jù)狀態(tài)等);2、堅(jiān)持前后端分離的基本原則(不分離的時(shí)候,可以在后端用模版引擎直接生成好頁(yè)面);3、頁(yè)面加載時(shí)間短(業(yè)務(wù)邏輯復(fù)雜就需要引用第三方的庫(kù),但很可能加載的庫(kù)和用戶本次操作沒(méi)關(guān)系);4,還要代碼好維護(hù)(加入新的邏輯時(shí),影響的文件盡量少)。

想同時(shí)實(shí)現(xiàn)這些目標(biāo),就必須有一套按需加載的機(jī)制,頁(yè)面上展現(xiàn)的內(nèi)容和所有需要依賴的文件,都可以根據(jù)業(yè)務(wù)邏輯需要按需加載。最近都是基于angularjs做開發(fā),所以本文主要圍繞angularjs提供的各種機(jī)制,探索全面實(shí)現(xiàn)按需加載的套路。

一、一步一步實(shí)現(xiàn)

基本思路:1、先開發(fā)一個(gè)框架頁(yè)面,它可以完成一些基本的業(yè)務(wù)邏輯,并且支持?jǐn)U展的機(jī)制;2、業(yè)務(wù)邏輯變復(fù)雜,需要把部分邏輯拆分到子頁(yè)面中,子頁(yè)面按需加載;3、子頁(yè)面中的展現(xiàn)內(nèi)容也變了復(fù)雜,又需要進(jìn)行拆分,按需加載;4、子頁(yè)面的內(nèi)容復(fù)雜到依賴外部模塊,需要按需加載angular模塊。

1、框架頁(yè)

提到前端的按需加載,就會(huì)想到AMD( Asynchronous Module Definition),現(xiàn)在用requirejs的非常多,所以首先考慮引入requires。

index.html

注意:采用手動(dòng)啟動(dòng)angular的方式,因此html中沒(méi)有ng-app。

spa-loader.js

require.config({
    paths: {
        "domReady": "/static/js/domReady",
        "angular": "http://cdn.bootcss.com/angular.js/1.4.8/angular.min",
        "angular-route": "http://cdn.bootcss.com/angular.js/1.4.8/angular-route.min",
    },
    shim: {
        "angular": {
            exports: "angular"
        },
        "angular-route": {
            deps: ["angular"]
        },
    },
    deps: ["/test/lazyspa/spa.js"],
    urlArgs: "bust=" + (new Date()).getTime()
});

spa.js

define(["require", "angular", "angular-route"], function(require, angular) {
    var app = angular.module("app", ["ngRoute"]);
    require(["domReady!"], function(document) {
        angular.bootstrap(document, ["app"]); /*手工啟動(dòng)angular*/
        window.loading.finish();
    });
});
2、按需加載子頁(yè)面

angular的routeProvider+ng-view已經(jīng)提供完整的子頁(yè)面加載的方法,直接用。
注意必須設(shè)置html5Mode,否則url變化以后,routeProvider不截獲。

index.html


spa.js

app.config(["$locationProvider", "$routeProvider", function($locationProvider, $routeProvider) {
    /* 必須設(shè)置生效,否則下面的設(shè)置不生效 */
    $locationProvider.html5Mode(true);
    /* 根據(jù)url的變化加載內(nèi)容 */
    $routeProvider.when("/test/lazyspa/page1", {
        template: "
page1
", }).when("/test/lazyspa/page2", { template: "
page2
", }).otherwise({ template: "
main
", }); }]);
3、按需加載子頁(yè)面中的內(nèi)容

用routeProvider的前提是url要發(fā)生變化,但是有的時(shí)候只是子頁(yè)面中的局部要發(fā)生變化。如果這些變化主要是和綁定的數(shù)據(jù)相關(guān),不影響頁(yè)面布局,或者影響很小,那么通過(guò)ng-if一類的標(biāo)簽基本就解決了。但是有的時(shí)候要根據(jù)頁(yè)面狀態(tài),完全改變局部的內(nèi)容,例如:用戶登錄前和登錄后局部要發(fā)生的變化等,這就意味著局部的布局可能也挺復(fù)雜,需要作為獨(dú)立的單元來(lái)對(duì)待。

利用ng-include可以解決頁(yè)面局部?jī)?nèi)容加載的問(wèn)題。但是,我們可以再考慮更復(fù)雜一些的情況。這個(gè)頁(yè)面片段對(duì)應(yīng)的代碼是后端動(dòng)態(tài)生成的,而且不僅僅有html還有js,js中定義了代碼片段對(duì)應(yīng)的controller。這種情況下,不僅僅要考慮動(dòng)態(tài)加載html的問(wèn)題,還要考慮動(dòng)態(tài)定義controller的問(wèn)題。controller是通過(guò)angular的controllerProvider的register方法注冊(cè),因此需要獲得controllerProvider的實(shí)例。

spa.js

app.config(["$locationProvider", "$routeProvider", "$controllerProvider", function($locationProvider, $routeProvider, $controllerProvider) {
    app.providers = {
        $controllerProvider: $controllerProvider //注意這里?。?!
    };
    /* 必須設(shè)置生效,否則下面的設(shè)置不生效 */
    $locationProvider.html5Mode(true);
    /* 根據(jù)url的變化加載內(nèi)容 */
    $routeProvider.when("/test/lazyspa/page1", {
        /*!!!頁(yè)面中引入動(dòng)態(tài)內(nèi)容!!!*/
        template: "
page1
", controller: "ctrlPage1" }).when("/test/lazyspa/page2", { template: "
page2
", }).otherwise({ template: "
main
", }); app.controller("ctrlPage1", ["$scope", "$templateCache", function($scope, $templateCache) { /* 用這種方式,ng-include配合,根據(jù)業(yè)務(wù)邏輯動(dòng)態(tài)獲取頁(yè)面內(nèi)容 */ /* !!!動(dòng)態(tài)的定義controller!!! */ app.providers.$controllerProvider.register("ctrlPage1Dyna", ["$scope", function($scope) { $scope.openAlert = function() { alert("page1 alert"); }; }]); /* !!!動(dòng)態(tài)定義頁(yè)面的內(nèi)容!!! */ $templateCache.put("page1.html", "
"); }]); }]);
4、動(dòng)態(tài)加載模塊

采用上面子頁(yè)面片段的加載方式存在一個(gè)局限,就是各種邏輯(js)要加入到啟動(dòng)模塊中,這樣還是限制子頁(yè)面片段的獨(dú)立封裝。特別是,如果子頁(yè)面片段需要使用第三方模塊,且這個(gè)模塊在啟動(dòng)模塊中沒(méi)有事先加載時(shí),就沒(méi)有辦法了。所以,必須要能夠?qū)崿F(xiàn)模塊的動(dòng)態(tài)加載。實(shí)現(xiàn)模塊的動(dòng)態(tài)加載就是把a(bǔ)ngular啟動(dòng)過(guò)程中加載模塊的方式提取出來(lái),再處理一些特殊情況。

動(dòng)態(tài)加載模塊深入分析可以參考這篇文章:
http://www.tuicool.com/articles/jmuymiE

但是,實(shí)際跑起來(lái)發(fā)現(xiàn)文章中的代碼有問(wèn)題,就是“$injector”到底是什么?研究了angular的源代碼injector.js才大概搞明白是怎么回事。

一個(gè)應(yīng)用有兩個(gè)$injector,providerInjector和instanceInjector。invokeQueue和用providerInjector,runBlocks用instanceProvider。如果$injector用錯(cuò)了,就會(huì)找到需要的服務(wù)。

routeProvider中動(dòng)態(tài)加載模塊文件。

template: "
page2
", resolve: { load: ["$q", function($q) { var defer = $q.defer(); /* 動(dòng)態(tài)加載angular模塊 */ require(["/test/lazyspa/module1.js"], function(loader) { loader.onload && loader.onload(function() { defer.resolve(); }); }); return defer.promise; }] }

動(dòng)態(tài)加載angular模塊

angular._lazyLoadModule = function(moduleName) {
    var m = angular.module(moduleName);
    console.log("register module:" + moduleName);
    /* 應(yīng)用的injector,和config中的injector不是同一個(gè),是instanceInject,返回的是通過(guò)provider.$get創(chuàng)建的實(shí)例 */
    var $injector = angular.element(document).injector();
    /* 遞歸加載依賴的模塊 */
    angular.forEach(m.requires, function(r) {
        angular._lazyLoadModule(r);
    });
    /* 用provider的injector運(yùn)行模塊的controller,directive等等 */
    angular.forEach(m._invokeQueue, function(invokeArgs) {
        try {
            var provider = providers.$injector.get(invokeArgs[0]);
            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
        } catch (e) {
            console.error("load module invokeQueue failed:" + e.message, invokeArgs);
        }
    });
    /* 用provider的injector運(yùn)行模塊的config */
    angular.forEach(m._configBlocks, function(invokeArgs) {
        try {
            providers.$injector.invoke.apply(providers.$injector, invokeArgs[2]);
        } catch (e) {
            console.error("load module configBlocks failed:" + e.message, invokeArgs);
        }
    });
    /* 用應(yīng)用的injector運(yùn)行模塊的run */
    angular.forEach(m._runBlocks, function(fn) {
        $injector.invoke(fn);
    });
};

定義模塊
module1.js

define(["angular"], function(angular) {
    var onloads = [];
    var loadCss = function(url) {
        var link, head;
        link = document.createElement("link");
        link.href = url;
        link.rel = "stylesheet";
        head = document.querySelector("head");
        head.appendChild(link);
    };
    loadCss("http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css");
    /* !!! 動(dòng)態(tài)定義requirejs !!!*/
    require.config({
        paths: {
            "ui-bootstrap-tpls": "http://cdn.bootcss.com/angular-ui-bootstrap/1.1.2/ui-bootstrap-tpls.min"
        },
        shim: {
            "ui-bootstrap-tpls": {
                deps: ["angular"]
            }
        }
    });
    /*!!! 模塊中需要引用第三方的庫(kù),加載模塊依賴的模塊 !!!*/
    require(["ui-bootstrap-tpls"], function() {
        var m1 = angular.module("module1", ["ui.bootstrap"]);
        m1.config(["$controllerProvider", function($controllerProvider) {
            console.log("module1 - config begin");
        }]);
        m1.controller("ctrlModule1", ["$scope", "$uibModal", function($scope, $uibModal) {
            console.log("module1 - ctrl begin");
            /*!!! 打開angular ui的對(duì)話框 !!!*/
            var dlg = "";
            dlg += "";
            dlg += "";
            $scope.openDialog = function() {
                $uibModal.open({
                    template: dlg,
                    controller: ["$scope", "$uibModalInstance", function($scope, $mi) {
                        $scope.cancel = function() {
                            $mi.dismiss();
                        };
                        $scope.ok = function() {
                            $mi.close();
                        };
                    }],
                    backdrop: "static"
                });
            };
        }]);
        /* !!!動(dòng)態(tài)加載模塊!!! */
        angular._lazyLoadModule("module1");
        console.log("module1 loaded");
        angular.forEach(onloads, function(onload) {
            angular.isFunction(onload) && onload();
        });
    });
    return {
        onload: function(callback) {
            onloads.push(callback);
        }
    };
});
二、完整的代碼

index.html



    
        
        
        
        SPA
    
    
        
        

spa-loader.js

window.loading = {
    finish: function() {
        /* 保留個(gè)方法做一些加載完成后的處理,我實(shí)際的項(xiàng)目中會(huì)在這里結(jié)束加載動(dòng)畫 */
    },
    load: function() {
        require.config({
            paths: {
                "domReady": "/static/js/domReady",
                "angular": "http://cdn.bootcss.com/angular.js/1.4.8/angular.min",
                "angular-route": "http://cdn.bootcss.com/angular.js/1.4.8/angular-route.min",
            },
            shim: {
                "angular": {
                    exports: "angular"
                },
                "angular-route": {
                    deps: ["angular"]
                },
            },
            deps: ["/test/lazyspa/spa.js"],
            urlArgs: "bust=" + (new Date()).getTime()
        });
    }
};
window.loading.load();

spa.js

"use strict";
define(["require", "angular", "angular-route"], function(require, angular) {
    var app = angular.module("app", ["ngRoute"]);
    /* 延遲加載模塊 */
    angular._lazyLoadModule = function(moduleName) {
        var m = angular.module(moduleName);
        console.log("register module:" + moduleName);
        /* 應(yīng)用的injector,和config中的injector不是同一個(gè),是instanceInject,返回的是通過(guò)provider.$get創(chuàng)建的實(shí)例 */
        var $injector = angular.element(document).injector();
        /* 遞歸加載依賴的模塊 */
        angular.forEach(m.requires, function(r) {
            angular._lazyLoadModule(r);
        });
        /* 用provider的injector運(yùn)行模塊的controller,directive等等 */
        angular.forEach(m._invokeQueue, function(invokeArgs) {
            try {
                var provider = providers.$injector.get(invokeArgs[0]);
                provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
            } catch (e) {
                console.error("load module invokeQueue failed:" + e.message, invokeArgs);
            }
        });
        /* 用provider的injector運(yùn)行模塊的config */
        angular.forEach(m._configBlocks, function(invokeArgs) {
            try {
                providers.$injector.invoke.apply(providers.$injector, invokeArgs[2]);
            } catch (e) {
                console.error("load module configBlocks failed:" + e.message, invokeArgs);
            }
        });
        /* 用應(yīng)用的injector運(yùn)行模塊的run */
        angular.forEach(m._runBlocks, function(fn) {
            $injector.invoke(fn);
        });
    };
    app.config(["$injector", "$locationProvider", "$routeProvider", "$controllerProvider", function($injector, $locationProvider, $routeProvider, $controllerProvider) {
        /**
         * config中的injector和應(yīng)用的injector不是同一個(gè),是providerInjector,獲得的是provider,而不是通過(guò)provider創(chuàng)建的實(shí)例
         * 這個(gè)injector通過(guò)angular無(wú)法獲得,所以在執(zhí)行config的時(shí)候把它保存下來(lái)
        */
        app.providers = {
            $injector: $injector,
            $controllerProvider: $controllerProvider
        };
        /* 必須設(shè)置生效,否則下面的設(shè)置不生效 */
        $locationProvider.html5Mode(true);
        /* 根據(jù)url的變化加載內(nèi)容 */
        $routeProvider.when("/test/lazyspa/page1", {
            template: "
page1
", controller: "ctrlPage1" }).when("/test/lazyspa/page2", { template: "
page2
", resolve: { load: ["$q", function($q) { var defer = $q.defer(); /* 動(dòng)態(tài)加載angular模塊 */ require(["/test/lazyspa/module1.js"], function(loader) { loader.onload && loader.onload(function() { defer.resolve(); }); }); return defer.promise; }] } }).otherwise({ template: "
main
", }); }]); app.controller("ctrlMain", ["$scope", "$location", function($scope, $location) { console.log("main controller"); /* 根據(jù)業(yè)務(wù)邏輯自動(dòng)到缺省的視圖 */ $location.url("/test/lazyspa/page1"); }]); app.controller("ctrlPage1", ["$scope", "$templateCache", function($scope, $templateCache) { /* 用這種方式,ng-include配合,根據(jù)業(yè)務(wù)邏輯動(dòng)態(tài)獲取頁(yè)面內(nèi)容 */ /* 動(dòng)態(tài)的定義controller */ app.providers.$controllerProvider.register("ctrlPage1Dyna", ["$scope", function($scope) { $scope.openAlert = function() { alert("page1 alert"); }; }]); /* 動(dòng)態(tài)定義頁(yè)面內(nèi)容 */ $templateCache.put("page1.html", "
"); }]); require(["domReady!"], function(document) { angular.bootstrap(document, ["app"]); }); });

module1.js

"use strict";
define(["angular"], function(angular) {
    var onloads = [];
    var loadCss = function(url) {
        var link, head;
        link = document.createElement("link");
        link.href = url;
        link.rel = "stylesheet";
        head = document.querySelector("head");
        head.appendChild(link);
    };
    loadCss("http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css");
    require.config({
        paths: {
            "ui-bootstrap-tpls": "http://cdn.bootcss.com/angular-ui-bootstrap/1.1.2/ui-bootstrap-tpls.min"
        },
        shim: {
            "ui-bootstrap-tpls": {
                deps: ["angular"]
            }
        }
    });
    require(["ui-bootstrap-tpls"], function() {
        var m1 = angular.module("module1", ["ui.bootstrap"]);
        m1.config(["$controllerProvider", function($controllerProvider) {
            console.log("module1 - config begin");
        }]);
        m1.controller("ctrlModule1", ["$scope", "$uibModal", function($scope, $uibModal) {
            console.log("module1 - ctrl begin");
            var dlg = "";
            dlg += "";
            dlg += "";
            $scope.openDialog = function() {
                $uibModal.open({
                    template: dlg,
                    controller: ["$scope", "$uibModalInstance", function($scope, $mi) {
                        $scope.cancel = function() {
                            $mi.dismiss();
                        };
                        $scope.ok = function() {
                            $mi.close();
                        };
                    }],
                    backdrop: "static"
                });
            };
        }]);
        angular._lazyLoadModule("module1");
        console.log("module1 loaded");
        angular.forEach(onloads, function(onload) {
            angular.isFunction(onload) && onload();
        });
    });
    return {
        onload: function(callback) {
            onloads.push(callback);
        }
    };
});
寫后感

年初定下的目標(biāo)是堅(jiān)持每周寫一篇自己在開發(fā)過(guò)程碰到的問(wèn)題總結(jié),本以為是個(gè)簡(jiǎn)單的事情,寫起來(lái)才發(fā)現(xiàn)寫文章的時(shí)間比寫代碼的花的時(shí)間還要長(zhǎng)。因?yàn)閷懘a的時(shí)候只要功能實(shí)現(xiàn)了就行了,但是,寫文章的時(shí)候就一定要把代碼搞清楚才敢寫,實(shí)際上就是逼著自己要認(rèn)真研究源代碼,雖然壓力很大,但收獲更大。另一方面,發(fā)現(xiàn)找到一個(gè)好題目挺難的,只是簡(jiǎn)單的貼別人的代碼沒(méi)意思,可是自己想出來(lái)有價(jià)值,有意思的問(wèn)題挺難的。因此大家要是覺(jué)得有啥有意思,有價(jià)值前端問(wèn)題,分享一下吧,給我的年度寫作計(jì)劃幫幫忙

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78737.html

相關(guān)文章

  • avalon 單頁(yè)面程序 (種子工程)之一 用requirejs引入avalon

    摘要:現(xiàn)在微軟終于痛定思痛決定放棄了不支持的安全更新,對(duì)我們前端來(lái)說(shuō),真的是重大利好啊言歸正傳,這篇文章的目的就是把怎么用構(gòu)建一個(gè)單頁(yè)面程序介紹以下,是對(duì)自己的一個(gè)總結(jié),也喜歡對(duì)大家有一定的借鑒作用,寫的不好不對(duì)的地方希望大家多評(píng)論評(píng)論謝謝。 這篇文章是寫在公司項(xiàng)目結(jié)束之后的,因?yàn)槲覀€(gè)人不太會(huì)把沒(méi)有實(shí)踐過(guò)的東西寫出來(lái),實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)么,用的怎么樣,好不好用,在成熟實(shí)踐過(guò)的項(xiàng)目上能體...

    solocoder 評(píng)論0 收藏0
  • angularjs學(xué)習(xí)筆記——使用requirejs動(dòng)態(tài)注入控制器

    摘要:最近一段時(shí)間在學(xué)習(xí),由于覺(jué)得直接使用它需要加載很多的文件,因此想使用來(lái)實(shí)現(xiàn)異步加載,并動(dòng)態(tài)注入控制器。手動(dòng)啟動(dòng),特別說(shuō)明此處的不是那個(gè)框架,而是的一個(gè)手動(dòng)啟動(dòng)框架的函數(shù)中完成了各模塊的初始化,并且引入了。 最近一段時(shí)間在學(xué)習(xí)angularjs,由于覺(jué)得直接使用它需要加載很多的js文件,因此想使用requirejs來(lái)實(shí)現(xiàn)異步加載,并動(dòng)態(tài)注入控制器。簡(jiǎn)單搜索了下發(fā)現(xiàn)好多教程寫的都很復(fù)雜,所...

    王軍 評(píng)論0 收藏0
  • avalon 單頁(yè)面程序 (種子工程)之二 按需加載和路由系統(tǒng)

    摘要:的成功離開不這三個(gè)東西,分層架構(gòu),路由系統(tǒng),儲(chǔ)存系統(tǒng)。分層架構(gòu)是我們組織復(fù)雜代碼的關(guān)鍵,路由系統(tǒng)是將多個(gè)頁(yè)面壓縮在一個(gè)頁(yè)面的關(guān)鍵。在這個(gè)種子工程中,我都調(diào)用了同一個(gè)方法,就比較適合目錄動(dòng)態(tài)生成,需要按需調(diào)用不同的頁(yè)面的情況。 SPA的成功離開不這三個(gè)東西,分層架構(gòu),路由系統(tǒng),儲(chǔ)存系統(tǒng)。分層架構(gòu)是我們組織復(fù)雜代碼的關(guān)鍵,路由系統(tǒng)是將多個(gè)頁(yè)面壓縮在一個(gè)頁(yè)面的關(guān)鍵。 其中avalon路由用到...

    fanux 評(píng)論0 收藏0
  • 前端資源系列(4)-前端學(xué)習(xí)資源分享&前端面試資源匯總

    摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒(méi)想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...

    princekin 評(píng)論0 收藏0
  • Regularjs是什么

    摘要:目前已經(jīng)在大大小小多個(gè)線上產(chǎn)品中使用了,也收集了一些有效的建議好了,該看下一個(gè)最簡(jiǎn)單的組件長(zhǎng)什么樣吧免費(fèi)領(lǐng)取驗(yàn)證碼內(nèi)容安全短信發(fā)送直播點(diǎn)播體驗(yàn)包及云服務(wù)器等套餐更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營(yíng)經(jīng)驗(yàn)分享請(qǐng)?jiān)L問(wèn)網(wǎng)易云社區(qū)。文章來(lái)源網(wǎng)易云社區(qū) 本文由作者鄭海波授權(quán)網(wǎng)易云社區(qū)發(fā)布。 此文摘自regularjs的指南, 目前指南正在全面更新, 把老文檔的【接口/語(yǔ)法部分】統(tǒng)一放到了獨(dú)立的 Reference...

    seal_de 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<