programing

Express/Jade를 사용하여 부분 뷰를 올바르게 렌더링하고 JavaScript 파일을 AJAX에 로드하는 방법은 무엇입니까?

subpage 2023. 3. 5. 09:49
반응형

Express/Jade를 사용하여 부분 뷰를 올바르게 렌더링하고 JavaScript 파일을 AJAX에 로드하는 방법은 무엇입니까?

요약

웹 어플리케이션에서 Express + Jade를 사용하고 있는데 AJAX 내비게이션에서 부분 뷰를 렌더링하는 데 어려움을 겪고 있습니다.

두 가지 다른 질문이 있는데, 완전히 연결되어 있기 때문에 같은 투고에 포함시켰습니다.긴 투고가 될 것 같지만, 이미 같은 문제로 고민하셨다면 분명 재미있을 것입니다.누군가 시간을 내어 읽어보고 해결책을 제안해 주셨으면 합니다.

TL;DR : 2가지 질문

  • Express + Jade를 사용하여 AJAX 내비게이션의 뷰 조각을 렌더링하는 가장 깨끗하고 빠른 방법은 무엇입니까?
  • 각 뷰에 관련된 JavaScript 파일을 로드하려면 어떻게 해야 합니까?

요구 사항들

  • 웹은 사용하지 설정한 .
  • JavaScript가 사용 가능한 경우, 전체 레이아웃이 아닌 페이지 자체 컨텐츠만 서버에서 클라이언트로 전송해야 합니다.
  • 앱은 가능한 한 빠르고 적은 바이트를 로드해야 합니다.

문제 1: 내가 시도한 것

해결책 1: AJAX 요구와 AJAX 이외의 요구의 파일이 다르다

레이아웃은 다음과 같습니다.

doctype html
    html(lang="fr")
        head
            // Shared CSS files go here
            link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
        body
            div#main_content
                block content
            // Shared JS files go here
            script(src="js/jquery.min.js")

my page_full.jade는 다음과 같습니다.

extends layout.jade

block content
    h1 Hey Welcome !

my page_ajax는 다음과 같습니다.

h1 Hey Welcome

마지막으로 router.js(Express):

app.get("/page",function(req,res,next){
   if (req.xhr) res.render("page_ajax.jade");
   else res.render("page_full.jade");
});

결점:

  • 짐작하신 것처럼, 저는 무언가를 변경해야 할 때마다 두 번 보기를 수정해야 합니다.꽤 답답하다.

해결책 2: "include"와 동일한 기술

레이아웃은 변하지 않습니다.

doctype html
    html(lang="fr")
        head
            // Shared CSS files go here
            link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
        body
            div#main_content
                block content
            // Shared JS files go here
            script(src="js/jquery.min.js")

my page_full.jade는 다음과 같습니다.

extends layout.jade

block content
   include page.jade

페이지에는 레이아웃/블록/테이블/테이블이 없는 실제 내용이 포함되어 있습니다.

h1 Hey Welcome

이제 router.js(Express)에 있습니다.

app.get("/page",function(req,res,next){
   if (req.xhr) res.render("page.jade");
   else res.render("page_full.jade");
});

장점:

  • 이제 내 콘텐츠는 한 번만 정의되므로 더 좋습니다.

결점:

  • 페이지에 두 개의 파일이 필요합니다.
  • 익스프레스에서는 모든 루트에서 같은 기술을 사용해야 합니다.코드 반복 문제를 제이드에서 익스프레스로 옮겼습니다.똑딱똑딱.

솔루션 3: 솔루션 2와 동일하지만 코드 반복 문제를 해결합니다.

알렉스 포드의 기술을 사용하여, 나는 내 자신의 기술을 정의할 수 있었다.rendermiddleware.function:

app.use(function (req, res, next) {  
    res.renderView = function (viewName, opts) {
        res.render(viewName + req.xhr ? null : '_full', opts);
        next();
    };
 });

다음으로 router.js(Express)를 다음과 같이 변경합니다.

app.get("/page",function(req,res,next){
    res.renderView("/page");
});

다른 파일은 변경하지 않습니다.

이점

  • 코드 반복 문제를 해결했다.

결점

  • 페이지에 두 개의 파일이 필요합니다.
  • 만의 ★★★★★★★★★★★★★★★★★★★의 정의renderView방법이 좀 지저분하게 느껴집니다.결국, 템플릿 엔진/프레임워크가 이것을 대신 처리해 줄 것으로 기대하고 있습니다.

해결책 4: 로직의 제이드로의 이행

저는 한 페이지에 두 개의 파일을 사용하는 것을 좋아하지 않습니다.Express 대신 Jade에게 렌더링 방법을 결정하게 하면 어떨까요?언뜻 보기엔 매우 불편해 보이는데, 템플릿 엔진은 논리를 전혀 다루지 않아야 한다고 생각하기 때문입니다.하지만 해보자.

먼저 Jade에게 어떤 요청인지 알려주는 변수를 전달해야 합니다.

in middleware.js (Express)

app.use(function (req, res, next) {  
    res.locals.xhr = req.xhr;
 });

, 이제 제 레이아웃입니다.은 이전과 같습니다.

doctype html
    html(lang="fr")
        head
            // Shared CSS files go here
            link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
        body
            div#main_content
                block content
            // Shared JS files go here
            script(src="js/jquery.min.js")

그리고 내 페이지.은 다음과 같습니다.

if (!locals.xhr)
    extends layout.jade

block content
   h1 Hey Welcome !

훌륭하지? 하지만 제이드에서는 조건 연장이 불가능하기 때문에 그것은 효과가 없을 것이다.그래서 나는 시험지를 이동할 수 있었다.옥을 배치하다:

if (!locals.xhr)
    doctype html
       html(lang="fr")
           head
               // Shared CSS files go here
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                    block content
                // Shared JS files go here
                script(src="js/jquery.min.js")
 else
     block content

클릭합니다.은 다음과 같이 반환됩니다.

extends layout.jade

block content
   h1 Hey Welcome !

장점:

  • 이제 한 페이지당 하나의 파일만 있습니다.
  • 는 반복할 가 없다.req.xhr 또는

단점:

  • 내 템플릿에는 논리가 있다.좋지 않습니다.

요약

이것들은 모두 제가 생각하고 시도했던 기술들이지만, 어느 것도 저를 납득시키지 못했습니다.내가 뭘 잘못하고 있나요?더 깨끗한 기술이 있나요?아니면 다른 템플릿엔진/프레임워크를 사용해야 하나요?


문제 #2

뷰에 자체 JavaScript 파일이 있는 경우(이러한 솔루션 중 하나) 어떻게 됩니까?

예를 들어 솔루션 #4를 사용하여 클라이언트 측 JavaScript 파일 js/page_a.js 및 js/page_b.js를 가진 페이지 page_a.jade와 page_b.jade의 두 페이지가 있는 경우 페이지가 AJAX에 로드되면 어떻게 됩니까?

ㅇㅇ를 , 첫 번째를 정의하고 있습니다.extraJS블록 배열을 하다:

if (!locals.xhr)
    doctype html
       html(lang="fr")
           head
               // Shared CSS files go here
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                    block content
                // Shared JS files go here
                script(src="js/jquery.min.js")
                // Specific JS files go there
                block extraJS
 else
     block content
     // Specific JS files go there
     block extraJS

다음으로 page_a.displaces가 됩니다.

extends layout.jade

block content
   h1 Hey Welcome !
block extraJS
   script(src="js/page_a.js")

localhost/page_a내 URL 바(AJAX 이외의 요청)에서 컴파일된 버전을 얻을 수 있습니다.

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
            body
               div#main_content
                  h1 Hey Welcome A !
               script(src="js/jquery.min.js")
               script(src="js/page_a.js")

츠키노 지금 지지 to to to 로 가면 될까요?page_b AJAX 내비게이션을 사용하여?내 페이지는 의 컴파일 버전입니다.

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                  h1 Hey Welcome B !
                  script(src="js/page_b.js")
               script(src="js/jquery.min.js")
               script(src="js/page_a.js")

js/page_a.filename과 js/page_b.filename은 모두 같은 페이지에 로드됩니다.충돌(같은 변수 이름 등)이 발생하면 어떻게 됩니까? 또한 AJAX를 사용하여 localhost/page_a로 돌아가면 다음과 같이 됩니다.

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                  h1 Hey Welcome B !
                  script(src="js/page_a.js")
               script(src="js/jquery.min.js")
               script(src="js/page_a.js")

동일한 JavaScript 파일(page_a.js)이 동일한 페이지에 두 번 로드됩니다! 충돌, 각 이벤트 더블 부팅이 발생합니까?그게 사실이든 아니든, 이건 명백한 암호는 아닌 것 같아.

특정 은 JS파일이 JS파일에 수 .block content다른 페이지로 이동하면 지워질 수 있습니다.레이아웃은 이렇습니다.은 다음과 같아야 합니다.

if (!locals.xhr)
    doctype html
       html(lang="fr")
           head
               // Shared CSS files go here
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                    block content
                    block extraJS
                // Shared JS files go here
                script(src="js/jquery.min.js")
 else
     block content
     // Specific JS files go there
     block extraJS

지? 러... if if if if 。localhost/page_a의 : , ,의 컴 , 、 。

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
            body
               div#main_content
                  h1 Hey Welcome A !
                  script(src="js/page_a.js")
               script(src="js/jquery.min.js")

js/page_a.js는 실제로 jQuery보다 먼저 로드되기 때문에 jQuery가 아직 정의되지 않았기 때문에 동작하지 않습니다.그래서 나는 이 문제에 대해 어떻게 해야 할지 모르겠어.(예를 들어) 클라이언트 측에서 스크립트 요구를 처리할 수 있을 것으로 생각했습니다.jQuery.getScript()클라이언트는 스크립트의 파일 이름을 알아야 합니다.이미 로딩되어 있는지 확인하거나 삭제할 수도 있습니다.클라이언트 측에서 하면 안 될 것 같아요.

AJAX를 통해 로드된 JavaScript 파일을 다른 전략/템플릿 엔진을 사용하여 서버측에서 처리하려면 어떻게 해야 합니까?클라이언트측?

여기까지 해냈다면, 당신은 진정한 영웅입니다.감사합니다만, 조언을 해 주시면 더욱 감사하겠습니다.

좋은 질문입니다.완벽한 옵션은 없지만 마음에 드는 솔루션 #3의 변형을 제안합니다.솔루션 #3과 동일한 아이디어이지만 _full 파일의 옥 템플릿을 코드로 이동합니다.보일러플레이트이기 때문에 javascript는 페이지 전체를 위해 필요할 때 생성할 수 있기 때문입니다.면책사항: 검증되지 않았지만 겸허히 제안합니다.

app.use(function (req, res, next) {
    var template = "extends layout.jade\n\nblock content\n    include ";  
    res.renderView = function (viewName, opts) {
        if (req.xhr) {
            var renderResult = jade.compile(template + viewName + ".jade\n", opts);
            res.send(renderResult);
        } else {
            res.render(viewName, opts);
        }
        next();
    };
 });

예를 들어 이 템플릿을 파일 이름의 자리 표시자가 있는 파일에 저장하는 등 시나리오가 복잡해짐에 따라 이 아이디어를 더욱 현명하게 활용할 수 있습니다.

물론 이것은 여전히 완벽한 해결책은 아니다.솔루션 #3에 대한 원래 반대와 마찬가지로 템플릿 엔진에서 실제로 처리해야 할 기능을 구현하고 있습니다.만약 당신이 이것을 위해 몇 십 줄 이상의 코드를 작성하게 된다면, Jade에 이 기능을 맞추는 방법을 찾아보고 그들에게 풀 요청을 보내보세요.예를 들어, xhr 요청의 레이아웃 확장을 비활성화할 수 있는 인수를 jade "extends" 키워드가 사용했을 경우...

두 번째 문제에 대해서는 템플릿 엔진이 도움이 될 수 있을지 모르겠습니다.Ajax 네비게이션을 사용하는 경우 백엔드 템플릿 매직으로 네비게이션을 수행할 때 page_a.js를 "언로드"할 수 없습니다.이(클라이언트 측)에는 기존의 Javascript 분리 기법을 사용해야 한다고 생각합니다.고객 고유의 우려 사항:우선 페이지 고유의 논리(및 변수)를 클로저에 구현하고 필요에 따라 이들 간에 합리적인 협력을 합니다.둘째, 이벤트 핸들러를 이중으로 연결하는 것에 대해 너무 걱정할 필요가 없습니다.메인 콘텐츠가 Ajax 네비게이션에서 클리어되고 새로운 Ajax 콘텐츠가 DOM에 로드될 때 호출되는 이벤트 핸들러가 연결된 요소들이라고 가정합니다.

도움이 될지는 모르겠지만 Express와 ejs 템플릿에서도 같은 문제를 해결했습니다.

내 폴더:

  • app.module
  • 뷰 / 뷰.ejs
  • 뷰/페이지.ejs
  • 뷰 / 뷰.ejs

내 앱.my application.displays

app.get('/page', function(req, res) {
    if (req.xhr) {
        res.render('page',{ajax:1});
    } else {
        res.render('page',{ajax:0});
    }
});

my page.ejs

<% if (ajax == 0) { %> <% include header %> <% } %>

content

<% if (ajax == 0) { %> <% include footer %><% } %>

매우 심플하지만 완벽하게 작동합니다.

당신이 부탁한 것을 하는 방법은 여러 가지가 있지만, 모두 건축적으로 좋지 않습니다.지금은 눈치채지 못하겠지만 시간이 지날수록 점점 더 나빠질 겁니다.

현시점에서는 이상하게 들리지만 JS, CSS를 AJAX를 통해 전송하고 싶지는 않습니다.

당신이 원하는 것은 AJAX를 통해 마크업을 받고 그 후에 Javascript를 하는 것입니다.또한, 여러분은 이것을 하는 동안 유연하고 이성적이기를 원합니다.확장성 또한 중요합니다.

일반적인 방법은 다음과 같습니다.

  1. 모든 프리로드js파일은 특정 페이지 및 해당 AJAX 요청 핸들러에서 사용할 수 있습니다.이름 충돌이나 스크립트 부작용이 우려되는 경우 browserify를 사용하십시오.사용자가 대기하지 않도록 비동기(스크립트 비동기)로 로드합니다.

  2. 클라이언트에서 기본적으로 다음을 수행할 수 있는 아키텍처를 개발합니다.loadPageAjax('page_a').then(...).catch(...)포인트는 모든 JS 모듈을 프리다운로드했기 때문에 AJAX 페이지 관련 코드를 착신측이 아닌 요청 발신측에서 실행하는 것입니다.

솔루션 #4는 거의 양호합니다.스크립트가 아닌 HTML을 가져오는 데 사용합니다.

이 기술은 불분명한 아키텍처를 구축하지 않고도 하나의 견고한 목표 제한 방법을 사용하여 목표를 달성할 수 있습니다.

더 이상의 질문에 기꺼이 대답하고 당신이 하려는 일을 하지 않도록 설득하겠습니다.

언급URL : https://stackoverflow.com/questions/25134232/how-to-properly-render-partial-views-and-load-javascript-files-in-ajax-using-ex

반응형