2016-01-28 14 views
7

Tôi đang viết một ứng dụng với một số bộ phận như SPA và một số trang tạo ra trên phía máy chủ cho SEO. Tôi đã chọn khung công tác Aurelia.io và tôi sử dụng phương thức enhance để bật các phần tử tùy chỉnh trên các trang của mình. Nhưng tôi không thể tìm thấy cách tốt nhất để sử dụng chỉ thị mẫu cụ thể aurelia và nội suy trên trang bên máy chủ của tôi. Hãy bắt đầu với một ví dụ.Làm thế nào để cải thiện trang được tạo ra phía máy chủ với Aurelia.io?

Tất cả các trang của tôi chứa một tiêu đề động. Tiêu đề này sẽ là một phần tử tùy chỉnh có tên là my-cool-header. Tiêu đề này sẽ tải người dùng được xác thực và hiển thị tên của nó hoặc nếu không có người dùng nào được xác thực, một liên kết tới đăng nhập sẽ được hiển thị. Phần thân của trang sẽ được tạo ở phía máy chủ và được lưu trong bộ nhớ cache. Vì vậy, chúng ta sẽ có một cái gì đó như thế:

<html> 
<body> 
    <my-cool-header> 
     <img src="logo.png"> 
     <div 
      show.bind="user">${user.name}</div> 
     <div 
      show.bind="!user"><a href="/signin">Sign-in</a></div> 
    </my-cool-header> 
    <div>Cachabled content</div> 
</body> 
</html> 

Sau đó, phần đầu của tôi sẽ bởi xác định bởi:

import {UserService} from './user'; 
import {inject} from 'aurelia-framework'; 

@inject(UserService) 
export class MyCoolHeader { 
    constructor(userService) { 
     this.userService = userService; 
    } 

    async attached() { 
     this.user = await this.userService.get(); 
    } 
} 

Với mẫu sau:

<template> 
    <content></content> 
</template> 

Và kịch bản bootstrap này:

export function configure(aurelia) { 
    aurelia.use 
    .standardConfiguration() 
    .developmentLogging() 
    .globalResources('my-cool-header'); 

    aurelia.start().then(a => a.enhance(document.body)); 
} 

Trong cấu hình này tion, phần tử tùy chỉnh được nạp và instanciated. Nhưng, tôi không thể truy cập viewModel của nút bên trong nút <content>. Vì vậy, tất cả các nội suy (${user.name}) and attributes ( show.bind ) are ignored. If I include a custom-element in my content template, it will be loaded only if it is declared as global in the bootstrap : the `thẻ bị bỏ qua.

Tôi đã tìm thấy cách giải quyết để có thể thay đổi chế độ xemMô hình sau khi đọc tài liệu bằng cách đặt chế độ xem tùy chỉnhPhương thức nâng cao phương pháp và sau đó, tiêm . để yếu tố tùy chỉnh của tôi lớp Một cái gì đó như:

import {MainData} from './main-data'; 
export function configure(aurelia) { 
    const mainData = aurelia.container.get(MainData); 
    aurelia.use 
    .standardConfiguration() 
    .developmentLogging() 
    .globalResources('my-cool-header'); 

    aurelia.start().then(a => a.enhance(mainData, document.body)); 
} 

tuỳ chỉnh yếu tố:

import {UserService} from './user'; 
import {inject} from 'aurelia-framework'; 
import {MainData} from './main-data'; 

@inject(UserService, MainData) 
export class MyCustomElement { 
    constructor(userService, mainData) { 
     this.userService = userService; 
     this.mainData = mainData; 
    } 

    async attached() { 
     this.mainData.user = await this.userService.get(); 
    } 
} 

Và cuối cùng, nếu tôi thay đổi mẫu của tôi như vậy, nó sẽ làm việc:

<html> 
<body> 
    <my-cool-header 
     user.bind="user"> 
     <img src="logo.png"> 
     <div 
      show.bind="user">${user.name}</div> 
     <div 
      show.bind="!user"><a href="/signin">Sign-in</a></div> 
    </my-cool-header> 
    <div>Cachabled content</div> 
</body> 
</html> 

Tôi không thể tin rằng đó là cách phù hợp để làm vì nó xấu xí và nó không giải quyết được vấn đề của thẻ <require>. Vì vậy, câu hỏi của tôi là: Cách tốt nhất để làm gì?

+0

Làm thế nào để bạn phát triển "một số phần như SPA và một số trang được tạo ở phía máy chủ"? Tại sao bạn không thể chỉ sử dụng phía khách hàng? Và tại sao bạn sử dụng phía máy chủ cho seo? –

+0

Tôi có một số trang cần được tham khảo và được tăng cường bằng javascript, trong ví dụ của tôi, tôi có tiêu đề này là một phần tử tùy chỉnh chung giữa backoffice như SPA và các trang được tham chiếu, nhưng tôi sẽ có –

Trả lời

3

Nhờ những manh mối của bạn, tôi đã tìm ra giải pháp!

Phần tử tùy chỉnh cần phải xây dựng mẫu riêng của mình:

import {processContent, noView} from 'aurelia-framework'; 

@processContent(function(viewCompiler, viewResources, element, instruction) { 
    instruction.viewFactory = viewCompiler.compile(`<template>${element.innerHTML}</template>`, viewResources, instruction); 
    element.innerHTML = ''; 
    return false; 
}) 
@noView 
export class MyCustomElement { 
    attached() { 
    this.world = 'World!'; 
    this.display = true; 
    } 
} 

Sau đó, theo quan điểm của tôi từ máy chủ, chúng ta có thể suy và đòi hỏi yếu tố tùy chỉnh!

<body> 
    <my-custom-element> 
    <require="./other-custom-element"></require> 
    <p 
     if.bind="display">Hello ${world}</p> 
    <other-custom-element></other-custom-element> 
    </my-custom-element> 
</body> 

Tôi đã viết một trang trí để giúp tạo ra loại này của các yếu tố tùy chỉnh nâng: https://github.com/hadrienl/aurelia-enhanced-template

Thêm de chi tiết en français sur mon blog: https://blog.hadrien.eu/2016/02/04/amelioration-progressive-avec-aurelia-io/

EDIT: <require> là không thực sự làm việc với giải pháp này.Tôi phải đào một lần nữa: (

2

Thay đổi mẫu MyCoolHeader của bạn từ:

<template> 
    <content></content> 
</template> 

tới:

<template> 
    <img src="logo.png"> 
    <div show.bind="user">${user.name}</div> 
    <div show.bind="!user"><a href="/signin">Sign-in</a></div> 
</template> 

sau đó thay đổi trang chủ tạo của bạn để một cái gì đó như thế này:

<html> 
<body> 
    <my-cool-header></my-cool-header> 
    <div>Cachabled content</div> 
</body> 
</html> 

Hy vọng rằng sẽ giúp . Nếu điều này không giải quyết được vấn đề hoặc không phải là giải pháp có thể chấp nhận được, hãy cho tôi biết.

Sửa

Sau khi đọc trả lời của bạn và suy nghĩ về điều này một chút nữa tôi đang nghiêng về phía loại bỏ các yếu tố <my-cool-header>.Nó không cung cấp bất kỳ hành vi nào, nó chỉ hoạt động như một trình tải dữ liệu, mẫu của nó được cung cấp bởi quy trình hiển thị phía máy chủ và được dự kiến ​​sẽ được hiển thị bên ngoài hệ thống tạo mẫu aurelia, không cần phải trả lại nó. Đây là những gì phương pháp này sẽ như thế nào, cho tôi biết nếu nó có vẻ như một sự phù hợp tốt hơn:

<html> 
<body> 
    <div class="my-cool-header"> 
    <img src="logo.png"> 
    <div show.bind="user">${user.name}</div> 
    <div show.bind="!user"><a href="/signin">Sign-in</a></div> 
    </div> 

    <div>Cachabled content</div> 
</body> 
</html> 
import {MainData} from './main-data'; 
import {UserService} from './user'; 

export function configure(aurelia) { 
    const mainData = aurelia.container.get(MainData); 
    const userService = aurelia.container.get(UserService); 

    aurelia.use 
    .standardConfiguration() 
    .developmentLogging(); 

    Promise.all([ 
    this.userService.get(), 
    aurelia.start()  
    ]).then(([user, a]) => { 
    mainData.user = user; 
    a.enhance(mainData, document.body); 
    }); 
} 
+0

Không, bởi vì tôi muốn một số đánh dấu trong nút nội dung để được hiển thị mà không có javascript.Phải của tôi sẽ không thể hiểu được với: '

Tiêu đề ứng dụng web của tôi được Google thu thập thông tin

${someInterpolation}
' –

+0

Offhand, tôi nghĩ rằng vấn đề ở đây là phạm vi viewmodel. Nội dung bên trong thẻ '' sẽ thuộc về chế độ xem có chứa (cha mẹ), không phải là dạng xem của phần tử tùy chỉnh. –

+0

Tôi đồng ý! Có cách nào để truy cập vào phạm vi của thẻ không? –

0

Bổ sung câu trả lời của Jeremy, nếu bạn đã thay đổi mẫu để:

<template> 
    <img src="logo.png"> 
    <div show.bind="user">${user.name}</div> 
    <div show.bind="!user"><a href="/signin">Sign-in</a></div> 
</template> 

này nội dung sẽ có mặt khi Aurelia xử lý phần tử và khi không có bộ chọn nội dung, bất kỳ thứ gì bên trong thẻ phần tử tùy chỉnh sẽ được thay thế bằng mẫu

Nếu bạn đặt non-javas của mình nội dung cript bên trong các thẻ thành phần tùy chỉnh:

<my-cool-header> 
    <div>This stuff will be visible when JS is turned off</div> 
</my-cool-header> 

Trong ví dụ trên, trong sự vắng mặt của JS các div vẫn nên có mặt ở đó như Aurelia sẽ không xóa nó khỏi DOM.

(Điều này là tất nhiên giả sử công nghệ phía máy chủ của bạn không mangle/sửa chữa các thẻ HTML biết trong DOM đối với một số lý do khi phục vụ trang - mà nó có lẽ sẽ không vì nó sẽ phá vỡ Aurelia anyway)

CHỈNH SỬA:

Cách thay thế bạn có thể đang tìm kiếm là trang trí @processContent.

Điều này cho phép bạn chuyển một hàm gọi lại chạy trước khi Aurelia kiểm tra phần tử.

Tại thời điểm này, bạn chỉ có thể nâng nội dung giữa các thẻ phần tử tùy chỉnh và thêm nó làm phần tử con của phần tử mẫu. Nội dung sau đó sẽ nằm trong phạm vi của chế độ xem của bạn.

Bằng cách này bạn có thể có đánh dấu tương tự ở giữa các thẻ thành phần tùy chỉnh không có javascript, và bên trong mẫu của bạn trong phạm vi chính xác khi Aurelia đang chạy

import {processContent, TargetInstruction, inject} from 'aurelia-framework'; 

@inject(Element, TargetInstruction) 
@processContent(function(viewCompiler, viewResources, element, instruction) { 
    // Do stuff 
    instruction.templateContent = element; 

    return true; 
}) 
class MyViewModel { 
    constructor(element, targetInstruction) { 
     var behavior = targetInstruction.behaviorInstructions[0]; 
     var userTemplate = behavior.templateContent; 

     element.addChild(userTemplate); 
    } 
} 

Disclaimer: mã trên hasn' t đã được thử nghiệm và tôi kéo nó từ lưới của tôi mà là một số phiên bản cũ - bạn có thể cần phải tinh chỉnh

+0

Tôi muốn '' có thể trở thành một đánh dấu lớn hơn bởi vì nó là tiêu đề trang web với tiêu đề và những thứ được hiển thị mà không có js, và với js. –

+0

Không chắc chắn ý bạn là gì - cách tiếp cận trên sẽ dẫn đến việc đánh dấu mẫu hiện diện khi Aurelia hoạt động và div khi Aurelia không hoạt động (js off) – Charleh

+0

Với ví dụ của bạn, ' 'nằm trong mẫu phần tử tùy chỉnh. Vì vậy, nó sẽ được hiển thị chỉ khi aurelia sẽ được tải. Tôi muốn '' hiển thị bên trong phần tử '' trước và sau khi javascript được thi hành. Và tôi không muốn lặp lại đánh dấu trong mẫu máy chủ và mẫu khách hàng. –

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