pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

我應該使用哪種 jQuery 插件設計模式?

Which jQuery plugin design pattern should I use?(我應該使用哪種 jQuery 插件設計模式?)
本文介紹了我應該使用哪種 jQuery 插件設計模式?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我需要構建一個 jQuery 插件,它會為每個選擇器 ID 返回一個實例.該插件應該并且只會用于具有 id 的元素(不可能使用匹配許多元素的選擇器),因此應該像這樣使用它:

I need to build a jQuery plugin that would return a single instance per selector id. The plugin should and will only be used on elements with id (not possible to use selector that matches many elements), so it should be used like this:

$('#element-id').myPlugin(options);

  • 我需要能夠為插件提供一些私有方法以及一些公共方法.我可以做到這一點,但我的主要問題是每次調用 $('#element-id').myPlugin() 時我都想獲得相同的實例.
  • 我想要一些代碼,只在第一次為給定 ID(構造)初始化插件時執行.
  • options 參數應該第一次提供,對于構造,之后我不希望構造被執行,這樣我就可以像 $('#element 一樣訪問插件-id').myPlugin()
  • 插件應該能夠在同一頁面上處理多個元素(通常最多 2 個)(但每個元素都需要自己的配置,再次重申 - 它們將由 ID 初始化,而不是通用的類選擇器例子).
  • 上面的語法只是一個例子——我愿意接受任何關于如何實現該模式的建議
    • I need to be able to have few private methods for the plugin as well as few public methods. I can achieve that but my main issue is that I want to get the very same instance every time I call $('#element-id').myPlugin().
    • And I want to have some code that should be executed only the first time the plugin is initialized for a given ID (construct).
    • The options parameter should be supplied the first time, for the construct, after that I do not want the construct to be executed, so that I can access the plugin just like $('#element-id').myPlugin()
    • The plugin should be able to work with multiple elements (usually up to 2) on the same page (but each and every one of them will need own config, again - they will be initialized by ID, not common class selector for example).
    • The above syntax is just for example - I'm open for any suggestions on how to achieve that pattern
    • 我在其他語言方面有相當多的 OOP 經驗,但對 javascript 的了解有限,我真的很困惑如何正確地做到這一點.

      I have quite some OOP experience with other language, but limited knowledge of javascript and I'm really confused on how do it right.

      編輯

      詳細說明 - 這個插件是一個 GoogleMaps v3 API 包裝器(幫助器),可以幫助我擺脫代碼重復,因為我在很多地方使用谷歌地圖,通常帶有標記.這是當前的庫(刪除了很??多代碼,只剩下最重要的方法):

      To elaborate - this plugin is a GoogleMaps v3 API wrapper (helper) to help me get rid of code duplication as I use google maps on many places, usually with markers. This is the current library (lots of code removed, just most important methods are left to see):

      ;(function($) {
          /**
           * csGoogleMapsHelper set function.
           * @param options map settings for the google maps helper. Available options are as follows:
           * - mapTypeId: constant, http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeId
           * - mapTypeControlPosition: constant, http://code.google.com/apis/maps/documentation/javascript/reference.html#ControlPosition
           * - mapTypeControlStyle: constant, http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeControlStyle
           * - mapCenterLatitude: decimal, -180 to +180 latitude of the map initial center
           * - mapCenterLongitude: decimal, -90 to +90 latitude of the map initial center
           * - mapDefaultZoomLevel: integer, map zoom level
           * 
           * - clusterEnabled: bool
           * - clusterMaxZoom: integer, beyond this zoom level there will be no clustering
           */
          $.fn.csGoogleMapsHelper = function(options) {
              var id = $(this).attr('id');
              var settings = $.extend(true, $.fn.csGoogleMapsHelper.defaults, options);
      
              $.fn.csGoogleMapsHelper.settings[id] = settings;
      
              var mapOptions = {
                  mapTypeId: settings.mapTypeId,
                  center: new google.maps.LatLng(settings.mapCenterLatitude, settings.mapCenterLongitude),
                  zoom: settings.mapDefaultZoomLevel,
                  mapTypeControlOptions: {
                      position: settings.mapTypeControlPosition,
                      style: settings.mapTypeControlStyle
                  }
              };
      
              $.fn.csGoogleMapsHelper.map[id] = new google.maps.Map(document.getElementById(id), mapOptions);
          };
      
          /**
           * 
           * 
           * @param options settings object for the marker, available settings:
           * 
           * - VenueID: int
           * - VenueLatitude: decimal
           * - VenueLongitude: decimal
           * - VenueMapIconImg: optional, url to icon img
           * - VenueMapIconWidth: int, icon img width in pixels
           * - VenueMapIconHeight: int, icon img height in pixels
           * 
           * - title: string, marker title
           * - draggable: bool
           * 
           */
          $.fn.csGoogleMapsHelper.createMarker = function(id, options, pushToMarkersArray) {
              var settings = $.fn.csGoogleMapsHelper.settings[id];
      
              markerOptions = {
                      map:  $.fn.csGoogleMapsHelper.map[id],
                      position: options.position || new google.maps.LatLng(options.VenueLatitude, options.VenueLongitude),
                      title: options.title,
                      VenueID: options.VenueID,
                      draggable: options.draggable
              };
      
              if (options.VenueMapIconImg)
                  markerOptions.icon = new google.maps.MarkerImage(options.VenueMapIconImg, new google.maps.Size(options.VenueMapIconWidth, options.VenueMapIconHeight));
      
              var marker = new google.maps.Marker(markerOptions);
              // lets have the VenueID as marker property
              if (!marker.VenueID)
                  marker.VenueID = null;
      
              google.maps.event.addListener(marker, 'click', function() {
                   $.fn.csGoogleMapsHelper.loadMarkerInfoWindowContent(id, this);
              });
      
              if (pushToMarkersArray) {
                  // let's collect the markers as array in order to be loop them and set event handlers and other common stuff
                   $.fn.csGoogleMapsHelper.markers.push(marker);
              }
      
              return marker;
          };
      
          // this loads the marker info window content with ajax
          $.fn.csGoogleMapsHelper.loadMarkerInfoWindowContent = function(id, marker) {
              var settings = $.fn.csGoogleMapsHelper.settings[id];
              var infoWindowContent = null;
      
              if (!marker.infoWindow) {
                  $.ajax({
                      async: false, 
                      type: 'GET', 
                      url: settings.mapMarkersInfoWindowAjaxUrl, 
                      data: { 'VenueID': marker.VenueID },
                      success: function(data) {
                          var infoWindowContent = data;
                          infoWindowOptions = { content: infoWindowContent };
                          marker.infoWindow = new google.maps.InfoWindow(infoWindowOptions);
                      }
                  });
              }
      
              // close the existing opened info window on the map (if such)
              if ($.fn.csGoogleMapsHelper.infoWindow)
                  $.fn.csGoogleMapsHelper.infoWindow.close();
      
              if (marker.infoWindow) {
                  $.fn.csGoogleMapsHelper.infoWindow = marker.infoWindow;
                  marker.infoWindow.open(marker.map, marker);
              }
          };
      
          $.fn.csGoogleMapsHelper.finalize = function(id) {
              var settings = $.fn.csGoogleMapsHelper.settings[id];
              if (settings.clusterEnabled) {
                  var clusterOptions = {
                      cluster: true,
                      maxZoom: settings.clusterMaxZoom
                  };
      
                  $.fn.csGoogleMapsHelper.showClustered(id, clusterOptions);
      
                  var venue = $.fn.csGoogleMapsHelper.findMarkerByVenueId(settings.selectedVenueId);
                  if (venue) {
                      google.maps.event.trigger(venue, 'click');
                  }
              }
      
              $.fn.csGoogleMapsHelper.setVenueEvents(id);
          };
      
          // set the common click event to all the venues
          $.fn.csGoogleMapsHelper.setVenueEvents = function(id) {
              for (var i in $.fn.csGoogleMapsHelper.markers) {
                  google.maps.event.addListener($.fn.csGoogleMapsHelper.markers[i], 'click', function(event){
                      $.fn.csGoogleMapsHelper.setVenueInput(id, this);
                  });
              }
          };
      
          // show the clustering (grouping of markers)
          $.fn.csGoogleMapsHelper.showClustered = function(id, options) {
              // show clustered
              var clustered = new MarkerClusterer($.fn.csGoogleMapsHelper.map[id], $.fn.csGoogleMapsHelper.markers, options);
              return clustered;
          };
      
          $.fn.csGoogleMapsHelper.settings = {};
          $.fn.csGoogleMapsHelper.map = {};
          $.fn.csGoogleMapsHelper.infoWindow = null;
          $.fn.csGoogleMapsHelper.markers = [];
      })(jQuery);
      

      它的用法看起來像這樣(實際上并不完全像這樣,因為有一個 PHP 包裝器可以通過一次調用來自動化它,但基本上):

      It's usage looks like this (not actually exactly like this, because there is a PHP wrapper to automate it with one call, but basically):

      $js = "$('#$id').csGoogleMapsHelper($jsOptions);
      ";
      
      if ($this->venues !== null) {
          foreach ($this->venues as $row) {
              $data = GoogleMapsHelper::getVenueMarkerOptionsJs($row);
              $js .= "$.fn.csGoogleMapsHelper.createMarker('$id', $data, true);
      ";
          }
      }
      
      $js .= "$.fn.csGoogleMapsHelper.finalize('$id');
      ";
      echo $js;
      

      上述實現的問題是我不喜歡為設置"和地圖"保留哈希映射

      The problems of the above implementation are that I don't like to keep a hash-map for "settings" and "maps"

      $id 是初始化地圖的 DIV 元素 ID.它用作 .map 中的鍵,并且 .settings 具有地圖,其中我保存頁面上每個已初始化的此類 GoogleMaps 的設置和 GoogleMaps MapObject 實例.PHP 代碼中的 $jsOptions$data 是 JSON 對象.

      The $id is the DIV element ID where the map is initialized. It's used as a key in the .map and .settings has maps where I hold the settings and GoogleMaps MapObject instance for each initialized such GoogleMaps on the page. The $jsOptions and $data from the PHP code are JSON objects.

      現在我需要能夠創建一個 GoogleMapsHelper 實例來保存它自己的設置和 GoogleMaps 地圖對象,以便在我對某個元素(通過它的 ID)初始化它之后,我可以重用該實例.但是如果我在頁面上的 N 個元素上初始化它,每個元素都應該有自己的配置、地圖對象等.

      Now I need to be able to create a GoogleMapsHelper instance that holds its own settings and GoogleMaps map object so that after I initialize it on certain element (by its ID), I can reuse that instance. But if I initialize it on N elements on the page, each and every of them should have own configuration, map object, etc.

      我不堅持這是作為一個 jQuery 插件實現的!我堅持認為它是靈活和可擴展的,因為我將在一個大型項目中使用它,其中包含十多個當前計劃的不同屏幕幾個月后就會被使用,改變它的使用界面將是對整個項目進行重構的一場噩夢.

      I do not insist that this is implemented as a jQuery plugin! I insist that it's flexible and extendable, because I will be using it in a large project with over dozen currently planned different screens where it will be used so in few months, changing it's usage interface would be a nightmare to refactor on the whole project.

      我會為此添加賞金.

      推薦答案

      當你說通過 $('#element').myPlugin() 獲取"實例時,我假設你的意思是:

      When you say "get" the instance via $('#element').myPlugin() I assume you mean something like:

      var instance = $('#element').myPlugin();
      instance.myMethod();
      

      一開始這似乎是個好主意,但它被認為是擴展 jQuery 原型的不好做法,因為您破壞了 jQuery 實例鏈.

      This might seem to be a good idea at first, but it’s considered bad practice for extending the jQuery prototype, since you break the jQuery instance chain.

      另一種方便的方法是將實例保存在 $.data 對象中,因此您只需初始化插件一次,然后您可以隨時使用 DOM 元素獲取實例作為參考,f.ex:

      Another handy way to do this is to save the instance in the $.data object, so you just initialize the plugin once, then you can fetch the instance at any time with just the DOM element as a reference, f.ex:

      $('#element').myPlugin();
      $('#element').data('myplugin').myMethod();
      

      這是我用來在 JavaScript 和 jQuery 中維護類類結構的模式(包括注釋,希望你能關注):

      Here is a pattern I use to maintain a class-like structure in JavaScript and jQuery (comments included, hope you can follow):

      (function($) {
      
          // the constructor
          var MyClass = function( node, options ) {
      
              // node is the target
              this.node = node;
      
              // options is the options passed from jQuery
              this.options = $.extend({
      
                  // default options here
                  id: 0
      
              }, options);
      
          };
      
          // A singleton for private stuff
          var Private = {
      
              increaseId: function( val ) {
      
                  // private method, no access to instance
                  // use a bridge or bring it as an argument
                  this.options.id += val;
              }
          };
      
          // public methods
          MyClass.prototype = {
      
              // bring back constructor
              constructor: MyClass,
      
              // not necessary, just my preference.
              // a simple bridge to the Private singleton
              Private: function( /* fn, arguments */ ) {
      
                  var args = Array.prototype.slice.call( arguments ),
                      fn = args.shift();
      
                  if ( typeof Private[ fn ] == 'function' ) {
                      Private[ fn ].apply( this, args );
                  }
              },
      
              // public method, access to instance via this
              increaseId: function( val ) {
      
                  alert( this.options.id );
      
                  // call a private method via the bridge
                  this.Private( 'increaseId', val );
      
                  alert( this.options.id );
      
                  // return the instance for class chaining
                  return this;
      
              },
      
              // another public method that adds a class to the node
              applyIdAsClass: function() {
      
                  this.node.className = 'id' + this.options.id;
      
                  return this;
      
              }
          };
      
      
          // the jQuery prototype
          $.fn.myClass = function( options ) {
      
              // loop though elements and return the jQuery instance
              return this.each( function() {
      
                  // initialize and insert instance into $.data
                  $(this).data('myclass', new MyClass( this, options ) );
              });
          };
      
      }( jQuery ));
      

      現在,你可以這樣做了:

      Now, you can do:

      $('div').myClass();
      

      這將為找到的每個 div 添加一個新實例,并將其保存在 $.data 中.現在,要檢索某個實例的應用方法,您可以這樣做:

      This will add a new instance for each div found, and save it inside $.data. Now, to retrive a certain instance an apply methods, you can do:

      $('div').eq(1).data('myclass').increaseId(3).applyIdAsClass();
      

      這是我多次使用的模式,非常適合我的需求.

      This is a pattern I have used many times that works great for my needs.

      您還可以通過添加 window.MyClass = MyClass 公開該類,以便在沒有 jQuery 原型的情況下使用它.這允許使用以下語法:

      You can also expose the class so you can use it without the jQuery prototyp by adding window.MyClass = MyClass. This allows the following syntax:

      var instance = new MyClass( document.getElementById('element'), {
          id: 5
      });
      instance.increaseId(5);
      alert( instance.options.id ); // yields 10
      

      這篇關于我應該使用哪種 jQuery 插件設計模式?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

      【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

jQuery/JavaScript Library for avatar creation?(用于創建頭像的 jQuery/JavaScript 庫?)
How to do following mask input problem?(如何做以下掩碼輸入問題?)
Issues Setting Value/Label Using DropKick Javascript(使用 DropKick Javascript 設置值/標簽的問題)
how to unit-test private methods in jquery plugins?(如何對 jquery 插件中的私有方法進行單元測試?)
stellar.js - configuring offsets / aligning elements for a vertical scrolling website?(stellar.js - 為垂直滾動網站配置偏移量/對齊元素?)
jQuery masked input plugin. select all content when textbox receives focus(jQuery 屏蔽輸入插件.當文本框獲得焦點時選擇所有內容)
主站蜘蛛池模板: 讲师宝经纪-专业培训机构师资供应商_培训机构找讲师、培训师、讲师经纪就上讲师宝经纪 | 【直乐】河北石家庄脊柱侧弯医院_治疗椎间盘突出哪家医院好_骨科脊柱外科专业医院_治疗抽动症/关节病骨伤权威医院|排行-直乐矫形中医医院 | IIS7站长之家-站长工具-爱网站请使用IIS7站长综合查询工具,中国站长【WWW.IIS7.COM】 | 雷冲击高压发生器-水内冷直流高压发生器-串联谐振分压器-武汉特高压电力科技有限公司 | 衬氟旋塞阀-卡套旋塞阀-中升阀门首页 | 【化妆品备案】进口化妆品备案流程-深圳美尚美化妆品有限公司 | 合肥地磅_合肥数控切割机_安徽地磅厂家_合肥世佳电工设备有限公司 | 电子天平-华志电子天平厂家 | 档案密集柜_手动密集柜_智能密集柜_内蒙古档案密集柜-盛隆柜业内蒙古密集柜直销中心 | 网站制作优化_网站SEO推广解决方案-无锡首宸信息科技公司 | 杭州荣奥家具有限公司-浙江办公家具,杭州办公家具厂 | 细石混凝土泵_厂家_价格-烟台九达机械有限公司 | 纸张环压仪-纸张平滑度仪-杭州纸邦自动化技术有限公司 | 中山市派格家具有限公司【官网】 | VOC检测仪-甲醛检测仪-气体报警器-气体检测仪厂家-深恒安科技有限公司 | 地磅-电子地磅维修-电子吊秤-汽车衡-无人值守系统-公路治超-鹰牌衡器 | 沧州友城管业有限公司-内外涂塑钢管-大口径螺旋钢管-涂塑螺旋管-保温钢管生产厂家 | 宽带办理,电信宽带,移动宽带,联通宽带,电信宽带办理,移动宽带办理,联通宽带办理 | 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 防爆电机生产厂家,YBK3电动机,YBX3系列防爆电机,YBX4节防爆电机--河南省南洋防爆电机有限公司 | 北京易通慧公司从事北京网站优化,北京网络推广、网站建设一站式服务商-北京网站优化公司 | 东莞螺杆空压机_永磁变频空压机_节能空压机_空压机工厂批发_深圳螺杆空压机_广州螺杆空压机_东莞空压机_空压机批发_东莞空压机工厂批发_东莞市文颖设备科技有限公司 | 利浦顿蒸汽发生器厂家-电蒸汽发生器/燃气蒸汽发生器_湖北利浦顿热能科技有限公司官网 | 我爱古诗词_古诗词名句赏析学习平台 | 伊卡洛斯软装首页-电动窗帘,别墅窗帘,定制窗帘,江浙沪1000+别墅窗帘案例 | 除湿机|工业除湿机|抽湿器|大型地下室车间仓库吊顶防爆除湿机|抽湿烘干房|新风除湿机|调温/降温除湿机|恒温恒湿机|加湿机-杭州川田电器有限公司 | 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 | 上海防爆真空干燥箱-上海防爆冷库-上海防爆冷柜?-上海浦下防爆设备厂家? | 不锈钢散热器,冷却翅片管散热器厂家-无锡市烨晟化工装备科技有限公司 | 陕西华春网络科技股份有限公司 | 海鲜池-专注海鲜鱼缸、移动海鲜缸、饭店鱼缸设计定做-日晟水族厂家 | 识禅_对禅的了解,从这里开始 | 蓝米云-专注于高性价比香港/美国VPS云服务器及海外公益型免费虚拟主机 | 阿里巴巴诚信通温州、台州、宁波、嘉兴授权渠道商-浙江联欣科技提供阿里会员办理 | 连续油炸机,全自动油炸机,花生米油炸机-烟台茂源食品机械制造有限公司 | 振动筛-交叉筛-螺旋筛-滚轴筛-正弦筛-方形摇摆筛「新乡振动筛厂家」 | 乙炔气体报警装置|固定式氯化氢检测仪|河南驰诚电气百科 | 成都中天自动化控制技术有限公司 | 安徽免检低氮锅炉_合肥燃油锅炉_安徽蒸汽发生器_合肥燃气锅炉-合肥扬诺锅炉有限公司 | 风淋室生产厂家报价_传递窗|送风口|臭氧机|FFU-山东盛之源净化设备 | 昆山新莱洁净应用材料股份有限公司-卫生级蝶阀,无菌取样阀,不锈钢隔膜阀,换向阀,离心泵 |