2014-11-03 3 views
1

내 백본 응용 프로그램을 정리할 수있는 깨끗하고 견고한 방법을 고민하고 있습니다. HTML 뷰를 동적으로로드하기 위해 Requirejs, Handlebars 및 Requirejs Text 플러그인을 사용하고 있습니다. 일을 단순화하기 위해, 그냥 사이트가 다음과 같은 페이지가 가정 해 봅시다 :백본 프로젝트 조직

홈 : 디스플레이 제품

의 컬렉션을

소개 : 정적 페이지

계정 : 계정 정보가 포함되어 있습니다. 구입 한 제품은 다양한 업데이트를 허용합니다. 많은 기능. 다른 섹션으로 이동하기위한 탭이 있습니다.

그래서 저는 새 페이지를 div ('.backbone-view')에로드하는 SPA를 사용할 것입니다. 경로가 변경되고 적절한 템플릿을로드 할 때 호출되는 el : $ ('. backbone-view')가있는 일반적인 AppView가 있어야합니까? 또는 각 페이지 (homeView, aboutView, accountView)에 대한보기가 있어야하며, 모두 엘을 백본보기로 설정해야합니까?

그 외에도 ... 제품 이외의 모델은 필요합니까? 정적 인 페이지에 대해서는 HTML 템플릿에로드하기 만하면됩니다. 그러나 제품의 경우 각 제품보기를 렌더링하는 제품 컬렉션을 호출해야하며 각 제품보기는 제품 모델과 관련됩니다. 괜찮아요 ...하지만이 제품 구조를 어디에서 초기화할까요? 홈페이지로 연결되면 거기에서합니까?

routes: { 
     '': 'home', 
     'about': 'about', 
     'my-account': 'myAccount', 
     '*default': 'home' 
    }, 

    'home': function() { 
     // Grab template for home page 

     // Load up products 

     // Replace $('.backbone-view') with home page template populated with products 
    }, 

    'about': function() { 
     // Grab about template and replace $('.backbone-view') with its contents 
    }, 

    'myAccount': function() { 
     MIND EXPLOSION 
    } 

내가 큰 문제는 내가보기의 목적에 명확하지 않다 ... 그들은 페이지 전환을 위해 간단하게 사용할 수 있습니다, 또는 그들은 항상 모델을 가져야한다고 생각 :이 의사 코드를 그들에게 붙어 있니? 이전 버전의 경우 AppView가 필요하고 각 페이지마다 뷰가 필요합니다. 맞습니까? 나는 각 단계를 위임 할 곳을 잃어 버렸으므로 ... 어떤 도움을 주시면 감사하겠습니다.

도움 주셔서 감사합니다.

답변

4

다음은 매우 큰 백본 응용 프로그램에서 작업 한 후의 몇 가지 팁입니다. 그것은 두 개의 디렉토리, 예를 들어

  1. 서버 디렉토리 예 : server/
  2. 공개적으로 액세스 할 수있는 디렉토리에

    나누기 .. 철저한 또는 최종 아니다 www/

또한 당신은 당신의 빌드 작업 그것은 build/ 또는 dist/ 디렉토리에 배포 버전으로 응용 프로그램을 구축 할 것을 실행할 때. Gulp 나 Grunt를 사용했을 수도 있습니다.

백본을 확장

귀하의 전체 응용 프로그램은 다음과 같이 구성됩니다

  • 조회수 & 하위 뷰
  • 라우터 & 서브 라우터
  • 모델
  • 컬렉션

처음에는 비어있는 경우에도 백본 클래스를 확장해야합니다. 가장 유용한 두 가지 확장 기능은 다음과 같습니다

  • 하위 뷰 (뷰는 상위 뷰를 제거 할 때 정리 얻을 더 뷰와 views 객체/기능을 가질 수있다). model 또는 collection이라는 모델 및 모음이 자동으로 하위보기로 전달됩니다.
  • 하위 라우터

사용 포드 아키텍처로

주위에 당신의 응용 프로그램을 구성 (이 좋다 모듈 폴더 내의 각 모듈에 대한 라우팅 로직을 가지고) 독립적 인 모듈 예 :

www/app/modules/home/router.js < - 서브 라우터는 modules.js의 메소드를 호출합니다.
www/app/modules/home/module.js < - 레이아웃 변경,보기 초기화 의 & 모델 등
www/app/modules/home/views/... 모든 뷰
www/app/modules/home/templates/
(너무 하위 폴더를 가질 수 있습니다) www/app/modules/home/models/
www/app/modules/home/collections

시작 뷰의 규정 및 하위 뷰

있는 페이지 아무튼에서 응용 프로그램을보고 ' 단지 하나의 견해로 구성됩니다. 그것은 아마도 특별한 "레이아웃"뷰를 가질 것이고 내부에는 많은 뷰가있을 것입니다. 하나는 페이지를 반으로 나눕니다. 하나는 페이지 번호별로 더 많은 뷰가있는 페이지 매김이 있으며, 내부에는 많은 하위 뷰가있는 폼의 뷰입니다. 각 양식 요소 및 메시지 등에 대해

DOM 트리를 음영 처리하고 논리적으로 분할하는 것으로 생각할 수 있습니다. 페이지에서 재사용 가능하다고 생각되는 항목은 패키지로 만듭니다 (자체보기 및 모델/모음입니다). 필요하다면).

모델은 서버/api/데이터베이스에서 뷰가 아무것도 표시하지 않으면 일반적으로 뷰에 전달되어 모델 속성 전체 또는 일부를 템플리트에 전달하는 데이터 및 데이터에 대해 수행 된 모든 논리에 대한 것입니다. .

정보를 표시하는 해당 항목이 목록에있는 경우 컬렉션은 각 항목에 대한 각 모델을 관리합니다.당신은 자신이 다른보기에보기에서 뭔가를 전달하고자 발견하면 모델

합니까 통신은 공유 모델을 사용합니다. 뷰는 가능한 한 분리되어야합니다 (부모를 인식 할 필요는 없습니다).

광범위 트리거 및 수신을 사용하여 응용 프로그램을 통해 통신 할 수 AppState 서비스라는 모델을 작성 앱 상태를 되세요. 당신은 당신이 할 수있는 다시 사용 가능한 생각 앱에서 물건을 건너 때마다

도 다른 미래의 앱에 패키지를 만들,

(옵션) 패키지 폴더 되세요. 이들은 일반적으로 자신의 git repos에서 호스팅되며 package.json 또는 명령 줄을 사용하여 프로젝트로 가져올 수 있습니다. 예를 들어, -

여러 앱에서 소비하는 모듈에 대한 확장 폴더가 당신이 간 응용 프로그램 물건

을 확장 폴더를 가지고 귀하의 백본 확장이 여기에 갈 수 있습니다. 또는 양식 용 패키지를 만들었지 만이 응용 프로그램 용으로 특별히 작업하려면 여기에서 확장하십시오.

www/app/extensions/view.js
www/app/extensions/model.js는 "버튼"패키지에서 링크보기를 확장
www/app/extensions/collection.js
www/app/extensions/buttons/link.js // .

www/assets/css
: 나는 공공 www/ 폴더에 app/ 폴더가 왜

자산

이유는 나 또한 글꼴 및 이미지 등 거기에 자산 폴더를 가질 수 있도록이다 www/assets/images

참고 : 모듈 폴더에 자산을 보관하고 싶을 수도 있습니다 (포드 아키텍처로 인라인). 나는 이것을 전에하지 않았지만 고려할만한 가치가있다.

index.html을 당신이 CommonJS를 사용 또는 AMD 당신의 index.html을 그냥 실제 DOM 요소 보일러 것이다 당신이 항목의 js 파일이 하나의 전화를했을 일반적 경우

. 디바이스에서 실행 그래서 (비 빌드) RequireJS가 app/config.js을로드하지만 빌드에서 전체 응용 프로그램 것

<!--IF NOT BUILD--> 
<script data-main="/app/config" src="/packages/require.js"></script> 
<!--ELSE 
<script src="/app.js"></script> 
--> 

: CommonJS 컴파일해야하기 때문에 이것은 단지 <script src="/app.js"></script> 같은 것을 할 것이지만, AMD 것이 더 같은 것 app.js에 있습니다. 다양한 Grunt/Gulp 빌드 작업을 통해 위와 같은 작업을 수행 할 수 있습니다 (조건부 구문이 작성된 것임).

레이아웃

내가 extensions/view.js 확장하는 extensions/layout.js을 만들 것이며, 정상적인 같은 하위 뷰 (예 : 머리글과 바닥 글)을 가질 수있는 간단한 확장뿐만 아니라, 내가 어떤을 첨부 할 수있는 특별한 서브 뷰 것 보기 (예 : 본문 하위보기) 방법은 setContentView(view)입니다.

나는 layouts라는 모듈을 만들고 거기에 머리말과 꼬리말 subviews가있는보기가있는 modules/layout/default 디렉토리를 가지고있을 것이다. 그런 다음 인덱스 경로에 도달하면이 같은 것을 흐를 것 :

app/router.js => app/modules/home/router.js => app/modules/home/[email protected] => setContentView(view from app/modules/home/views/index.js)"

라우팅을

나는이 응용 프로그램 라우터가 예를 들어,에있는 것

당신이 필요 확장에 (주 같은과 일반 백본 라우터를 확장하여

subRouters: { 
    'store-locator': StoreLocatorRouter, 
    myaccount: MyAccountRouter, 
    sitemap: SitemapRouter 
} 

내가이 가능하게합니다 : 어떤 특별한 경로를 가질 수 있지만, 대부분 단지 하위 라우터에서 지적 객체와 subroute 것 www/app/router.js) initializeinitSubRouters 전화 -

define([ 
    'underscore', 
    'backbone' 
], 
function(_, Backbone) { 

    'use strict'; 

    /** 
    * Extended Backbone Boilerplate Router 
    * @class extensions/router 
    * @extends backbone/view 
    */ 
    var Router = Backbone.Router.extend(
     /** @lends extensions/router.prototype */ 
     { 

     /** 
     * Holds reference to sub-routers 
     * @type {Object} 
     */ 
     subRouters: {}, 

     /** 
     * Adds sub-routing 
     * based on https://gist.github.com/1235317 
     * @param {String} prefix The string to be prefixed to the route values 
     */ 
     constructor: function(options) { 
      if (!options) { 
       options = {}; 
      } 

      var routes = {}, prefix = options.prefix; 

      if (prefix) { 
       // Ensure prefixes have exactly one trailing slash 
       prefix.replace(/\/*$/, '/'); 
      } else { 
       // Prefix is optional, set to empty string if not passed 
       prefix = ''; 
      } 

      if (prefix) { 
       // Every route needs to be prefixed 
       _.each(this.routes, function(callback, path) { 
        if (path) { 
         routes[prefix + '/' + path] = callback; 
        } else { 
         // If the path is "" just set to prefix, this is to comply 
         // with how Backbone expects base paths to look gallery vs gallery/ 
         routes[prefix + '(/)'] = callback; 
        } 
       }); 

       // Must override with prefixed routes 
       this.routes = routes; 
      } 

      // .navigate needs subrouter prefix 
      this.prefix = prefix; 

      // Required to have Backbone set up routes 
      Backbone.Router.prototype.constructor.apply(this, arguments); 
     }, 

     /** 
     * Sets up 'beforeRoute' event. 
     */ 
     initialize: function() { 
      // This is a round about way of adding a beforeRoute event and must 
      // happen before any other routes are added. 
      Backbone.history.route({ 
       test: this.beforeRoute 
      }, function() {}); 
     }, 

     /** 
     * Called before routes. 
     * @return {Boolean} false This ensures the 'route' is disabled. 
     */ 
     beforeRoute: function() { 
      Backbone.history.trigger('beforeRoute'); 
      return false; 
     }, 

     /** 
     * Adds prefix to navigation routes 
     * @param {String} route Non-prefixed route 
     * @param {Object} options Passed through to Backbone.router.navigate 
     */ 
     navigate: function(route, options) { 
      if (route.substr(0, 1) !== '/' && route.indexOf(this.prefix.substr(0, 
       this.prefix.length - 1)) !== 0) { 
       route = this.prefix + route; 
      } 
      Backbone.Router.prototype.navigate.call(this, route, options); 
     }, 

     /** 
     * Initializes sub-routers defined in `this.subRouters` 
     */ 
     initSubRouters: function() { 
      _.each(this.subRouters, function(Router, name) { 
       this[name] = new Router({ 
        prefix: name 
       }); 
      }, this); 
     } 

    }); 

    return Router; 
}); 

project layout

app layout

+0

훌륭한 답변, 감사합니다 Dominic! 나는이 템플릿으로 프로젝트를 재구성하기 시작했고, 이미 훨씬 더 조직화되어 있습니다. 몇 가지 후속 질문이 있습니다. 모든 페이지에 표시 될 헤더의 부분 템플릿이있는 경우 (다른 요소를 기반으로하는 동적 인 경우에도) 확장 프로그램 폴더에 배치해야합니까? 모든 모듈? 또한 뷰와 하위 뷰가있는 경로를 클릭하면 응용 프로그램 흐름을 설명 할 수 있습니까? 마찬가지로, 하위보기를 호출하는 기본보기 내에서 기본보기 -> 메소드를 호출하는 router -> method ...? 감사! –

+0

@ user918065 Np 추가 정보를 추가했습니다. 나는 막연하게 어떤 것들을 만졌을 뿐더러 붙어 있다면 Qs에 자유롭게 물어보십시오. 그리고 자신의 리포지토리와 패키지로 패키지를 만드는 것에 대해 걱정할 필요가 없을 것입니다. –

+0

감사! 빠른 질문 : 내 서브 라우터는 링크를 통해 탐색 할 때 작동하지만 URL로 직접 이동할 때는 작동하지 않습니다. 그 상황에서 서브 라우터는 절대로 호출되지 않습니다. –

관련 문제