URL.jsまたはリンク処理javascriptのフレンド

画像



こんにちは、ハブラビテスさん!



今日、クライアント側で、サーバーと「対話」する機能なしに、GETパラメーターとURL全体をクライアント側で生成するタスクに直面しました。 すぐに予約をして、この記事を書く直前にこの投稿について知りました。最初に執筆を終えてから検索に頼ったので、その投稿は私のものと同じではないからです。



要するに。



挑戦と問題



問題は、上記で引用した投稿と同じです。



自分のために設定したタスク:





IE <9はこれを行う方法を知らないため、クロスブラウザー互換性のために、 prototype.__defineGetter__



またはprototype.__defineSetter__



を使用せずに、純粋なJavaScriptでprototype.__defineSetter__



ました。 この投稿でゲッター/セッターの詳細をご覧ください。



興味のある方-私たちが座って、既製のソリューションを必要とする人-あなたは投稿の終わりに歓迎されています、ダウンロードリンクがあります。



さあ始めましょう! 早く座ります-早く出発します。





コンストラクター



コンストラクターコード
 var URL = function( param, param2 ){ param = param || false; param2 = ( param2 === false ) ? false : true; this.urlEncode = param2; this.data = { scheme: false, user: false, pass: false, host: false, port: false, path: false, query: false, params: {}, fragment: false }; if( typeof(param) == 'string' ){ this.url = param; this.parse(); } else if ( typeof(param) == 'object' ){ for(var key in param){ if( this.data.hasOwnProperty( key ) ){ if( param[ key ] || ( key == 'params' && typeof(param.params) == 'object' ) ) this.data[ key ] = param[ key ]; } } this.update(); } }
      
      







詳細






解析



既存のURLを解析する必要があります。これはRegExp



ます。 いいえ、もちろんstr.split()



ですべてを処理できますが、これは、私には思えるが、特別な種類のフェティシズムです。

 regExp = /^(?:([a-z0-9_\-\.]+):\/\/)*(?:([a-z0-9_\-\.]+)(?:\:)*([a-z0-9_\-\.]+)*\@)*([a-z0-9][a-z0-9_\-\.]+)(?:\:([\d]+))*(?:\/([^?#]*))*(?:\?([^?#]*))*(?:\#([^?#]*))*/gi;
      
      





そして部分的に
  • (?:([a-z0-9_\-\.]+):\/\/)*



    - ウィキペディアによると、スキームは://



    ように見えます://



    ここで、 -



    _



    両方があります。 普遍性のために、インストール済み*すなわち スキームが示されていない場合があります。
  • (?:([a-z0-9_\-\.]+)(?:\:)*([a-z0-9_\-\.]+)*\@)*



    -ユーザー:パスワード、パスワードなしユーザー名はありませんが、パスワードのないユーザー名があります。
  • ([a-z0-9][a-z0-9_\-\.]+)



    -ホスト、私の知る限り、ドメイン名は文字/数字で始まり、その後-および_で始まり、さらに進むことができます。 さらに、6文字より短いドメイン名はありませんが、リンクはイントラネットワークにすることもできます。イントラネットワークでは、ホスト名を好きなように使用して、1つ以上の文字を入力します。
  • (?:\:([\d]+))*



    -PORT、このパラメーターはオプションです::および数字
  • (?:\/([^?#]*))*



    -PATH、ファイルへのパス、一般に、理論的には、これは任意の数の文字ですが、カットされますか? #GETパラメータまたはパスへのフラグメントポインターを解析しないようにします。 パスが示されていない可能性があります。
  • (?:\?([^?#]*))*



    -クエリ、GETパラメータのセット、キー=値のペア。 省略することもできます。
  • (?:\#([^?#]*))*



    -フラグメント、フラグメント化されたポインタ。 誰も知らない場合、/ /index.html#fragment



    id="fragment"



    はブラウザにid="fragment"



    DOM要素までスクロールするよう指示します




もちろん、RegExpを理解するすべての言語で動作します。 使用して、恥ずかしがらないでください。



パーサー
  parse: function(){ this.res = /^(?:([a-z0-9_\-\.]+):\/\/)*(?:([a-z0-9_\-\.]+)(?:\:)*([a-z0-9_\-\.]+)*\@)*([a-z0-9][a-z0-9_\-\.]+)(?:\:([\d]+))*(?:\/([^?#]*))*(?:\?([^?#]*))*(?:\#([^?#]*))*/gi.exec( this.url ); this.data.scheme = this.res[ 1 ] || false; this.data.user = this.res[ 2 ] || false; this.data.pass = this.res[ 3 ] || false; this.data.host = this.res[ 4 ] || false; this.data.port = this.res[ 5 ] || false; this.data.path = this.res[ 6 ] || false; this.data.query = this.res[ 7 ] || false; this.data.fragment = this.res[ 8 ] || false; if( this.data.query ){ this.parts = this.data.query.split( '&' ); for( var i = 0; i < this.parts.length; i++ ){ param = this.parts[ i ].split( '=' ); this.data.params[ param[ 0 ] ] = decodeURIComponent( param[ 1 ] ); } } delete this.res; delete this.parts; }
      
      







複雑なことは何もありません。上記のようにregExp



を分割し、 this.data



ハッシュにデータを保存します

前に言及した場合をregExp



、urlのGETパラメーターを使用した便利な作業が必要です。したがって、split(この場合はsplit()はregExp



よりも「安い」)を使用してクエリを中断し、同じ悪名高いハッシュに保存します。 GETパラメータはurlencodedであるため、decodeURIComponentの使用に注意する価値があります。



オプション1.「美」による



ゲッター/セッター



パラメータの読み取り/変更に関する便利な作業のために、JSウェイゲッターとセッターを選択することにしました。 Teは、プロパティの名前によるメソッドであり、メソッドがパラメーターで呼び出された場合はセッターであり、パラメーターがない場合はゲッターです。

メモリ内でメソッドの冗長インスタンスを生成しないように、 URL.prototype = { }



を介してURL.prototype = { }



します。

例として1つ例を挙げます。これらは類似しているためです。

  scheme: function( param ){ if( typeof( param ) != 'undefined' ){ this.data.scheme = param; return this.update(); } else { return this.data.scheme ? this.data.scheme : false; } }
      
      





値が変更された場合、 String



返されませんが、 Object



セッターチェーンを記述できるように行われます。

 var url = new URL(); url.scheme('https').host('example.com').path('index.php').params({'p1':"v1", 'p2':"2"}).url; // : https://example.com/index.php?p1=v1&p2=%D0%B22
      
      







params



プロパティのゲッター/セッターについて個別に説明しましょう

  params: function( param1, param2 ){ if( typeof( param1 ) != 'undefined' ){ if( typeof( param1 ) == 'string' ){ if( typeof( param2 ) != 'undefined' && ( param2 == '' || param2 === false ) ){ if( this.data.params.hasOwnProperty( param1 ) ){ delete this.data.params[ param1 ]; } } else if( typeof( param2 ) != 'undefined' ){ this.data.params[ param1 ] = param2; } else{ return this.data.params[ param1 ] ? this.data.params[ param1 ] : false; } } else if( typeof( param1 ) == 'object' ){ for( var key in param1 ){ if( typeof( param1[ key ] ) != 'undefined' && ( param1[ key ] == '' || param1[ key ] === false ) ){ if( this.data.params.hasOwnProperty( key ) ) delete this.data.params[ key ]; } else{ this.data.params[ key ] = param1[ key ]; } } } return this.update(); } else { return this.data.params ? this.data.params : false; } }
      
      





ご覧のとおり、両方のパラメーターはオプションです。

そして、私が言ったように-私は自分自身に目標を設定しました-GETパラメータを使用することの利便性、つまり次のことができるようになる必要があることを意味します。



単一のパラメーターおよびパラメーターのグループとして。



したがって、構文は次のようになります。





URLを元に戻す



お気づきのように、 this.update()



this.update()



で呼び出され、2つの機能を実行します。



コレクターコード
  update: function(){ this.data.query = ''; for( var key in this.data.params ){ this.data.query += this.urlEncode ? key+'='+encodeURIComponent( this.data.params[ key ] )+'&' : key+'='+this.data.params[ key ]+'&'; } if( this.data.query ) this.data.query = this.data.query.slice( 0, -1 ); this.url = ''; this.url += this.data.scheme ? this.data.scheme+'://' : ''; this.url += this.data.user ? this.data.user+':' : ''; this.url += this.data.pass ? this.data.pass+'@' : ''; this.url += this.data.host ? this.data.host+'/' : ''; this.url += this.data.path ? this.data.path : ''; this.url += this.data.query ? '?'+this.data.query : ''; this.url += this.data.fragment ? '#'+this.data.fragment : ''; return this; }
      
      







GETパラメーターをアセンブルするときに、パラメーター値がエスケープシーケンスに変換されることに注意してください。

最初:そうです。

第二に 、GETパラメーターを使用してユーザーが入力したデータを転送すると、ユーザーが挿入したアンパサンドによってキーと値のシーケンスが破壊され、すべてがタルタルになります。



さて、鼻からまっすぐに、あなたはurlencodedラインを必要としない場合-あなたは2つのオプションがあります:

コンストラクターに2番目のパラメーターを渡すfalse

  1. プロパティURL.urlEncode=false;



    手動で設定しますURL.urlEncode=false;



  2. メソッドURL.update();



    呼び出しURL.update();





 test = new URL({"path":"index.php", "params":{"param1":"value1", "param2":" &"}}, false); test.url; //index.php?param1=value1¶m2= & test2 = new URL({"path":"index.php", "params":{"param1":"value1", "param2":" &"}}); test2.url; //index.php?param1=value1¶m2=%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D0%B0%26 test2.urlEncode=false; test2.update().url; //index.php?param1=value1¶m2= &
      
      







まあ、それを便利にするために-生成されたリンクをたどる方法:

  go: function(){ if(!this.data.scheme && this.data.host) this.data.scheme = 'http'; window.location.href = this.update().url; }
      
      





ご覧のとおり、スキームが指定されていないが、ホストが指定されている場合、 http



スキームが自動的に最も一般的なものとして置換されます。

次に、リンクが更新され、クリックされます。



文字列オブジェクトの拡張



理論的には、これで終了する可能性があります。 しかし、オブジェクトのインスタンスを明示的に作成せずに文字列変数を直接操作する方が便利だと思われました(ただし、奇妙に聞こえますが、JSにはクラスはありません)。



いつものように、1つの方法の例を示します。

 String.prototype.scheme = function( param ){ var url = new URL( this.valueOf() ); if( typeof( param ) != 'undefined' ){ url.scheme( param ); result = url.url; } else{ result = url.scheme(); } delete url; return result; }
      
      





一般に、コードはURLオブジェクトの対応するメソッドにパラメーターを渡すだけです。

しかし、URLオブジェクトを作成および削除し、毎回1つのアクションのみを呼び出すことは奇妙に思えるかもしれません。このアクションは、実行される変数の値を変更しません。

これは、 String



オブジェクトの最も重要な不便なところです;既存の変数の値を変更することはできません。 何もできません。 常に新しい変数を作成してください。 したがって、新しいオブジェクトが作成され、 String



型の変数String



返されるたびに。

チェーンはもちろんサポートされています:

 url = 'example.com'; url.scheme('https').path('index.php').params({'p1':"v1", 'p2':"2"}); // : https://example.com/index.php?p1=v1&p2=%D0%B22
      
      







オプション2.「風水による」



たとえば、以前のバージョンが使用中の「美しい」場合、このオプションは簡潔になります。 コードと使用の両方の面で。



ゲッター/セッター



そのため、この場合のゲッター/セッターは、すべて、つまり完全に1つになります。

  val: function( key, param, param2 ){ if( this.data.hasOwnProperty( key ) ){ if( typeof( param ) == 'undefined' ){ return this.data[ key ] ? this.data[ key ] : false; } else if( typeof( param ) != 'undefined' ){ if( key == 'params' ){ if( typeof( param ) == 'string' ){ if( typeof( param2 ) != 'undefined' ){ this.data[ key ][ param ] = param2; } else{ return this.data[ key ][ param ] ? this.data[ key ][ param ] : false; } } else if( typeof( param ) == 'object' ){ for( var keys in param ){ if( typeof( param[ keys ] ) != 'undefined' && ( param[ keys ] == '' || param[ keys ] === false ) ){ if( this.data[ key ].hasOwnProperty( keys ) ){ delete this.data[ key ][ keys ]; } } else{ this.data[ key ][ keys ] = param[ keys ]; } } } } else{ this.data[ key ] = param; } return this.update(); } } else return 'undefined'; }
      
      







文字列オブジェクトの拡張



状況はString



オブジェクトの拡張でも同じです。コードが少ないだけです。 このメソッドは、パラメーターをURL.val()にのみ転送します。



まとめ



したがって、出力には、URLを適切に処理する機会を提供するライブラリがあり、URLの個々の部分を解析するだけでなく、変更することもできます。 これは、私の意見では、GETパラメーターを操作するための非常に便利なツールは言うまでもありません。



アプローチの長所と短所


オプション1


長所:



短所:





オプション2


長所:



短所:





以下の両方のオプションのソースをダウンロードできます:[ オプション1 || オプション2 ]。 ファイルが1つしかないため、githubに拡散する理由はありません。

サポート:





そして、シムのために-私は私の休暇が私の投稿が誰かのためになることを心から願っています。

すべての良いコード、より多くの睡眠、そしてそのIEは人生を台無しにしません。



All Articles