programing

jQuery/JavaScript 코드를 구성하는 가장 좋은 방법(2013)

oldcodes 2023. 8. 22. 22:28
반응형

jQuery/JavaScript 코드를 구성하는 가장 좋은 방법(2013)

문제

이 답변은 이전에 답변한 적이 있지만 오래되어 최신 상태가 아닙니다.저는 하나의 파일에 2,000줄이 넘는 코드를 가지고 있습니다. 우리 모두가 알다시피 이것은 나쁜 관행입니다. 특히 코드를 살펴보거나 새로운 기능을 추가할 때 그렇습니다.저는 현재와 미래를 위해 코드를 더 잘 구성하고 싶습니다.

저는 많은 버튼, UI 요소, 드래그, 드롭, 액션 리스너/핸들러 및 여러 청취자가 동일한 기능을 사용할 수 있는 글로벌 범위의 기능을 갖춘 도구(단순한 웹 사이트가 아님)를 구축하고 있다고 언급해야 합니다.

예제 코드

$('#button1').on('click', function(e){
    // Determined action.
    update_html();
});

... // Around 75 more of this

function update_html(){ .... }

...

기타 예제 코드

결론

반복하지 않고 새로운 기능을 추가하고 이전 기능을 업데이트할 수 있도록 이 코드를 구성해야 합니다.저는 이것을 혼자서 작업할 것입니다.일부 실렉터는 100줄의 코드일 수 있고 1줄일 수 있습니다.는 에대해조알다니습봤아금다▁a▁at에 대해 조금 알아봤습니다.require.js반복적이고, 실제로는 필요 이상의 코드를 작성합니다. 이 기준에 맞는 가능한 해결책을 찾고 리소스/예문에 연결하는 것이 항상 도움이 됩니다.

감사해요.

도움이 될 수도 있고 안 될 수도 있는 간단한 것들을 검토해 보겠습니다.어떤 것은 분명할 수도 있고, 어떤 것은 극도로 난해할 수도 있습니다.

1단계: 코드 구분

코드를 여러 모듈식 장치로 분리하는 것은 매우 좋은 첫 단계입니다."함께" 작동하는 것들을 모아서 그들만의 작은 상자에 넣습니다.지금은 포맷에 대해 걱정하지 말고, 그것을 계속 유지하세요.그 구조는 나중의 점입니다.

다음과 같은 페이지가 있다고 가정합니다.

enter image description here

유지보수가 용이하도록 헤더 관련 이벤트 처리기/바인더를 모두 배치하는 것이 좋습니다(1000줄을 걸러낼 필요가 없습니다).

그런 다음 Grunt와 같은 도구를 사용하여 JS를 단일 장치로 다시 빌드할 수 있습니다.

1a단계: 종속성 관리

Require와 같은 라이브러리 사용JS 또는 공통AMD라는 것을 구현하기 위한 JS. 비동기식 모듈 로딩은 당신이 당신의 코드가 무엇에 의존하는지 명시적으로 말할 수 있게 해주고, 그러면 당신은 라이브러리 호출을 코드로 오프로드 할 수 있게 해줍니다.문자 그대로 "This needs jQuery"라고 말하면 AMD가 로드하고 jQuery가 사용 가능할 때 코드를 실행할 수 있습니다.

이것은 숨겨진 보석도 가지고 있습니다. 즉, 라이브러리 로딩은 DOM이 준비되는 순간에 완료됩니다. 이전이 아닙니다.더 이상 페이지 로드가 중단되지 않습니다!

2단계: 모듈화

철조망 보여요?두 개의 광고 유닛이 있습니다.이벤트 청취자를 공유할 가능성이 높습니다.

이 단계의 작업은 코드에서 반복되는 지점을 식별하고 이 모든 것을 모듈로 통합하는 것입니다.모듈은 지금 당장 모든 것을 아우를 것입니다.우리가 가는 동안 물건들을 나눌 것입니다.

이 단계의 전체 아이디어는 1단계에서 모든 복사 파스타를 삭제하여 느슨하게 결합된 장치로 교체하는 것입니다.그래서, 다음을 갖는 대신에:

ad_unit1.js

 $("#au1").click(function() { ... });

ad_unit2.js

 $("#au2").click(function() { ... });

내가 가질 것:

ad_unit.js:

 var AdUnit = function(elem) {
     this.element = elem || new jQuery();
 }
 AdUnit.prototype.bindEvents = function() {
     ... Events go here
 }

page.js:

 var AUs = new AdUnit($("#au1,#au2"));
 AUs.bindEvents();

를 통해 이벤트와 마크업을 구분할 수 있을 뿐만 아니라 반복도 제거할 수 있습니다.이것은 꽤 괜찮은 단계이며 나중에 더 확장할 것입니다.

3단계: 프레임워크를 선택합니다!

모듈화하고 반복 횟수를 더욱 줄이고 싶다면 MVC(모델 - 보기 - 컨트롤러) 접근 방식을 구현하는 멋진 프레임워크가 많이 있습니다.제가 좋아하는 것은 백본/척추입니다. 하지만 Angular, Yii, ...도 있습니다.목록은 계속됩니다.

모형은 데이터를 나타냅니다.

보기는 마크업과 관련된 모든 이벤트를 나타냅니다.

컨트롤러는 비즈니스 로직을 나타냅니다. 즉, 컨트롤러는 페이지에 로드할 뷰와 사용할 모델을 알려줍니다.

이것은 중요한 학습 단계가 될 것이지만, 상은 그럴 가치가 있습니다: 스파게티보다 깨끗하고 모듈식 코드를 선호합니다.

여러분이 할 수 있는 다른 많은 것들이 있습니다. 그것들은 단지 지침과 아이디어일 뿐입니다.

코드별 변경 사항

코드에 대한 몇 가지 구체적인 개선 사항은 다음과 같습니다.

 $('.new_layer').click(function(){

    dialog("Create new layer","Enter your layer name","_input", {

            'OK' : function(){

                    var reply = $('.dialog_input').val();

                    if( reply != null && reply != "" ){

                            var name = "ln_"+reply.split(' ').join('_');
                            var parent = "";

                            if(selected_folder != "" ){
                            parent = selected_folder+" .content";
                            }

                            $R.find(".layer").clone()
                            .addClass(name).html(reply)
                            .appendTo("#layer_groups "+parent);

                            $R.find(".layers_group").clone()
                            .addClass(name).appendTo('#canvas '+selected_folder);

            }

        }

    });
 });

이는 다음과 같이 더 잘 작성됩니다.

$("body").on("click",".new_layer", function() {
    dialog("Create new layer", "Enter your layer name", "_input", {
         OK: function() {
             // There must be a way to get the input from here using this, if it is a standard library. If you wrote your own, make the value retrievable using something other than a class selector (horrible performance + scoping +multiple instance issues)

             // This is where the view comes into play. Instead of cloning, bind the rendering into a JS prototype, and instantiate it. It means that you only have to modify stuff in one place, you don't risk cloning events with it, and you can test your Layer stand-alone
             var newLayer = new Layer();
             newLayer
               .setName(name)
               .bindToGroup(parent);
          }
     });
});

코드의 이전 버전:

window.Layer = function() {
    this.instance = $("<div>");
    // Markup generated here
};
window.Layer.prototype = {
   setName: function(newName) {
   },
   bindToGroup: function(parentNode) {
   }
}

갑자기 코드의 모든 위치에서 복사 붙여넣기 없이 표준 레이어를 만들 수 있습니다.5개의 다른 장소에서 이 작업을 수행하고 있습니다.제가 방금 복사 페이스트 다섯 장을 저장했습니다.

하나 더:

작업에 대한 규칙 집합 래퍼

var PageElements = function(ruleSet) {
ruleSet = ruleSet || [];
this.rules = [];
for (var i = 0; i < ruleSet.length; i++) {
    if (ruleSet[i].target && ruleSet[i].action) {
        this.rules.push(ruleSet[i]);
    }
}
}
PageElements.prototype.run = function(elem) {
for (var i = 0; i < this.rules.length; i++) {
    this.rules[i].action.apply(elem.find(this.rules.target));
}
}

var GlobalRules = new PageElements([
{
    "target": ".draggable",
    "action": function() { this.draggable({
        cancel: "div#scrolling, .content",
        containment: "document"
        });
    }
},
{
    "target" :".resizable",
    "action": function() {
        this.resizable({
            handles: "all",
            zIndex: 0,
            containment: "document"
        });
    }
}

]);

GlobalRules.run($("body"));

// If you need to add elements later on, you can just call GlobalRules.run(yourNewElement);

이것은 표준이 아닌 이벤트나 생성 이벤트가 있는 경우 규칙을 등록할 수 있는 매우 강력한 방법입니다.이것은 또한 펍/서브 알림 시스템과 결합되어 있고 요소를 생성할 때마다 이벤트에 바인딩되어 있을 때 매우 충격적입니다.파이어는 모듈식 이벤트 바인딩을 잊지 않습니다!

require.js를 사용하여 현재 코드베이스를 여러 파일로 분할하는 간단한 방법은 다음과 같습니다.코드를 두 개의 파일로 나누는 방법을 보여드리겠습니다.그 후에는 파일을 더 추가하는 것이 간단합니다.

1단계) 코드 맨 위에 App 개체(또는 원하는 이름(예: MyGame)을 만듭니다.

var App = {}

2단계) 모든 최상위 변수와 함수를 App 개체에 속하도록 변환합니다.

다음 대신:

var selected_layer = "";

원하는 항목:

App.selected_layer = "";

다음 대신:

function getModified(){
...
}

원하는 항목:

App.getModified = function() {

}

이 시점에서 코드는 다음 단계를 완료할 때까지 작동하지 않습니다.

3단계) 모든 글로벌 변수 및 함수 참조를 App을 통해 변환합니다.

다음과 같은 변경 사항:

selected_layer = "."+classes[1];

대상:

App.selected_layer = "."+classes[1];

그리고:

getModified()

대상:

App.GetModified()

4단계) 이 단계에서 코드를 테스트합니다. 모두 작동해야 합니다.처음에는 무언가를 놓쳤기 때문에 몇 가지 오류가 발생할 수 있으므로 다음 단계로 넘어가기 전에 오류를 수정하십시오.

5단계) 요구 사항을 설정합니다.웹 서버에서 제공되는 웹 페이지의 코드는 다음과 같습니다.

www/page.html

그리고 jquery in.

www/js/jquery.js

이러한 경로가 정확히 이와 같지 않으면 아래와 같이 작동하지 않으므로 경로를 수정해야 합니다.

requirejs를 다운로드하고 require.js를 입력합니다.www/js디렉토리입니다.

의 신의에page.html모든 스크립트 태그를 삭제하고 다음과 같은 스크립트 태그를 삽입합니다.

<script data-main="js/main" src="js/require.js"></script>

를 만들다www/js/main.js내용 포함:

require.config({
 "shim": {
   'jquery': { exports: '$' }
 }
})

require(['jquery', 'app']);

그런 다음 1-3단계(글로벌 변수만 App이어야 함)에서 방금 수정한 모든 코드를 다음에 넣습니다.

www/js/app.js

파일 맨 위에 다음을 입력합니다.

require(['jquery'], function($) {

아래쪽 입력:

})

그런 다음 브라우저에 page.html을 로드합니다.앱이 작동해야 합니다!

6단계) 다른 파일 만들기

여기가 당신의 일이 성과를 내는 곳입니다. 당신은 이것을 계속해서 할 수 있습니다.

다음에서 일부 코드를 빼냅니다.www/js/app.js$ 및 App을 참조합니다.

예.

$('a').click(function() { App.foo() }

에 .www/js/foo.js

파일 맨 위에 다음을 입력합니다.

require(['jquery', 'app'], function($, App) {

아래쪽 입력:

})

그런 다음 www/js/main.js의 마지막 줄을 다음으로 변경합니다.

require(['jquery', 'app', 'foo']);

바로 그거야!코드를 파일에 넣을 때마다 이 작업을 수행합니다.

당신의 질문과 의견에 대해서는 백본과 같은 프레임워크에 코드를 이식하거나 Require와 같은 로더 라이브러리를 사용할 의향이 없다고 가정하겠습니다.당신은 이미 가지고 있는 코드를 가능한 가장 간단한 방법으로 구성할 수 있는 더 나은 방법을 원할 뿐입니다.

작업할 섹션을 찾기 위해 코드 2000줄 이상을 스크롤하는 것이 귀찮다는 것을 이해합니다.해결책은 각 기능별로 하나씩 다른 파일로 코드를 분할하는 것입니다.예를들면sidebar.js,canvas.js등. 그런 다음 그룬트를 사용하여 생산을 위해 함께 결합할 수 있으며, Usemin과 함께 다음과 같은 것을 가질 수 있습니다.

HTML에서:

<!-- build:js scripts/app.js -->
<script src="scripts/sidebar.js"></script>
<script src="scripts/canvas.js"></script>
<!-- endbuild -->

Grunt 파일에서:

useminPrepare: {
  html: 'app/index.html',
  options: {
    dest: 'dist'
  }
},
usemin: {
  html: ['dist/{,*/}*.html'],
  css: ['dist/styles/{,*/}*.css'],
  options: {
    dirs: ['dist']
  }
}

만약 당신이 요먼을 사용하고 싶다면, 그것은 당신에게 이 모든 것에 대한 상용어구 코드를 줄 것입니다.

그런 다음 각 파일 자체에 대해 모범 사례를 따르고 모든 코드와 변수가 해당 파일에 있으며 다른 파일에 종속되지 않도록 해야 합니다.이것은 한 파일의 함수를 다른 파일에서 호출할 수 없다는 것을 의미하지 않습니다. 요점은 변수와 함수를 캡슐화하는 것입니다.이름을 띄우는 것과 비슷한 것.모든 코드를 Object Oriented로 포팅하고 싶지는 않을 것입니다. 하지만 조금만 리팩터링해도 괜찮다면 Module pattern이라고 불리는 것과 동등한 것을 추가하는 것이 좋습니다.다음과 같습니다.

사이드바.js

var Sidebar = (function(){
// functions and vars here are private
var init = function(){
  $("#sidebar #sortable").sortable({
            forceHelperSize: true,
            forcePlaceholderSize: true,
            revert: true,
            revert: 150,
            placeholder: "highlight panel",
            axis: "y",
            tolerance: "pointer",
            cancel: ".content"
       }).disableSelection();
  } 
  return {
   // here your can put your "public" functions
   init : init
  }
})();

그런 다음 다음 다음과 같은 코드를 로드할 수 있습니다.

$(document).ready(function(){
   Sidebar.init();
   ...

이렇게 하면 코드를 너무 많이 다시 작성할 필요 없이 훨씬 더 유지 관리 가능한 코드를 가질 수 있습니다.

Javascript MVC Framework를 사용하여 Javascript 코드를 표준 방식으로 구성합니다.

사용 가능한 최고의 자바스크립트 MVC 프레임워크는 다음과 같습니다.

JavaScript MVC 프레임워크를 선택하려면 고려해야 할 요소가 너무 많습니다.프로젝트에 중요한 요소를 기반으로 최적의 프레임워크를 선택하는 데 도움이 되는 다음 비교 기사를 읽으십시오. http://sporto.github.io/blog/2013/04/12/comparison-angular-backbone-can-ember/

Require를 사용할 수도 있습니다.비동기 js 파일 및 모듈 로딩을 지원하는 프레임워크를 가진 js.
JS 모듈 로드를 시작하려면 아래를 참조하십시오.
http://www.sitepoint.com//http://www.sitepoint.com/understanding-requirejs-for-effective-javascript-module-loading/

코드를 분류합니다.이 방법은 저에게 많은 도움이 되고 있으며 어떤 JS 프레임워크에서도 작동합니다.

(function(){//HEADER: menu
    //your code for your header
})();
(function(){//HEADER: location bar
    //your code for your location
})();
(function(){//FOOTER
    //your code for your footer
})();
(function(){//PANEL: interactive links. e.g:
    var crr = null;
    $('::section.panel a').addEvent('click', function(E){
        if ( crr) {
            crr.hide();
        }
        crr = this.show();
    });
})();

선호하는 편집기(코모도 편집기)에서 모든 항목을 접으면 제목만 표시됩니다.

(function(){//HEADER: menu_____________________________________
(function(){//HEADER: location bar_____________________________
(function(){//FOOTER___________________________________________
(function(){//PANEL: interactive links. e.g:___________________

다음을 제안합니다.

  1. 이벤트 관리를 위한 게시자/가입자 패턴입니다.
  2. 물체의 방향
  3. 네임스페이스

제시카의 경우, 인터페이스를 페이지나 화면으로 나눕니다.페이지 또는 화면은 개체가 될 수 있으며 일부 상위 클래스에서 확장될 수 있습니다.페이지 관리자 클래스가 있는 페이지 간의 상호 작용을 관리합니다.

백본과 같은 것을 사용할 것을 제안합니다.백본은 RESTFULL 지원 Javascript 라이브러리입니다.Ik는 코드를 더 깨끗하고 읽기 쉽게 만들어 주며 requirejs와 함께 사용할 때 강력합니다.

http://backbonejs.org/

http://requirejs.org/

백본은 실제 라이브러리가 아닙니다.자바스크립트 코드에 구조를 부여하기 위한 것입니다.jquery, jquery-ui, 구글 맵 등의 다른 라이브러리를 포함할 수 있습니다.Backbone은 Object Oriented 및 Model View Controller 구조에 가장 가까운 Javascript 접근 방식이라고 생각합니다.

워크플로우에 대해서도..PHP로 응용프로그램을 빌드할 경우 Laravel 라이브러리를 사용합니다.RESTfull 원리와 함께 사용하면 Backbone에서 완벽하게 작동합니다.Laravel Framework 및 RESTfull API 구축에 대한 튜토리얼 링크 아래:

http://maxoffsky.com/code-blog/building-restful-api-in-laravel-start-here/

http://laravel.com/

아래는 netuts의 튜토리얼입니다.Netuts에는 고품질 튜토리얼이 많이 있습니다.

http://net.tutsplus.com/tutorials/javascript-ajax/understanding-backbone-js-and-the-server/

yoman http://yeoman.io/ 과 같은 도구를 사용하여 전체 개발 워크플로우를 구현하기 시작할 때가 된 것 같습니다.이렇게 하면 모든 종속성을 제어하고 프로세스를 빌드하며 원하는 경우 자동 테스트를 수행할 수 있습니다.시작하기에는 많은 작업이 필요하지만 일단 구현되면 미래의 변화가 훨씬 쉬워질 것입니다.

언급URL : https://stackoverflow.com/questions/16736483/best-way-to-organize-jquery-javascript-code-2013

반응형