2017-01-16 45 views
5

Tôi đang xây dựng một trang web tĩnh bằng Handlebars và Gulp. Dưới đây là cấu trúc thư mục của tôi:Làm thế nào để kết hợp JSON và Handlebars từ partials vào HTML với Gulp?

app/ 
    content/ 
     intro.json 
     header.json 
     faq.json 
     features.json 
     footer.json 
    templates/ 
     home.hbs 
     partials/ 
      home-section.hbs 
      header.hbs 
      footer.hbs 
    index.html 
Gulpfile.js 

Nội dung của home.hbs là thế này:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <title>Test</title> 
</head> 
<body> 
    {{> header}} 
    {{> home-section}} 
    {{> home-section}} 
    {{> home-section}} 
    {{> footer}} 
</body> 
</html> 

Tôi muốn vượt qua trong intro.json, faq.json, và features.json cho mỗi home-section partials, và header.json để headerfooter.json để chân trang.

Đây là những gì tôi có trong Gulpfile của tôi cho đến nay:

var gulp = require('gulp'); 
var handlebars = require('gulp-compile-handlebars'); 
var rename = require('gulp-rename'); 

gulp.task('html', function() { 
    return gulp.src('./app/templates/*.hbs') 
    .pipe(handlebars({}, { 
      ignorePartials: true, 
      batch: ['./app/templates/partials'] 
      })) 
    .pipe(rename({ 
      extname: '.html' 
      })) 
    .pipe(gulp.dest('build')); 
}); 

tôi đã không thể tìm ra cách để vượt qua tập tin nhiều hơn một JSON tại một thời điểm, đặc biệt là các home-section s. Cảm ơn trước!

Trả lời

3

Tham số đầu tiên là handlebars là ngữ cảnh chung của bạn, có sẵn cho tất cả các mẫu của bạn. Bạn có thể tải các tệp JSON riêng lẻ của bạn vào một đối tượng bối cảnh và sử dụng nó làm tham số đầu tiên.

(Có cách chắc chắn tốt hơn để làm điều này, nhưng hey, nó nhanh chóng và dễ dàng!)

var infoData = require('./app/content/info.json'); 
var faqData = require('./app/content/faq.json'); 
var featuresData = require('./app/content/features.json'); 

Sau đó bạn có thể vượt qua các đối tượng này thông qua bối cảnh toàn cầu để tay lái của bạn hoạt động

.pipe(handlebars({ info: infoData, faq: faqData, features: featuresData })) 

Khi dữ liệu nằm trong ngữ cảnh của bạn, bạn có thể truy cập dữ liệu như sau:

{{> home-section content=info }} 
{{> home-section content=faq }} 
{{> home-section content=features }} 

Bên trong phần home-section của bạn, bạn sẽ có một đối tượng content sẽ chứa dữ liệu của tệp bạn đã truyền vào nó. Vì vậy, nếu tập tin info.json của bạn trông như thế này:

{ "header": "Info", "details": "This is some information" } 

bạn home-content.hbs phần sau đó có thể truy cập dữ liệu như thế này:

<h2>{{ content.header }}</h2> 
<p>{{ content.details }}</p> 
+0

Bạn có ý nghĩa gì bởi 'bên trong' mục nhà 'của bạn, bạn sẽ có đối tượng 'nội dung'? Bạn có thể cho tôi xem mã này không? – Ryan

+0

@Ryan Khi bạn render một handlebars một phần, các tham số bạn truyền vào nó sau đó có sẵn bên trong template của partial dựa trên tên của tham số mà bạn đã sử dụng. Vì vậy, nếu bạn chèn một phần của bạn với '{{> home-section thing = info}}', phần 'home-section' của bạn sẽ có quyền truy cập vào một' điều' biến chứa nội dung của 'info'. – dstaley

2

Thật không may, gulp-compile-handlerbars chức năng chỉ mất two arguments, là đầu tiên là toàn bộ dữ liệu được chuyển vào mẫu của bạn. Điều này có nghĩa là bạn phải tải tất cả các tệp json của bạn lại với nhau và chuyển chúng thành một đối tượng duy nhất.

Bạn có thể làm điều này với một helper nhỏ như:

function requireJsons(fileNames) { 
    return fileNames.reduce(function(jsons, fileName) { 
    jsons[fileName] = require('app/content/' + fileNames[i] + '.json'); 
    return jsons; 
    }, {}); 
} 

Mà bạn có thể sử dụng để xây dựng các đối tượng dữ liệu cho tất cả các mẫu của bạn:

var data = requireJsons(['intro', 'header', 'faq', 'features', 'footer']); 

gulp.task('html', function() { 
    return gulp.src('./app/templates/*.hbs') 
    .pipe(handlebars(data, { 
     // ... 

Nếu bạn luôn cần phải tải tất cả các tệp json từ thư mục app/content, bạn có thể sử dụng readdirSync để có được tất cả.tên file json và sau đó vượt qua họ để requireJsons:

var path = require('path'); 
var fileNames = fs.readdirSync('app/content') 
    .filter(function(fileName) { 
    return path.extname(fileName) === '.json'; 
    }); 
var data = requireJsons(fileNames); 

Tất nhiên, nếu tốc độ là quan trọng, bạn có thể kết hợp hai thành một phương pháp mà tải jsons và xây dựng các đối tượng data trong một lần.


Một tùy chọn khác là có thể biên dịch từng mẫu riêng lẻ và chuyển dữ liệu thích hợp vào mỗi biên dịch. Một công cụ như gulp-foreach sẽ hữu ích.

Các vấn đề liên quan