質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.40%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

6788閲覧

pjaxで遷移後スクロール制御のスクリプトがおかしくなる

yamaotakuro

総合スコア13

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

1グッド

0クリップ

投稿2016/06/01 01:26

通常の読み込みではスクロール制御のスクリプトが問題なく動くのですが、
pjaxで遷移した後だと動かなくなります。

エラーログ:無し
jQueryバージョン:1.7.2

javascript

1scrollControl:function (){ 2 3 var keys = [32, 37, 38, 39, 40], wheelIter = 0; 4 5 function preventDefault(e) { 6 e = e || window.event; 7 if (e.preventDefault) 8 e.preventDefault(); 9 e.returnValue = false; 10 } 11 12 function keydown(e) { 13 for (var i = keys.length; i--;) { 14 if (e.keyCode === keys[i]) { 15 preventDefault(e); 16 return; 17 } 18 } 19 } 20 21 function touchmove(e) { 22 preventDefault(e); 23 } 24 25 function disable_scroll() { 26 window.onmousewheel = document.onmousewheel; 27 document.onkeydown = keydown; 28 document.body.ontouchmove = touchmove; 29 } 30 31 function enable_scroll() { 32 window.onmousewheel = document.onmousewheel = document.onkeydown = document.body.ontouchmove = null; 33 } 34 35 var docElem = window.document.documentElement, 36 scrollVal, 37 isRevealed, 38 noscroll, 39 isAnimating, 40 container = $( '#container' ), 41 trigger = $( '.pagedown' ); 42 43 function scrollY() { 44 return window.pageYOffset || docElem.scrollTop; 45 } 46 47 function scrollPage() { 48 scrollVal = scrollY(); 49 if( noscroll ) { 50 if( scrollVal < 0 ) return false; 51 window.scrollTo( 0, 0 ); 52 } 53 54 if( container.hasClass('notrans') ) { 55 container.removeClass( 'notrans' ); 56 return false; 57 } 58 59 if( isAnimating ) { 60 return false; 61 } 62 63 if( scrollVal <= 0 && isRevealed ) { 64 toggle(0); 65 } 66 else if( scrollVal > 0 && !isRevealed ){ 67 toggle(1); 68 } 69 } 70 71 function toggle( reveal ) { 72 isAnimating = true; 73 if( reveal ) { 74 container.addClass( 'is-move' ); 75 } 76 else { 77 noscroll = true; 78 disable_scroll(); 79 container.removeClass( 'is-move' ); 80 } 81 82 setTimeout( function() { 83 isRevealed = !isRevealed; 84 isAnimating = false; 85 if( reveal ) { 86 noscroll = false; 87 enable_scroll(); 88 } 89 }, 1200 ); 90 } 91 92 function menuShow(){ 93 $('.menu_trigger').on('click',function(){ 94 if(!$(this).hasClass('is-act')){ 95 if(!$('#container').hasClass('is-move')){ 96 disable_scroll(); 97 } 98 }else{ 99 enable_scroll(); 100 } 101 }); 102 } 103 104 menuShow(); 105 106 var pageScroll = scrollY(); 107 noscroll = pageScroll === 0; 108 109 disable_scroll(); 110 111 if( pageScroll ) { 112 isRevealed = true; 113 container.addClass( 'notrans' ); 114 container.addClass( 'is-move' ); 115 } 116 117 window.addEventListener( 'scroll', scrollPage ); 118 trigger.on('click',function(){ 119 toggle( 'reveal' ); 120 }); 121}

読み込みは
通常

javascript

1$(function(){});

pjax遷移後

javascript

1$(document).on('pjax:render', function() {});

で行っております。

console.logで確認するとpjax遷移後だとscrollY()の値が増えずに0に戻ってしまうので
そこが原因かと思ったのですが
なぜ戻ってしまうのかがわかりません。

ここの動きを参考にソースを改変したものになります。

http://tympanus.net/Development/ArticleIntroEffects/index.html

どなたか原因がわかる方がいればご教授お願いします。

kei344👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

開示されているコードがオブジェクトの一箇所だけなので断定はできませんが
scrollControlをpjax毎の呼び出すということですね?

scrollControlで登録した全イベントはpjaxで遷移した後も
明示的に削除しない限り残っているというということはお分かりでしょうか?

window.addEventListener( 'scroll', scrollPage );がpjaxの度に上書きされることを期待されているのでしょうが、重複して登録されています。(親にあたるメソッドを呼び出すと別のものとして判断される模様)
つまるところ、scroll時に呼び出されるイベントが重複しておかしなことになっている、ということです。(要するにメモリリークもしています)
scrollPage()関数の条件分岐のところが重複して呼び出されると妙な挙動を起こすはずです。

pjaxのareaがどの要素に指定されているかにもよりますが
trigger(と必要であればcontainer)の部分をscrollControlメソッド外部から変更できるようにして
pjax:renderの際に呼び出すのはtrigger(+container)を遷移後の要素に置き換える処理のみにしておくとよいのではないでしょうか。(本当はもっとメソッドを小分けにしたほうが良いと思います。)

#####ポイントとして
pjaxでコンテンツを切り替えていく作りにしたい際は、リロードが発生しない為、イベントの状態管理が必要になります
これはpjax関連の記事を見ていて誰も触れてないので、すこぶる不可思議なのですが
言うなればSPAを作る時と同じになるので、通常のサイトやページの作り方そのままを流用しようとすると、メモリリークのオンパレードで、コンテンツを切り替える毎にどんどんページ動作が重くなる…なんてことも少なくありません。

また、pjaxを使用する際、下手にネイティブのコードとjQueryのコードを混ぜないほうがお勧めです。
ネイティブのJavaScriptで付与したイベントはjQueryで削除できません。
その逆も然りです。
その為、思わぬところでメモリリークを発生させることになるので、可能な限りどちらかに揃えるほうが無難でしょう。
pjaxそのものがjQueryに依存しているので、個人的には、イベント処理もjQueryで行っておいたほうが事故が少ないと思います。

投稿2016/06/03 14:14

manabufukai

総合スコア700

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamaotakuro

2016/06/06 02:02

遷移時にスクロールイベントを削除することで正しい挙動を実現できました。 恥ずかしながら今までメモリリークを意識してなかったので今後意識していこうと思います。 pjaxを使った遷移のアドバイスまでいただき本当にありがとうございました。
manabufukai

2016/06/07 12:01

お返事が遅くなり申し訳ございませんでした。 今のコードをなるべく触らずに解消するにはその方法が妥当でしょう。 今やJavaScriptでメモリリークのことを考えなければならないケースというのはそこまで多くないので無理もないと思います。(普通ならページ遷移した時点でリフレッシュされる為) また、jQueryとJavaScriptの併用によるメモリリークに関してはちょっとググってみていただくと結構いろいろ出てくると思いますので、そちらも合わせて是非。 慣れきたら是非、メソッドを小分けにした上で updateメソッドのようなものを作成して、回答で挙げた対象要素の更新だけを行わせる、といったコードも考えてみてください。 pjax前後の処理が大幅に減らせるはずなので高速な動作感も高まると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.40%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問