2015-05-06 21 views
9

Daniel F Pupius mô tả các vấn đề như:Ember.js khôi phục di chuyển trên lịch sử, thiết lập lại di chuyển vào liên kết

Rất nhiều trang web có được điều này sai và nó thực sự gây phiền nhiễu. Khi người dùng điều hướng bằng nút tiến lên hoặc quay lại của trình duyệt, vị trí cuộn phải giống với lần cuối cùng trên trang. Điều này đôi khi hoạt động chính xác trên Facebook nhưng đôi khi không hoạt động. Google+ dường như luôn mất vị trí cuộn của bạn.

Vì vậy, đã có rất nhiều câu hỏi về việc đặt lại cuộn lên đầu trang khi duyệt đến một trang mới. Cookbook của Ember.js cũng là shows how to hook into Route.activate:

export default Ember.Mixin.create({ 
    activate: function() { 
    this._super(); 
    window.scrollTo(0,0); 
    } 
}); 

Tuy nhiên điều này chỉ giải quyết được một nửa vấn đề. Khi người dùng sử dụng các nút lùi/tiến, vị trí cuộn sẽ không được khôi phục nhưng chỉ cần đặt lại.

Có khá nhiều nỗ lực để giải quyết vấn đề này, nhiều khi chỉ lưu trữ vị trí cuộn trong ví dụ Ember.Controller, ví dụ: article. Tuy nhiên đây chỉ là một giải pháp một phần. Nếu bộ điều khiển được sử dụng nhiều lần, chỉ một trạng thái cuộn đơn sẽ được giữ nguyên.

Làm cách nào để triển khai trình duyệt mặc định khôi phục trạng thái cuộn cũ được giữ nguyên? Do đó, không làm gì nếu Route.activate được kích hoạt từ một thay đổi trạng thái lịch sử html5?

Trả lời

14

Tôi vừa giải quyết vấn đề này trong ứng dụng của riêng mình.

Nếu bạn chỉ muốn sử dụng nó ở những nơi mà cần đến nó, chỉ cần sử dụng một mixin:

ember g mixin remember-scroll

Sau đó, trong mixins/remember-scroll.js, thay bằng:

import Ember from 'ember'; 

export default Ember.Mixin.create({ 

    scrollSelector: window, 

    activate: function() { 
    this._super.apply(this, arguments); 
    var self = this; 
    if(this.get('lastScroll')){ 

     Ember.run.next(function(){ 
     Ember.$(self.scrollSelector).scrollTop(self.get('lastScroll')); 
     }); 

    } else { 
     Ember.$(this.scrollSelector).scrollTop(0); 
    } 
    }, 

    deactivate: function() { 
    this._super.apply(this, arguments); 
    this.set('lastScroll',Ember.$(this.scrollSelector).scrollTop()); 
    }, 

}); 

Nếu bạn muốn nó tự động trộn vào tất cả các tuyến đường, sau đó thực hiện như sau.

Trong Ember CLI, tạo một trình khởi tạo mới.

ember g initializer remember-scroll

Sau đó, trong initializers/remember-scroll.js, thay thế mã với điều này:

import Ember from "ember"; 

var rememberScroll = Ember.Mixin.create({ 

    scrollSelector: window, 

    activate: function() { 
    this._super.apply(this, arguments); 
    var self = this; 
    if(this.get('lastScroll')){ 

     Ember.run.next(function(){ 
      Ember.$(self.scrollSelector).scrollTop(self.get('lastScroll')); 
     }); 

    } else { 
     Ember.$(this.scrollSelector).scrollTop(0); 
    } 
    }, 

    deactivate: function() { 
    this._super.apply(this, arguments); 
    this.set('lastScroll',Ember.$(this.scrollSelector).scrollTop()); 
    }, 

}); 

export function initialize(/* container, application */) { 
    Ember.Route.reopen(rememberScroll); 
} 

export default { 
    name: 'remember-scroll', 
    initialize: initialize 
}; 

Bạn có thể loại bỏ các mixin đầu tiên ở trên nếu bạn đang sử dụng phiên bản khởi tạo.

Điều này sẽ khiến tất cả các tuyến đường của bạn phải nhớ vị trí cuộn cuối cùng (nếu bạn đã ở đó trước đó) và áp dụng nó khi bạn quay trở lại đó.

Mặc dù tôi khuyên bạn không nên đặt nó vào tất cả các tuyến đường, vì người dùng có thể không được trả về vị trí cuộn trước đó nếu một khoảng thời gian đáng kể đã trôi qua kể từ khi họ ở đó.

+0

Tôi nghĩ rằng điều này sẽ không nhớ hai vị trí cuộn khác nhau nếu bộ điều khiển được truy cập hai lần? – bouke

+0

Bản mixin này áp dụng cho tuyến đường chứ không phải bộ điều khiển. Nó nhớ vị trí cuộn khi bạn rời khỏi tuyến đường (xem phần 'hủy kích hoạt'), sau đó khôi phục nó khi bạn quay trở lại. – JeremyTM

3

Tôi đã tìm thấy the solution by JeremyTM here để có hiệu quả chung. Tuy nhiên, sử dụng phương pháp deactivate trong trải nghiệm của tôi dẫn đến mâu thuẫn trong giá trị được đặt thành lastScroll khi chuyển đổi trong khi sử dụng phương thức hành động willTransition của tuyến đường dẫn đến hành vi đặt nhất quán.

Đây là sửa đổi để mixin mình mà làm việc tốt hơn cho tôi:

import Ember from 'ember'; 

export default Ember.Mixin.create({ 
    activate: function() { 
    this._super.apply(this, arguments); 
    var self = this; 

    if(this.get('lastScroll')){ 
     Ember.run.next(function(){ 
     Ember.$(window).scrollTop(self.get('lastScroll')); 
     }); 
    } else { 
     Ember.$(window).scrollTop(0); 
    } 
    }, 

    actions: { 
    willTransition: function() { 
     this._super.apply(this, arguments); 
     this.set('lastScroll', Ember.$(window).scrollTop()); 
    } 
    } 
}); 

Note cũng rằng đây vẫn đập vào mắt tôi như một giải pháp phần cho vấn đề ở chỗ nó không thiết lập lại cuộn trên tất cả các liên kết nhấp chuột (trái ngược với điều hướng trình duyệt/thay đổi lịch sử). Nó làm như vậy trên nhấp chuột liên kết đầu tiên tải tuyến đường, nhưng tất cả các nhấp chuột liên kết tiếp theo đến tuyến đường đó sẽ tải vị trí cuộn trước đó, do đó không nhận ra hành động dự định của người dùng để tải tuyến đường mà không tham chiếu đến hành vi xem trước đó của nó (aka với một vị trí cuộn thiết lập lại).

1

Cài đặt tiện ích ember này ember-router-scroll để đặt lại cuộn bằng khả năng khôi phục lịch sử cuộn. Nó sử dụng API HistoryLocation của các trình duyệt để nó hoạt động ngay ngoài hộp.

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