Skip to content

你好,请问怎么不通过使用路由,来异步加载HTML及JS,并使它成功编译成ANGULAR局部应用? #7

Open

Description

@vrbvillor

这是这块代码的压缩包。
https://github.com/CHIheart/CHIanimate/blob/master/async.rar

index.html

<!DOCTYPE html>
<html ng-controller="CtrlMain">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
</head>
<body>


<button>load!!!</button>
<div id="Sync" ng-controller="CtrlSync">{{message}}{{LoginInfo.username}}</div>

</body>
</html>

<script src="./angular1.2.29.js"></script>
<script src="./sea2.3.0.js"></script>
<script>

seajs.use('./js')
</script>

js.js

define(function(require,exports,module){
    angular.module('AppLogin',[])
        .value('LoginInfo',{
            login:false,
            username:'用户名称'
        })
    angular.module('AppMain',['AppLogin'])
        .controller('CtrlMain',['$scope',function($scope){}])
        .controller('CtrlSync', ['$scope','LoginInfo', function($scope,LoginInfo){
            $scope.message="This is a sync controller."
            $scope.LoginInfo=LoginInfo;
        }]);
    angular.element(document.getElementsByTagName("button")[0]).on('click',function(event) {
        require.async(['./try.css','./try.html','./try.js'],function(css,html,js){
            angular.element(document.body).append(html)
        });
    });
    angular.bootstrap(document, ['AppMain'])
});

try.css

body{
    background-color: gray;
}

div{
    width: 100px;
    height: 100px;
    border: 1px solid red;
}

try.html

<div ng-app="AppTry" ng-controller="CtrlTry">{{message}}{{LoginInfo.username}}
<button ng-click="login();">登录</button>
</div>

try.js

define(function(require,exports,module){

    angular.module('AppMain')
        .controller('CtrlTry', ['$scope','$timeout','LoginInfo' , function ($scope,$timeout,LoginInfo) {
            $scope.message="This is the message!";
            $scope.login=function(){
                $timeout(function(){
                    $scope.LoginInfo.username="已登录用户";
                alert(1)

                });
            }
        }]);
});

sea2.3.0.js,这里边混入了sea的两个插件sea-text和sea-css

/*! Sea.js 2.3.0 | seajs.org/LICENSE.md */
!function(a,b){function c(a){return function(b){return{}.toString.call(b)=="[object "+a+"]"}}function d(){return z++}function e(a){return a.match(C)[0]}function f(a){for(a=a.replace(D,"/"),a=a.replace(F,"$1/");a.match(E);)a=a.replace(E,"/");return a}function g(a){var b=a.length-1,c=a.charAt(b);return"#"===c?a.substring(0,b):".js"===a.substring(b-2)||a.indexOf("?")>0||"/"===c?a:a+".js"}function h(a){var b=u.alias;return b&&w(b[a])?b[a]:a}function i(a){var b=u.paths,c;return b&&(c=a.match(G))&&w(b[c[1]])&&(a=b[c[1]]+c[2]),a}function j(a){var b=u.vars;return b&&a.indexOf("{")>-1&&(a=a.replace(H,function(a,c){return w(b[c])?b[c]:a})),a}function k(a){var b=u.map,c=a;if(b)for(var d=0,e=b.length;e>d;d++){var f=b[d];if(c=y(f)?f(a)||a:a.replace(f[0],f[1]),c!==a)break}return c}function l(a,b){var c,d=a.charAt(0);if(I.test(a))c=a;else if("."===d)c=f((b?e(b):u.cwd)+a);else if("/"===d){var g=u.cwd.match(J);c=g?g[0]+a.substring(1):a}else c=u.base+a;return 0===c.indexOf("//")&&(c=location.protocol+c),c}function m(a,b){if(!a)return"";a=h(a),a=i(a),a=j(a),a=g(a);var c=l(a,b);return c=k(c)}function n(a){return a.hasAttribute?a.src:a.getAttribute("src",4)}function o(a,b,c){var d=K.createElement("script");if(c){var e=y(c)?c(a):c;e&&(d.charset=e)}p(d,b,a),d.async=!0,d.src=a,R=d,Q?P.insertBefore(d,Q):P.appendChild(d),R=null}function p(a,b,c){function d(){a.onload=a.onerror=a.onreadystatechange=null,u.debug||P.removeChild(a),a=null,b()}var e="onload"in a;e?(a.onload=d,a.onerror=function(){B("error",{uri:c,node:a}),d()}):a.onreadystatechange=function(){/loaded|complete/.test(a.readyState)&&d()}}function q(){if(R)return R;if(S&&"interactive"===S.readyState)return S;for(var a=P.getElementsByTagName("script"),b=a.length-1;b>=0;b--){var c=a[b];if("interactive"===c.readyState)return S=c}}function r(a){var b=[];return a.replace(U,"").replace(T,function(a,c,d){d&&b.push(d)}),b}function s(a,b){this.uri=a,this.dependencies=b||[],this.exports=null,this.status=0,this._waitings={},this._remain=0}if(!a.seajs){var t=a.seajs={version:"2.3.0"},u=t.data={},v=c("Object"),w=c("String"),x=Array.isArray||c("Array"),y=c("Function"),z=0,A=u.events={};t.on=function(a,b){var c=A[a]||(A[a]=[]);return c.push(b),t},t.off=function(a,b){if(!a&&!b)return A=u.events={},t;var c=A[a];if(c)if(b)for(var d=c.length-1;d>=0;d--)c[d]===b&&c.splice(d,1);else delete A[a];return t};var B=t.emit=function(a,b){var c=A[a],d;if(c){c=c.slice();for(var e=0,f=c.length;f>e;e++)c[e](b)}return t},C=/[^?#]*\//,D=/\/\.\//g,E=/\/[^/]+\/\.\.\//,F=/([^:/])\/+\//g,G=/^([^/:]+)(\/.+)$/,H=/{([^{]+)}/g,I=/^\/\/.|:\//,J=/^.*?\/\/.*?\//,K=document,L=location.href&&0!==location.href.indexOf("about:")?e(location.href):"",M=K.scripts,N=K.getElementById("seajsnode")||M[M.length-1],O=e(n(N)||L);t.resolve=m;var P=K.head||K.getElementsByTagName("head")[0]||K.documentElement,Q=P.getElementsByTagName("base")[0],R,S;t.request=o;var T=/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g,U=/\\\\/g,V=t.cache={},W,X={},Y={},Z={},$=s.STATUS={FETCHING:1,SAVED:2,LOADING:3,LOADED:4,EXECUTING:5,EXECUTED:6};s.prototype.resolve=function(){for(var a=this,b=a.dependencies,c=[],d=0,e=b.length;e>d;d++)c[d]=s.resolve(b[d],a.uri);return c},s.prototype.load=function(){var a=this;if(!(a.status>=$.LOADING)){a.status=$.LOADING;var c=a.resolve();B("load",c);for(var d=a._remain=c.length,e,f=0;d>f;f++)e=s.get(c[f]),e.status<$.LOADED?e._waitings[a.uri]=(e._waitings[a.uri]||0)+1:a._remain--;if(0===a._remain)return a.onload(),b;var g={};for(f=0;d>f;f++)e=V[c[f]],e.status<$.FETCHING?e.fetch(g):e.status===$.SAVED&&e.load();for(var h in g)g.hasOwnProperty(h)&&g[h]()}},s.prototype.onload=function(){var a=this;a.status=$.LOADED,a.callback&&a.callback();var b=a._waitings,c,d;for(c in b)b.hasOwnProperty(c)&&(d=V[c],d._remain-=b[c],0===d._remain&&d.onload());delete a._waitings,delete a._remain},s.prototype.fetch=function(a){function c(){t.request(g.requestUri,g.onRequest,g.charset)}function d(){delete X[h],Y[h]=!0,W&&(s.save(f,W),W=null);var a,b=Z[h];for(delete Z[h];a=b.shift();)a.load()}var e=this,f=e.uri;e.status=$.FETCHING;var g={uri:f};B("fetch",g);var h=g.requestUri||f;return!h||Y[h]?(e.load(),b):X[h]?(Z[h].push(e),b):(X[h]=!0,Z[h]=[e],B("request",g={uri:f,requestUri:h,onRequest:d,charset:u.charset}),g.requested||(a?a[g.requestUri]=c:c()),b)},s.prototype.exec=function(){function a(b){return s.get(a.resolve(b)).exec()}var c=this;if(c.status>=$.EXECUTING)return c.exports;c.status=$.EXECUTING;var e=c.uri;a.resolve=function(a){return s.resolve(a,e)},a.async=function(b,c){return s.use(b,c,e+"_async_"+d()),a};var f=c.factory,g=y(f)?f(a,c.exports={},c):f;return g===b&&(g=c.exports),delete c.factory,c.exports=g,c.status=$.EXECUTED,B("exec",c),g},s.resolve=function(a,b){var c={id:a,refUri:b};return B("resolve",c),c.uri||t.resolve(c.id,b)},s.define=function(a,c,d){var e=arguments.length;1===e?(d=a,a=b):2===e&&(d=c,x(a)?(c=a,a=b):c=b),!x(c)&&y(d)&&(c=r(""+d));var f={id:a,uri:s.resolve(a),deps:c,factory:d};if(!f.uri&&K.attachEvent){var g=q();g&&(f.uri=g.src)}B("define",f),f.uri?s.save(f.uri,f):W=f},s.save=function(a,b){var c=s.get(a);c.status<$.SAVED&&(c.id=b.id||a,c.dependencies=b.deps||[],c.factory=b.factory,c.status=$.SAVED,B("save",c))},s.get=function(a,b){return V[a]||(V[a]=new s(a,b))},s.use=function(b,c,d){var e=s.get(d,x(b)?b:[b]);e.callback=function(){for(var b=[],d=e.resolve(),f=0,g=d.length;g>f;f++)b[f]=V[d[f]].exec();c&&c.apply(a,b),delete e.callback},e.load()},t.use=function(a,b){return s.use(a,b,u.cwd+"_use_"+d()),t},s.define.cmd={},a.define=s.define,t.Module=s,u.fetchedList=Y,u.cid=d,t.require=function(a){var b=s.get(s.resolve(a));return b.status<$.EXECUTING&&(b.onload(),b.exec()),b.exports},u.base=O,u.dir=O,u.cwd=L,u.charset="utf-8",t.config=function(a){for(var b in a){var c=a[b],d=u[b];if(d&&v(d))for(var e in c)d[e]=c[e];else x(d)?c=d.concat(c):"base"===b&&("/"!==c.slice(-1)&&(c+="/"),c=l(c)),u[b]=c}return B("config",a),t}}}(this);

!function(){function a(a){return function(b){return{}.toString.call(b)=="[object "+a+"]"}}function b(a){return"[object Function]"=={}.toString.call(a)}function c(a,c,e,f){var g=u.test(a),h=r.createElement(g?"link":"script");if(e){var i=b(e)?e(a):e;i&&(h.charset=i)}void 0!==f&&h.setAttribute("crossorigin",f),d(h,c,g,a),g?(h.rel="stylesheet",h.href=a):(h.async=!0,h.src=a),p=h,t?s.insertBefore(h,t):s.appendChild(h),p=null}function d(a,b,c,d){function f(){a.onload=a.onerror=a.onreadystatechange=null,c||seajs.data.debug||s.removeChild(a),a=null,b()}var g="onload"in a;return!c||!v&&g?(g?(a.onload=f,a.onerror=function(){seajs.emit("error",{uri:d,node:a}),f()}):a.onreadystatechange=function(){/loaded|complete/.test(a.readyState)&&f()},void 0):(setTimeout(function(){e(a,b)},1),void 0)}function e(a,b){var c,d=a.sheet;if(v)d&&(c=!0);else if(d)try{d.cssRules&&(c=!0)}catch(f){"NS_ERROR_DOM_SECURITY_ERR"===f.name&&(c=!0)}setTimeout(function(){c?b():e(a,b)},20)}function f(a){return a.match(x)[0]}function g(a){for(a=a.replace(y,"/"),a=a.replace(A,"$1/");a.match(z);)a=a.replace(z,"/");return a}function h(a){var b=a.length-1,c=a.charAt(b);return"#"===c?a.substring(0,b):".js"===a.substring(b-2)||a.indexOf("?")>0||".css"===a.substring(b-3)||"/"===c?a:a+".js"}function i(a){var b=w.alias;return b&&q(b[a])?b[a]:a}function j(a){var b,c=w.paths;return c&&(b=a.match(B))&&q(c[b[1]])&&(a=c[b[1]]+b[2]),a}function k(a){var b=w.vars;return b&&a.indexOf("{")>-1&&(a=a.replace(C,function(a,c){return q(b[c])?b[c]:a})),a}function l(a){var c=w.map,d=a;if(c)for(var e=0,f=c.length;f>e;e++){var g=c[e];if(d=b(g)?g(a)||a:a.replace(g[0],g[1]),d!==a)break}return d}function m(a,b){var c,d=a.charAt(0);if(D.test(a))c=a;else if("."===d)c=g((b?f(b):w.cwd)+a);else if("/"===d){var e=w.cwd.match(E);c=e?e[0]+a.substring(1):a}else c=w.base+a;return 0===c.indexOf("//")&&(c=location.protocol+c),c}function n(a,b){if(!a)return"";a=i(a),a=j(a),a=k(a),a=h(a);var c=m(a,b);return c=l(c)}function o(a){return a.hasAttribute?a.src:a.getAttribute("src",4)}var p,q=a("String"),r=document,s=r.head||r.getElementsByTagName("head")[0]||r.documentElement,t=s.getElementsByTagName("base")[0],u=/\.css(?:\?|$)/i,v=+navigator.userAgent.replace(/.*(?:AppleWebKit|AndroidWebKit)\/?(\d+).*/i,"$1")<536;seajs.request=c;var w=seajs.data,x=/[^?#]*\//,y=/\/\.\//g,z=/\/[^/]+\/\.\.\//,A=/([^:/])\/+\//g,B=/^([^/:]+)(\/.+)$/,C=/{([^{]+)}/g,D=/^\/\/.|:\//,E=/^.*?\/\/.*?\//,r=document,F=location.href&&0!==location.href.indexOf("about:")?f(location.href):"",G=r.scripts,H=r.getElementById("seajsnode")||G[G.length-1];f(o(H)||F),seajs.resolve=n,define("seajs/seajs-css/1.0.5/seajs-css",[],{})}();

!function(){function a(a){h[a.name]=a}function b(a){return a&&h.hasOwnProperty(a)}function c(a){for(var c in h)if(b(c)){var d=","+h[c].ext.join(",")+",";if(d.indexOf(","+a+",")>-1)return c}}function d(a,b){var c=g.XMLHttpRequest?new g.XMLHttpRequest:new g.ActiveXObject("Microsoft.XMLHTTP");return c.open("GET",a,!0),c.onreadystatechange=function(){if(4===c.readyState){if(c.status>399&&c.status<600)throw new Error("Could not load: "+a+", status = "+c.status);b(c.responseText)}},c.send(null)}function e(a){a&&/\S/.test(a)&&(g.execScript||function(a){(g.eval||eval).call(g,a)})(a)}function f(a){return a.replace(/(["\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r").replace(/[\u2028]/g,"\\u2028").replace(/[\u2029]/g,"\\u2029")}var g=window,h={},i={};a({name:"text",ext:[".tpl",".html"],exec:function(a,b){e('define("'+a+'#", [], "'+f(b)+'")')}}),a({name:"json",ext:[".json"],exec:function(a,b){e('define("'+a+'#", [], '+b+")")}}),a({name:"handlebars",ext:[".handlebars"],exec:function(a,b){var c=['define("'+a+'#", ["handlebars"], function(require, exports, module) {','  var source = "'+f(b)+'"','  var Handlebars = require("handlebars")["default"]',"  module.exports = function(data, options) {","    options || (options = {})","    options.helpers || (options.helpers = {})","    for (var key in Handlebars.helpers) {","      options.helpers[key] = options.helpers[key] || Handlebars.helpers[key]","    }","    return Handlebars.compile(source)(data, options)","  }","})"].join("\n");e(c)}}),seajs.on("resolve",function(a){var d=a.id;if(!d)return"";var e,f;(f=d.match(/^(\w+)!(.+)$/))&&b(f[1])?(e=f[1],d=f[2]):(f=d.match(/[^?]+(\.\w+)(?:\?|#|$)/))&&(e=c(f[1])),e&&-1===d.indexOf("#")&&(d+="#");var g=seajs.resolve(d,a.refUri);e&&(i[g]=e),a.uri=g}),seajs.on("request",function(a){var b=i[a.uri];b&&(d(a.requestUri,function(c){h[b].exec(a.uri,c),a.onRequest()}),a.requested=!0)}),define("seajs/seajs-text/1.1.1/seajs-text",[],{})}();

现在的效果就是点击按钮之后,加载的CSS跟HTML都是正常的,JS貌似也是正常的,但就是没办法让加进来的HTML变成有效的ANGULAR局部应用。

Activity

  1. subchen commented on Aug 18, 2016

    @subchen
    Owner

    你的代码中有一段如下:

    angular.element(document.body).append(html)

    这种方式加入的 html 没有经过 angular 处理,所以正确无法识别里面的 ng directive.

    你需要用 $compile 对 html进行编译,连接才行, 然后在加入到 dom tree。

    var html = '<div ng-model="xxx" />';
    var dom = angular.element(document.body);
    var parentScope = dom.scope();
    var newElem = $compile(html)(parentScope);
    dom.append(newElem);

    上面的代码不一定能工作,只是提供一种思路和范例。

    参考:

    1. https://segmentfault.com/q/1010000002593982
    2. http://www.gsgundam.com/2014-12-13-angularjs-compile-to-show-dymanic-html-content/
  2. vrbvillor commented on Aug 18, 2016

    @vrbvillor
    Author

    我试过,在JS.JS里边加入$compile(html)($scope)但是不行。而且我的没有directive,只是controller。

  3. subchen commented on Aug 18, 2016

    @subchen
    Owner

    有controller也可以的,只要能拿到 $compile service 就可以了。

  4. vrbvillor commented on Aug 18, 2016

    @vrbvillor
    Author

    这是我的第二种写法 https://github.com/CHIheart/CHIanimate/blob/master/async2.rar
    它报错,报我要编译的那段HTML上的控制器不存在。

  5. vrbvillor commented on Aug 18, 2016

    @vrbvillor
    Author

    这是我的第三种写法 https://github.com/CHIheart/CHIanimate/blob/master/async3.rar
    因为我刚才想到,作用域不应该是原来的作用域,应该是新加进去的那个元素上的作用域,所以我把作用域写成它了,但是依然报控制器不存在。
    就算是先把HTML加进去,再编译也不行,只要链接到作用域就会报错,光编译时不会报错。

  6. subchen commented on Aug 18, 2016

    @subchen
    Owner
    $scope.load=function() {
        require.async(['./try.css','./try.html','./try.js'],function(css,html,js){
            $compile(html)($scope);
            angular.element(document.body).append(html)
        });
    }

    你的代码有 2 个问题:

    1. 需要把 try.js 动态注入到 angular.module 里面去(动态注入你就必须用到 angular-async-loader)
    2. 不能 append 原始的 html, 而是应该 append 编译后的 dom 对象

    新的范例代码如下:

    js.js

    angular.module('AppMain',['AppLogin'])
    .controller('CtrlMain',['$scope','$compile',function($scope,$compile){
        $scope.load=function() {
           require.async(['./try.css','./try.html','./try.js'],function(css,html,js) {
              var dom = $compile(html)($scope);
              var body = angular.element(document.body);
              body.append(dom)
              body.append('<style>\n' + css + '\n</style>')
           });
        }
    }

    try.js

    define(function(require,exports,module){
        var asyncLoader = require('angular-async-loader');
    
        var app = angular.module('AppMain');
        asyncLoader.configure(app);
        app.controller('CtrlTry', ['$scope','$timeout','LoginInfo' , function ($scope,$timeout,LoginInfo) {
            $scope.message="This is the message!";
            $scope.login=function(){
                $timeout(function(){
                    $scope.LoginInfo.username="已登录用户";
                    alert(1)
                });
            }
        }]);
    });
  7. vrbvillor commented on Aug 18, 2016

    @vrbvillor
    Author

    话说,大侠,怎么把你这插件,改成CMD格式的?

    我改了好多地方,最后还是不好使,大侠能来一个完整版的代码么?谢谢啦,这个地方我已经卡住两个月了。

    仍然是在$compile()()第二个括号,就是链接到作用域那个地方报错。而且try.js里边的控制器仍然没有执行到。

  8. subchen commented on Aug 18, 2016

    @subchen
    Owner

    angular-async-loader 已经支持 AMD/CMD 加载,可以直接使用

  9. vrbvillor commented on Aug 18, 2016

    @vrbvillor
    Author

    大侠能来一个完整版的代码么?谢谢啦,这个地方我已经卡住两个月了。

    仍然是在$compile()()第二个括号,就是链接到作用域那个地方报错。而且try.js里边的控制器仍然没有执行到。

  10. subchen commented on Aug 18, 2016

    @subchen
    Owner

    是因为你在 try.js 里面的 controller 是动态加载的。
    angular 不能在 angular.bootstrap() 之后,再通过 app.controller(...) 注册任何的 controller。
    所以你的原始代码在 $compile(html)(scope) 的时候会找不到 controller。

    虽然可以通过 angular-async-loader + $compile 来解决你的问题,不过还是建议你用
    ui-router + angular-async-loader + require.js 来做。

    可以参考我的 demo 代码:https://github.com/subchen/angular-async-loader/tree/master/demo

  11. vrbvillor commented on Aug 22, 2016

    @vrbvillor
    Author

    可是这是本页异步调用小插件,没有涉及到路由啊?而且我是CMD的,不会用require,用的是sea。既然能通过angular-async-loader+$compile来完成,求你帮我写一个完整版的代码呗,谢谢啦。我卡在这里卡好久了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions