[英]angular ui-router refresh only one part of the page, need multiple views?
[英]Multiple views on one page with history in AngularJS using Angular UI Router
在我的AngularJS應用中,我有一個關於頁面,其中包含幾個小節。 所有這些小節都在同一頁面上,並且是同一模板的一部分。 但是,我想通過它自己的URL訪問每個部分,如果匹配,它將向下滾動到正確的部分。
我已經將狀態設置為:
.state('about', {
url: "/about",
templateUrl: "partials/about.html",
})
.state('about.team', {
url: "/about/team",
templateUrl: "partials/about.html"
})
.state('about.office', {
url: "/about/office",
templateUrl: "partials/about.html"
})
.state('about.other', {
url: "/about/other",
templateUrl: "partials/about.html"
});
在About頁面上,我有一個類似的菜單:
<div class="menu">
<a ui-sref-active="selected"
ui-sref="about.team">The Team</a>
<a ui-sref-active="selected"
ui-sref="about.office">The Office</a>
<a ui-sref-active="selected"
ui-sref="about.other">Other</a>
</div>
此菜單固定在底部,當用戶單擊鏈接或通過地址欄直接訪問URL時,應滾動到該部分(在需要匹配的URL上進行更新)。
但是我不確定如何做到這一點(通過Angular)。 總結一下:
該頁面的HTML看起來像: http : //pastebin.com/Q60FWtL7
您可以在此處查看該應用程序: http : //dev.driz.co.uk/AngularPage/app/#/about
有關類似示例( https://devart.withgoogle.com/#/about/your-opportunity )的示例,您可以看到頁面加載后,它會根據URL向下滾動到正確的部分。不要使用哈希,而是使用ACTUAL網址。
您可以在創建可觸發點擊滾動的指令時嘗試這種方法。 您可以將此指令作為屬性添加到鏈接。 sref屬性將是目標div的ID。
app.directive('scrollTo', function() {
return {
link: function(scope, element, attrs) {
element.bind('click', function() {
var divPosition = $(attrs.sRef).offset();
$('html, body').animate({
scrollTop: divPosition.top
}, "slow");
});
}
};
});
ui-router對狀態對象的簽名沒有限制,因此您只需添加一個屬性即可:
.state('about.office', {
url: "/about/office"
,templateUrl: "partials/about.html"
,scrollToId = "divAboutOffice";
})
這樣,當您注入$ state服務時,控制器就可以訪問此數據。
$('html, body').animate({
scrollTop: $($state.current.scrollToId).offset().top
}, "slow");
假設您在HTML中添加了id="divAboutOffice"
。 (並且假設我的jQuery引用是正確的;我不使用jquery,所以我不確定。)根據您的需要,您可以將animate()
包裝在$on()
用於以下事件之一: $locationChangeSuccess)
, $routeChangeSuccess
或$stateChangeSuccess
還:您不必像我一樣使用“ id”-如果您確實想按屬性搜索元素,則可以利用現有的ui-sref
。 在您的示例中,看起來與$state.current.name
匹配
我將使用window.scrollTo或jquery scrollTo插件創建scrollTo指令。
示例:使用window.scrollTo 滾動到給定項目的Angular指令
jQuery scrollTo插件:
https://github.com/flesler/jquery.localScroll
https://github.com/flesler/jquery.scrollTo
在頁面加載中,您滾動到由標簽或任何其他url參數定義的視圖。 例如:www.sample.com#aboutUs或www.samplecom?view = aboutUs
在滾動時,我應該:
1. bind to "scroll" events,
2. compare if I reached the position of each headers, using "element.offset().top"
(在將標題設置為指令后。(我應將標題設置為指令,檢查如何從ngtutorial.com/learn/scope生成目錄)
3. update location.url()
在加載時(我更喜歡使用標簽,因為我可以只使用$ anchorScroll()或.when()),無論如何,在加載時進行更新的示例是:
1. http://ngtutorial.com/guide.html#/learn-filter.html
2. http://ngtutorial.com/learn/route.html#/_tblcontents_5
如果您不喜歡主題標簽,則可以解析location.url()
我在自己的應用程序中使用https://github.com/durated/angular-scroll進行滾動控制(和滾動間諜工作),而不是使用locationHash。 我自己沒有嘗試過此解決方案,但我認為它可以工作。
您需要在重要的div上聲明某種項目ID(作為您滾動到的位置)。
然后,您可以使用url / about /:locale聲明狀態“ about.stately”(在ui路由器state中,Param不必為整數)。 然后在控制器中大約。狀態,您可以(從角度滾動自述文件中)執行以下操作:
var someElement = angular.element(document.getElementById('some-id'));
$document.scrollToElement(someElement, offset, duration);
根據控制器中的$ stateParams.locale選擇要滾動到的元素。 請注意,直到所有子指令和所有內容加載完畢后,您可能需要$ evalAsync才能使其正常工作。 但是,我認為這就是要點。
這是我目前所嘗試的:
var scrolled = false;
var listenToScroll = false;
$('.subsection').each(function(i) {
var position = $(this).position();
$(this).scrollspy({
min: position.top,
max: position.top + $(this).outerHeight(),
onEnter: function(element, position) {
if(element.id){
if(listenToScroll) {
scrolled = true;
$state.transitionTo('about.'+element.id);
}
} else {
if(listenToScroll) {
scrolled = true;
$state.transitionTo('about');
}
}
}
});
});
$scope.startListenToScroll = function() {
listenToScroll = true;
}
$scope.stopListenToScroll = function(){
listenToScroll = false;
}
$scope.$on('$stateChangeStart', function(){
$scope.stopListenToScroll();
});
$scope.$on('$stateChangeSuccess', function(){
console.log(scrolled);
if( !scrolled ) {
var link = $state.current.name.split('.');
if(link.length>1){
var divPosition = $( '#' + link[1] ).offset();
$('body').stop(true,true).animate({ scrollTop: divPosition.top }, "fast", function(){
$scope.startListenToScroll();
scrolled = false;
});
} else {
$('body').stop(true,true).animate({ scrollTop: 0 }, "fast", function(){
$scope.startListenToScroll();
scrolled = false;
});
}
} else {
$scope.startListenToScroll();
scrolled = false;
}
});
如您所見,我聽stateChangeSuccess而不是點擊! 這樣,無論鈎子是由鏈接還是由瀏覽器歷史記錄按鈕調用的,我都會陷入任何狀態更改,並根據需要執行滾動。
我會在開始更改開始后立即關閉scrollspy,以便滾動動畫不會調用其他狀態更改(因為您可能會通過其他部分進行滾動,從而創建偽造的歷史記錄條目)。 動畫完成后再將其重新打開,這樣我就可以再次收聽滾動事件。
stateChangeSuccess在頁面加載時觸發,因此它可以處理任何URL粘貼。
我有一個名為scrolled
的變量,因此我可以跟蹤狀態更改是否由用戶滾動引起。 這是因為當用戶滾動它們時,我不需要為scrollTop設置動畫。
有什么想法嗎?
您需要做的是在ui-router之外的頁面頂部創建一個指令,該指令可以監視狀態,然后根據右錨點滾動。 然后,您無需使用templateUrls,因為您要實現的是某種平滑。
// get the current path
var x=$location.path();
// say x='about/team'
//read the last tag and set scrollTo to the top offset of desired div
if(lasttag(x)==team){
scroll to top offset of TEAM div;
}
else if(lasttag(x)==office){
scroll to top offset of OFFICE div;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.