program tip

터보 링크와 함께 angularjs 사용

radiobox 2020. 12. 7. 08:02
반응형

터보 링크와 함께 angularjs 사용


터보 링크가있는 앱에서 Angularjs 프레임 워크를 사용하려고합니다. 페이지 변경 후 새 이벤트 리스너를 초기화하지 않습니다. 작동하도록 만드는 방법이 있습니까? 미리 감사드립니다!


AngularJS 대 Turbolinks

TurbolinksAnguluarJS 는 모두 사용자 상호 작용에 대한 응답으로 전체 페이지를 다시로드하고 다시 렌더링하지 않고 웹 페이지에서 어떤 일이 발생한다는 점에서 웹 애플리케이션이 더 빠르게 응답하도록 만드는 데 사용할 수 있습니다.

다음과 같은 점에서 다릅니다.

  • AngularJS 는 클라이언트 시스템에서 실행되는 많은 JavaScript 코드를 작성 하는 리치 클라이언트 측 애플리케이션 을 빌드하는 데 도움이됩니다 . 이 코드는 사이트를 사용자와 대화 형으로 만듭니다. JSON API를 사용하여 서버 측 백엔드, 즉 Rails 앱과 통신합니다.

  • 반면에 Turbolinks 는 JavaScript를 코딩 할 필요없이 사이트를 대화 형으로 만드는 데 도움이됩니다. 이를 통해 서버 측에서 실행 되는 Ruby / Rails 코드고수하면서 "마법처럼"AJAX를 사용하여 변경된 페이지 부분 만 교체하고 다시 렌더링 할 수 있습니다.

Turbolinks가 손으로 아무것도하지 않고 Ruby / Rails 만 코딩 할 수있는 강력한 AJAX 메커니즘을 사용할 수 있도록 허용하는 경우 애플리케이션이 성장함에 따라 AngularJS와 같은 JavaScript 프레임 워크를 통합하려는 단계가 올 수 있습니다.

특히 AngularJS를 애플리케이션에 한 번에 하나의 구성 요소 씩 연속적으로 통합하려는 중간 단계에서는 Angular JS와 Turbolinks를 함께 실행하는 것이 완벽하게 합리적 일 수 있습니다.

AngularJS와 Turbolinks를 함께 사용하는 방법

콜백을 사용하여 Angular를 수동으로 부트 스트랩

Angular 코드에는 다음과 같이 애플리케이션 모듈을 정의하는 줄이 있습니다.

# app/assets/javascripts/angular-app.js.coffee
# without turbolinks
@app = angular.module 'MyApplication', ['ngResource']

이 코드는 페이지가로드 될 때 실행됩니다. 그러나 Turbolinks는 페이지의 일부를 대체하고 전체 페이지로드를 방지하기 때문에 Turbolinks가 부분적으로 다시로드 한 후에도 각도 응용 프로그램이 제대로 초기화되었는지 ( "부트 스트랩") 확인해야합니다. 따라서 위의 모듈 선언을 다음 코드로 바꿉니다.

# app/assets/javascripts/angular-app.js.coffee
# with turbolinks
@app = angular.module 'MyApplication', ['ngResource']

$(document).on 'turbolinks:load', ->
  angular.bootstrap document.body, ['MyApplication']

자동으로 부트 스트랩 안 함

ng-appHTML 코드 속성 을 사용하여 Angular 앱을 자동으로 부트 스트랩하는 방법을 자습서에서 자주 볼 수 있습니다.

<!-- app/views/layouts/my_layout.html.erb -->
<!-- without turbolinks -->
<html ng-app="YourApplication">
  ...

그러나이 메커니즘을 위에 표시된 수동 부트 스트랩과 함께 사용하면 응용 프로그램이 두 번 부트 스트랩되므로 응용 프로그램이 중단됩니다.

따라서 다음 ng-app속성을 제거하십시오 .

<!-- app/views/layouts/my_layout.html.erb -->
<!-- with turbolinks -->
<html>
  ...

추가 읽기


Turbolinks는 페이지 렌더링을 최적화하려고 시도하며 AngularJS의 일반적인 부트 스트랩과 충돌합니다.

앱의 일부 위치에서 Turbolinks를 사용하고 있고 일부 부분은 Angular를 사용하는 경우. 이 우아한 해결책을 제안 합니다.

angularapp (ng-app = "appname"을 사용하는 곳) 인 페이지에 대한 각 링크에는 다음 속성이 있어야합니다.

<a href="/myapp" data-no-turbolink>Say NO to Turbolinks</a>.

두 번째-Stackoverflow에 언급 된 것은 page : load 이벤트를 처리하여 모든 ng-app을 명시 적으로 다시로드 / 부트 스트랩하는 것입니다. 나는 당신이 잠재적으로 페이지에없는 것을로드하여 리소스를 낭비한다는 것은 말할 것도없이 방해가 될 것입니다.

개인적으로 위의 솔루션을 사용했습니다.

도움이되기를 바랍니다.


버그의 경우

포착되지 않은 오류 : [ng : btstrpd] 앱이 이미이 요소 '문서'로 부트 스트랩되었습니다.

angular 1.2.x로 업그레이드 한 후 아래에서 문제를 해결할 수 있습니다.

angular.module('App').run(function($compile, $rootScope, $document) {
  return $document.on('page:load', function() {
    var body, compiled;
    body = angular.element('body');
    compiled = $compile(body.html())($rootScope);
    return body.html(compiled);
  });
});

이전 게시물에서 @nates는 변경 angular.bootstrap(document, ['YourApplication'])제안 angular.bootstrap("body", ['YourApplication'])했지만 컴파일되지 않은 내용이 번쩍입니다.


Turbolinks는 클라이언트 측 MVC 프레임 워크에 적합하지 않습니다. Turbolinks는 서버 응답에서 본문을 제외한 모든 것을 제거하는 데 사용됩니다. 클라이언트 측 MVC를 사용하면 HTML이 아닌 JSON을 클라이언트에 전달해야합니다.

In any event, turbolinks creates its own callbacks.

page:load
page:fetch
page:restore
page:change

The jquery.turbolinks plugin can trigger bootstrapping of modules via ng-app directives. If you're trying to manually bootstrap your modules, jquery.turbolinks can lead to ng:btstrpd errors. One caveat I've found is that jquery.turbolinks relies on the page:load event, which can trigger before any new page-specific <script> tags finish running. This can lead to $injector:nomod errors if you include module definitions outside of the application.js. If you really want your modules defined in separate javascript files that are only included on certain pages, you could just disable turbolinks on any links to those specific pages via data-no-turbolink.


Add the following event handler to your application.

Coffeescript:

bootstrapAngular = ->
  $('[ng-app]').each ->
    module = $(this).attr('ng-app')
    angular.bootstrap(this, [module])

$(document).on('page:load', bootstrapAngular)

Javascript:

function bootstrapAngular() {
  $('[ng-app]').each(function() {
    var module = $(this).attr('ng-app');
    angular.bootstrap(this, [module]);
  });
};
$(document).on('page:load', bootstrapAngular);

This will cause the angular application to be started after each page loaded by Turbolinks.

Credit to https://gist.github.com/ayamomiji/4736614


Based on the comments I've seen, the only valid scenario for using both together in a way where Angular would conflict with Turbolinks (such as where I allow Angular to handle some of the routing) is if I have an existing application that I'm trying to port to Angular.

Personally, if I were to do this from scratch, I think the best solution would be to decide what should handle the routing and stick with that. If Angular, than get rid of Turbolinks -> it won't do much for you if you have something close to a single-page app. If you allow Rails to handle the routing, then just use Angular to organize client-side behavior that can't be processed by the server when serving up the templates.

Am I missing a scenario, here? It doesn't seem elegant to me to try to split the routing responsibilities between different frameworks, even in a large application... Is there some other scenario where Turbolinks would interfere with Angular other than refreshing the page or navigating to a new route?


Using Turbolinks and AngularJS together

+1 to @fiedl for a great answer. But my preference is to make use of page:change in concert with page:load because this affords some flexibility: the DOM can receive a page:load event from sources other than turbolinks, so you might not want to have the same callback fire.

Watching for a page:change, then a page:load should restrict your callback behaviour to solely turbolinks-instigated events.

function boostrapAngularJS () {
    angular.bootstrap(document.body, ['My Application']);
    addCallbackToPageChange();
}
function addCallbackToPageChange() {
    angular.element(document).one('page:change', function () {
        angular.element(this).one('page:load', boostrapAngularJS);
    });
}
addCallbackToPageChange();

(This will allow/require you to keep your ng-app declaration in your html, as normal when working with AngularJS.)


Turbolinks automatically fetches the page, swaps in its <body>, and merges its <head>, all without incurring the cost of a full page load.

https://github.com/turbolinks/turbolinks#turbolinks

So, instead of append ng-app directive on the <html> element, we can just do it on the <body> element.

<html>
  <body ng-app=“yourApplicationModuleName">
  </body>
</html>

참고URL : https://stackoverflow.com/questions/14797935/using-angularjs-with-turbolinks

반응형