Ractive.js - 손쉬운 웹 앱
게시 됨: 2022-03-11JavaScript 프레임워크 및 라이브러리가 빠르게 확산되는 오늘날의 환경에서 개발 기반으로 삼고 싶은 것을 선택하는 것은 상당히 어려울 수 있습니다. 결국 특정 프레임워크를 사용하는 경로로 이동하면 다른 프레임워크를 사용하도록 코드를 마이그레이션하는 것은 결코 수행할 시간이나 예산이 없을 수 있는 사소하지 않은 작업입니다.
그렇다면 왜 Ractive.js인가?
불활성 HTML을 생성하는 다른 도구와 달리 Ractive는 템플릿을 기본적으로 대화형 앱의 청사진으로 변환합니다. Ractive의 공헌이 혁명적이라기보다 더 진화적이라고 확실히 주장할 수 있지만 그럼에도 불구하고 그 가치는 상당합니다.
Ractive가 그토록 유용한 이유는 강력한 기능을 제공하면서도 개발자가 사용하기에 매우 간단하다는 점입니다. 게다가 상당히 우아하고 빠르며 눈에 거슬리지 않고 작습니다.
이 기사에서는 Ractive의 주요 기능 중 일부와 웹 앱 및 개발을 단순화하는 데 도움이 되는 방법을 보여주는 간단한 Ractive 검색 앱을 구축하는 과정을 살펴보겠습니다.
Ractive.js는 무엇입니까?
Ractive는 원래 데이터 바인딩 문제를 보다 우아한 방식으로 해결하기 위해 만들어졌습니다. 이를 위해 템플릿을 가져와 DOM의 가벼운 가상 표현으로 변환하여 데이터가 변경될 때 실제 DOM이 지능적이고 효율적으로 업데이트되도록 합니다.
그러나 Ractive가 채택한 접근 방식과 인프라를 사용하여 다른 작업도 더 효율적으로 수행할 수 있다는 것이 곧 분명해졌습니다. 예를 들어 이벤트 핸들러를 재사용하고 더 이상 필요하지 않을 때 자동으로 바인딩을 해제하는 등의 작업을 자동으로 처리할 수 있습니다. 이벤트 위임이 불필요해집니다. 데이터 바인딩과 마찬가지로 이 접근 방식은 앱이 성장함에 따라 코드가 다루기 어려워지는 것을 방지합니다.
양방향 바인딩, 애니메이션 및 SVG 지원과 같은 주요 기능은 기본적으로 제공되며 플러그인을 통해 사용자 정의 기능을 쉽게 추가할 수 있습니다.
일부 도구와 프레임워크는 새로운 어휘를 배우고 특정 방식으로 앱을 구성해야 하는 반면, Ractive는 그 반대가 아니라 당신을 위해 작동합니다. 또한 다른 라이브러리와도 잘 통합됩니다.
샘플 앱
샘플 앱은 기술을 기반으로 개발자의 Toptal 데이터베이스를 검색하는 데 사용됩니다. 우리 앱에는 두 가지 보기가 있습니다.
- 검색: 인라인 검색 상자가 있는 기술 목록
- 결과: 개발자 목록을 포함한 스킬 보기
각 개발자에 대해 이름, 사진, 간단한 설명 및 기술 목록을 표시합니다(각 기술은 해당 기술 보기에 연결됨).
(참고: 애플리케이션의 온라인 작업 인스턴스와 소스 코드 저장소에 대한 링크는 이 기사의 끝에 제공됩니다.)
Ractive 프레임워크에 대한 주요 초점을 유지하기 위해 일반적으로 프로덕션에서 수행해서는 안 되는 여러 가지 단순화를 사용합니다.
- 기본 테마. 앱 스타일에 맞게 테마를 사용자 지정하는 대신 스타일 지정을 위해 기본 테마와 함께 부트스트랩을 사용합니다.
- 종속성. 우리는 종속성을 전역 변수를 정의하는 별도의 스크립트로 추가할 것입니다.
- 정적 데이터. Toptal 사이트의 공개 페이지를 스크랩하여 준비한 정적 데이터를 사용합니다.
- 클라이언트 측 라우팅이 없습니다. 즉, 보기 간에 전환할 때 URL이 동일하게 유지됩니다. SPA에 대해서는 그렇게 해서는 안 되지만 일부 작은 대화형 구성 요소에는 괜찮을 수 있습니다. Ractive에는 라우터 구현이 내장되어 있지 않지만 이 예와 같이 타사 라우터와 함께 사용할 수 있습니다.
- HTML의 스크립트 태그 내부에 정의된 템플릿입니다. 이것은 특히 소규모 응용 프로그램의 경우 반드시 나쁜 생각은 아니며 몇 가지 장점이 있습니다(간단하고 국제화를 위해 이러한 클라이언트 측 템플릿을 서버 측 템플릿과 함께 처리할 수 있음). 그러나 더 큰 앱의 경우 사전 컴파일(즉, 템플릿을 내부 JS 표현으로 사전 구문 분석하는 것)의 이점을 얻을 수 있습니다.
웹 앱 시작하기
자, 그럼 이제 앱 빌드를 시작해 보겠습니다. 우리는 더 작은 기능을 하나씩 추가하고 마주치는 개념을 탐색하면서 반복적인 방식으로 이를 수행할 것입니다.
index.html
및 script.js
라는 두 개의 파일이 있는 폴더를 만드는 것으로 시작하겠습니다. 우리 앱은 매우 간단하며 개발 서버를 시작할 필요가 없도록 file://
프로토콜에서 작동합니다(원하는 경우 가능).
검색 페이지
사용자가 Toptal 데이터베이스에서 일치하는 개발자를 찾을 수 있는 기술을 선택할 수 있는 검색 페이지를 구현하는 것으로 시작하겠습니다.
HTML 스켈레톤
이 간단한 HTML 페이지부터 시작하겠습니다.
<html> <head> <title>Toptal Search</title> <!-- LOAD BOOTSTRAP FROM THE CDN --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body> <!-- SOME BASIC STATIC CONTENT --> <div class="container"> <h1>Toptal Search</h1> </div> <!-- LOAD THE JAVASCRIPT LIBRARIES WE NEED --> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.7.3/ractive.min.js"></script> <!-- LOAD THE DATA --> <script src="https://rawgit.com/emirotin/toptal-blog-ractive/master/data.js"></script> <!-- LOAD OUR SCRIPT --> <script src="script.js"></script> </body> </html>
보시다시피 사소한 HTML5 문서입니다. CDN, Lodash(멋진 데이터 조작 라이브러리) 및 Ractive.js에서 부트스트랩을 로드합니다.
Ractive는 전체 페이지를 SPA에 할애할 필요가 없으므로 일부 정적 콘텐츠를 가질 수 있습니다. 우리의 경우 이것은 컨테이너 요소와 페이지 제목으로 구성됩니다.
마지막으로 데모를 위해 준비한 데이터와 프로그램을 포함할 스크립트를 로드합니다.
자, 이제 HTML 스켈레톤이 준비되었으므로 실제 기능을 추가해 보겠습니다.
기술 목록
내가 Ractive에 대해 특히 좋아하는 것 중 하나는 달성하고자 하는 최종 표현(HTML)에 대해 생각하고 이를 실현하는 데 필요한 코드를 작성하는 데 집중할 수 있도록 하는 방법입니다.
따라서 먼저 초기 보기로 기술 목록을 작성해 보겠습니다. 이렇게 하면 다음이 수반됩니다.
- 기술 목록이 표시될 HTML 요소를 추가합니다.
- HTML에 템플릿 코드의 작은 스니펫을 추가합니다.
- 템플릿에 데이터를 제공하는 간단하고 간단한 JavaScript를 작성하여 추가한 HTML 요소에서 렌더링합니다.
HTML에 대한 모드는 다음으로 구성됩니다.
<div class="container"> <h1>Toptal Search</h1> <div></div> <!-- THIS IS THE NEW HTML ELEMENT --> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <div class="row"> {{#each skills}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>
표시할 데이터를 수신할 HTML 요소를 지정하는 Ractive에는 특별한 규칙이 없지만 가장 간단한 방법은 요소에 ID를 추가하는 것입니다. 나는 보통 이 목적을 위해 "루트" ID를 사용합니다. Ractive가 초기화될 때 이것이 어떻게 사용되는지 곧 보게 될 것입니다. 궁금한 분들을 위해 루트 요소를 지정하는 다른 방법이 있습니다.
type="text/html"
인 약간 어색한 스크립트 요소는 브라우저가 알 수 없는 유형의 스크립트를 무시하기 때문에 구문 분석되거나 렌더링되지 않고 브라우저에 의해 로드된 HTML 덩어리를 가져오는 영리한 트릭입니다. 스크립트의 내용은 Mustache/Handlebars와 유사한 템플릿입니다(Ractive에는 일부 확장 기능이 있지만).
기술 배열에 액세스할 수 있다고 가정하고 먼저 템플릿 코드를 작성합니다. {{#each}}
mustache 지시문을 사용하여 반복을 정의합니다. 지시문 내에서 현재 요소는 this
로 액세스할 수 있습니다. 다시, 우리는 기술 변수가 문자열 배열을 보유한다고 가정하므로 단순히 보간 콧수염 {{this}}
으로 렌더링합니다.
좋아, 그게 HTML이야. 하지만 자바스크립트는 어떻습니까? 템플릿에 데이터를 제공하는 "마법"이 발생하는 곳입니다.
(function () { var skills = DB.skills, developers = DB.developers; var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skills: _.keys(DB.skills) } }); }());
인상적이죠? 10줄의 코드만으로 다음을 수행할 수 있습니다.
- "DB"에서 데이터를 "검색"합니다.
- 새 Ractive 앱을 인스턴스화합니다.
- 다음을 사용하여 요소 내부를 렌더링하도록 지시하십시오.
.
- 스크립트 요소를 사용하도록 지시하십시오.
템플릿을 가져옵니다(다른 방법도 있음).
- 초기 데이터를 전달하거나(런타임에 변경하는 방법을 볼 것입니다) Angular 용어에 익숙하다면 "범위"를 전달합니다.
- lodash
keys
방법을 사용하여 "DB"에서 객체 키로 사용하는 기술 이름을 가져옵니다.
따라서 기본적으로 이 스크립트를 사용하여 프레임워크에 수행할 작업을 지시하지만 수행 방법은 알릴 수 없습니다. 템플릿은 개인적으로 매우 놀랍고 자연스러운 방법을 선언합니다.
이제 아이디어를 얻기 시작했으므로 이제 우리가 가진 것 외에 더 유용한 것을 구현해 보겠습니다.
기술 검색
물론 검색 페이지에는 검색 필드가 필요합니다. 또한 사용자가 검색 상자에 입력할 때 기술 목록이 필터링되어 입력된 하위 문자열이 포함된 기술만 포함하는 대화형 기능을 제공하고자 합니다(필터링은 대소문자를 구분하지 않음).
Ractive에서 평소와 같이 템플릿을 정의하는 것으로 시작합니다(어떤 새로운 컨텍스트 변수가 필요할지, 데이터 관리와 관련하여 무엇이 변경될지 생각하면서):
<div class="container"> <h1>Toptal Search</h1> <div></div> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <!-- HERE'S OUR SEARCH BOX --> <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <!-- NOW INSTEAD OF DISPLAYING ALL SKILLS, WE INVOKE A TO-BE-CREATED JAVASCRIPT skills() FUNCTION THAT WILL FILTER THE SKILL LIST DOWN TO THOSE THAT MATCH THE TEXT ENTERED BY THE USER --> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>
변경 사항이 많지는 않지만 여전히 배울 부분이 많습니다.
먼저 검색 상자가 포함된 새 <div>를 추가했습니다. 우리가 그 입력을 어떤 변수에 연결하기를 원한다는 것은 꽤 분명합니다(당신이 옛날 jQuery 수프 시절을 그리워하지 않는 한). Ractive는 소위 양방향 바인딩을 지원합니다. 즉, JS 코드가 DOM에서 값을 수동으로 읽을 필요 없이 값을 검색할 수 있습니다. 우리의 경우 이것은 보간 mustache value="{{ skillFilter }}"
를 사용하여 수행됩니다. Ractive는 이 변수를 입력의 값 속성에 바인딩하고 싶다는 것을 이해합니다. 따라서 입력을 감시하고 자동으로 변수를 업데이트합니다. HTML 한 줄로 꽤 깔끔합니다.
둘째, 위 코드 조각의 주석에서 설명한 대로 이제 모든 기술을 표시하는 대신 기술 목록을 필터링하고 사용자가 입력한 텍스트와 일치하는 항목만 반환하는 skills()
JS 함수를 만듭니다.
// store skill list in a variable outside of Ractive scope var skillNames = _.keys(DB.skills); var app = new Ractive({ el: '#root', template: '#tpl-app', data: { // initializing the context variable is not strictly // required, but it is generally considered good practice skillFilter: null, // Define the skills() function right in our data object. // Function is available to our template where we call it. skills: function() { // Get the skillFilter variable from the Ractive instance // (available as 'this'). // NOTE WELL: Our use of a getter here tells Ractive that // our function has a *dependency* on the skillFilter // value, so this is significant. var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } });
이것은 명확하고 구현하기 쉽지만 성능에 어떤 영향을 미치는지 궁금할 수 있습니다. 내 말은, 우리는 매번 함수를 호출할 것입니까? 글쎄, 매번? Ractive는 종속성(변수)이 변경될 때 템플릿의 일부만 다시 렌더링(및 모든 기능 호출)할 만큼 충분히 영리합니다(Ractive는 setter를 사용하여 이러한 일이 발생하는 시점을 알고 있습니다).
덧붙여서, 이것을 한 단계 더 발전시키는 데 관심이 있는 사람들을 위해 계산된 속성을 사용하여 이 작업을 수행하는 보다 우아한 방법이 있지만 원하는 경우 직접 사용하도록 남겨두겠습니다.
결과 페이지
이제 꽤 사용 가능한 검색 가능한 기술 목록이 있으므로 일치하는 개발자 목록이 표시되는 결과 보기로 이동하겠습니다.
스킬 보기로 전환 및 전환
이를 구현할 수 있는 여러 가지 방법이 분명히 있습니다. 스킬의 선택 여부에 따라 두 가지 다른 관점이 있는 접근 방식을 선택했습니다. 그렇다면 일치하는 개발자 목록을 표시합니다. 그렇지 않은 경우 스킬 목록과 검색 상자를 표시합니다.
따라서 처음에는 사용자가 기술 이름을 선택(즉, 클릭)할 때 기술 목록을 숨겨야 하고 기술 이름이 페이지 제목으로 대신 표시되어야 합니다. 반대로 선택한 스킬 보기에는 해당 보기를 닫고 스킬 목록으로 돌아갈 수 있는 방법이 있어야 합니다.

이 경로의 첫 번째 단계는 다음과 같습니다.
<script type="text/html"> <!-- PARTIAL IS A NEW CONCEPT HERE --> {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <!-- MAKE OUR SKILLS CLICKABLE, USING PROXY EVENTS --> <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> </span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> <!-- DISPLAY SELECTED SKILL AS HEADING ON THE PAGE --> {{ currentSkill }} <!-- CLOSE BUTTON TAKES USER BACK TO SKILLS LIST --> <button type="button" class="close pull-right" on-click="deselect-skill">× CLOSE</button> </h2> {{/partial}} <!-- PARTIALS ARE NOT IN THE VIEW UNTIL WE EXPLICITLY INCLUDE THEM, SO INCLUDE THE PARTIAL RELEVANT TO THE CURRENT VIEW. --> {{#if currentSkill}} {{> skillView}} {{else}} {{> skillsList}} {{/if}} </script>
여기에서 많은 일이 일어나고 있습니다.
첫째, 이것을 두 개의 다른 보기로 구현하는 것을 수용하기 위해 지금까지 가지고 있던 모든 것(즉, 목록 보기)을 부분이라고 하는 것으로 옮겼습니다. 부분은 본질적으로 다른 위치(곧)에 포함할 템플릿 코드 덩어리입니다.
그런 다음 스킬을 클릭할 수 있게 만들고 클릭하면 해당 스킬 보기로 이동하려고 합니다. 이를 위해 프록시 이벤트라는 것을 사용합니다. 물리적 이벤트(클릭 시, 이름은 Ractive가 이해할 수 있는 이름임)에 반응하고 이를 논리적 이벤트(select-skill, 이름은 우리가 부르는 이름)에 프록시합니다. ) 인수를 전달합니다.
(참고로 동일한 작업을 수행하기 위해 메서드 호출의 대체 구문이 존재합니다.)
다음으로 (다시) 선택한 기술의 이름(있는 경우)이 있거나 기술이 선택되지 않은 경우 비어 있는 currentSkill
이라는 변수가 있다고 가정합니다. 따라서 현재 기술 이름을 표시하는 또 다른 부분을 정의하고 기술을 선택 해제해야 하는 "CLOSE" 링크도 있습니다.
JavaScript의 경우 주요 추가 사항은 select-skill 및 deselect-skill 이벤트를 구독하고 그에 따라 currentSkill
(및 기술 skillFilter
)을 업데이트하는 코드입니다.
var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skillFilter: null, currentSkill: null, // INITIALIZE currentSkill TO null // skills function remains unchanged skills: function() { var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } }); // SUBSCRIBE TO LOGICAL EVENT select-skill app.on('select-skill', function(event, skill) { this.set({ // SET currentSkill TO THE SKILL SELECTED BY THE USER currentSkill: skill, // RESET THE SEARCH FILTER skillFilter: null }); }); // SUBSCRIBE TO LOGICAL EVENT deselect-skill app.on('deselect-skill', function(event) { this.set('currentSkill', null); // CLEAR currentSkill });
각 기술에 대한 개발자 나열
기술에 대한 새로운 보기를 준비했으므로 이제 고기를 추가할 수 있습니다. 해당 목록에 대한 실제 개발자 목록입니다. 이를 위해 다음과 같이 이 보기에 대한 부분을 확장합니다.
{{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">× CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body"> {{ this.name }} </div> </div> {{/each}} {{/partial}}
바라건대 이 시점에서 여기에서 무슨 일이 일어나고 있는지 skillDevelopers
skillView
의 결과를 반복하는 새로운 반복 섹션을 우리의 기술 보기 부분에 추가했습니다. 배열의 각 개발자( 해당 기술 skillDevelopers
함수에 의해 반환됨)에 대해 패널을 렌더링하고 개발자 이름을 표시합니다. 여기서 암시적 형식 {{name}}
을 사용할 수 있으며 Ractive는 현재 컨텍스트(이 경우 {{#each}}
에 바인딩된 개발자 개체임)에서 시작하는 컨텍스트 체인을 검색하여 적절한 속성을 찾을 수 있지만 나는 명시적인 것을 선호한다. 컨텍스트 및 참조에 대한 자세한 내용은 Ractive 설명서에서 확인할 수 있습니다.
다음은 skillDevelopers()
함수의 구현입니다.
skillDevelopers: function(skill) { // GET THE SKILL OBJECT FROM THE “DB” skill = skills[skill]; // SAFETY CHECK, RETURN EARLY IN CASE OF UNKNOWN SKILL NAME if (!skill) { return; } // MAP THE DEVELOPER'S IDs (SLUGS) TO THE // ACTUAL DEVELOPER DETAIL OBJECTS return _.map(skill.developers, function(slug) { return developers[slug]; }); }
각 개발자에 대한 항목 확장
이제 작업 중인 개발자 목록이 있으므로 더 자세한 정보와 멋진 사진을 추가할 차례입니다.
{{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">× CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <!-- ADD THE PHOTO --> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <!-- MAKE THE DEVELOPER'S NAME A HYPERLINK TO THEIR PROFILE --> <a class="h4 media-heading" href="{{ this.url }}" target="_blank"> {{ this.name }}</a> <!-- ADD MORE DETAILS (FROM THEIR PROFILE) --> <p>{{ this.desc }}</p> </div> </div> </div> {{/each}} {{/partial}}
Ractive 측면에서 새로운 것은 없지만 Bootstrap 기능을 조금 더 많이 사용합니다.
클릭 가능한 개발자 기술 목록 표시
우리는 지금까지 좋은 진전을 이루었지만 여전히 부족한 기능 중 하나는 기술-개발자 관계의 다른 면입니다. 즉, 각 개발자의 기술을 표시하고 각 기술이 해당 기술에 대한 결과 보기로 이동하는 클릭 가능한 링크가 되기를 원합니다.
하지만 잠시만요... 우리는 이미 기술 목록에 정확히 같은 것이 있다고 확신합니다. 예, 실제로 그렇습니다. 클릭 가능한 기술 목록에 있지만 각 개발자의 기술 집합과 다른 배열에서 나옵니다. 그러나 이것들은 충분히 유사하여 우리가 HTML 덩어리를 재사용해야 한다는 분명한 신호입니다. 그리고 그것을 위해 부분적인 사람들은 우리의 친구입니다.
(참고: Ractive는 또한 컴포넌트라고 하는 재사용 가능한 뷰 청크에 대한 고급 접근 방식을 가지고 있습니다. 그것들은 정말 매우 유용하지만 단순성을 위해 지금은 논의하지 않겠습니다.)
다음은 부분을 사용하여 이 작업을 수행하는 방법입니다(참고로, JavaScript 코드 한 줄 추가하지 않고도 이 기능을 추가할 수 있습니다!).
<!-- MAKE THE CLICKABLE SKILL LINK INTO ITS OWN “skill” PARTIAL --> {{#partial skill}} <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> {{/partial}} {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <!-- USE THE NEW “skill” PARTIAL --> <span class="col-xs-3">{{> skill}}</span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">× CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <a class="h4 media-heading" href="{{ this.url }}" target="_blank">{{ this.name }}</a> <p>{{ this.desc }}</p> <p> <!-- ITERATE OVER THE DEVELOPER'S SKILLS --> {{#each this.skills}} <!-- REUSE THE NEW “skill” PARTIAL TO DISPLAY EACH DEVELOPER SKILL AS A CLICKABLE LINK --> {{> skill}} {{/each}} </p> </div> </div> </div> {{/each}} {{/partial}}
이미 "DB"에서 검색한 개발자 개체에 기술 목록이 첨부되어 있으므로 템플릿을 약간 변경했습니다. 기술 레이블을 부분으로 렌더링하는 줄을 이동하고 해당 줄이 원래 있던 위치에 이 부분을 사용했습니다.
그런 다음 개발자의 기술을 반복할 때 이 동일한 새 부분을 재사용하여 각 기술을 클릭 가능한 링크로 표시할 수도 있습니다. 또한 기억하는 경우 동일한 스킬 이름을 전달하여 스킬 선택 이벤트를 프록시합니다. 이것은 우리가 이것을 어디에나 포함할 수 있고(적절한 컨텍스트가 있는) 스킬 보기로 연결되는 클릭 가능한 레이블을 얻게 된다는 것을 의미합니다!
최종 터치 - 프리로더
자, 이제 기본 기능 앱이 생겼습니다. 깨끗하고 빠르게 작동하지만 여전히 로드하는 데 시간이 걸립니다. (우리의 경우 이는 부분적으로 연결되지 않고 축소되지 않은 소스를 사용하기 때문이지만 실제 앱에서는 초기 데이터 로드와 같은 다른 중요한 이유가 있을 수 있습니다.)
따라서 마지막 단계로 Ractive가 앱을 렌더링하는 즉시 제거되는 미리 로드 애니메이션을 추가하는 멋진 트릭을 보여 드리겠습니다.
<div class="container"> <h1>Toptal Search</h1> <div> <div class="progress"> <div class="progress-bar progress-bar-striped active"> Loading... </div> </div> </div> </div>
그래서 여기에 마법이 무엇입니까? 사실 아주 간단합니다. 일부 콘텐츠(Bootstrap 애니메이션 진행률 표시줄이지만 애니메이션 GIF 또는 무엇이든 될 수 있음)를 루트 요소에 바로 추가했습니다. 스크립트가 로드되는 동안 사용자는 로드 표시기를 볼 수 있습니다(JavaScript에 대한 종속성이 없으므로 즉시 표시될 수 있음). 그러나 Ractive 앱이 초기화되는 즉시 Ractive는 렌더링된 템플릿으로 루트 요소의 콘텐츠를 덮어씁니다(따라서 사전 로드 애니메이션을 지웁니다). 그렇게 하면 정적 HTML과 0줄의 논리만으로 이 효과를 얻을 수 있습니다. 아주 멋진 일이라고 생각합니다.
결론
여기에서 우리가 성취한 것과 얼마나 쉽게 성취했는지 생각해 보십시오. 우리는 매우 포괄적인 앱을 가지고 있습니다. 이 앱은 기술 목록을 보여주고, 빠르게 검색할 수 있으며(검색 상자에 사용자가 입력할 때 기술 목록의 대화식 업데이트도 지원합니다.) 특정 기술로 이동한 다음 뒤로 이동하고 목록을 표시합니다. 선택한 각 기술의 개발자. 또한 개발자가 나열한 기술을 클릭하면 해당 기술을 보유한 개발자 목록으로 이동할 수 있습니다. 80줄 미만의 HTML과 40줄 미만의 JavaScript로 이 모든 것을 해결할 수 있습니다. 내 생각에 그것은 매우 인상적이며 Ractive의 강력함, 우아함 및 단순함에 대해 많은 것을 말해줍니다.
앱의 작동 버전은 여기에서 온라인으로 사용할 수 있으며 전체 소스 코드는 공개되어 있으며 여기에서 사용할 수 있습니다.
물론, 우리는 이 기사에서 Ractive 프레임워크로 가능한 것에 대한 표면을 거의 긁지 않았습니다. 지금까지 본 것이 마음에 든다면 Ractive의 60초 설정을 시작하고 Ractive가 제공하는 모든 것을 스스로 탐색하기 시작하는 것이 좋습니다.