ArcGIS JS 学习笔记3 实现百度风格的BubblePopup

1. 开篇

模仿是最好的学习,这次我们继续山寨百度,通过自定义Infowindow来实现百度风格的BubblePopup

2.准备

2.1 Copy模板

先打开百度地图,按下f12吧BubblePopup的HTML代码和CSS代码拷贝下来,这里我无耻的把类名改了,大家不要在意细节。

HTML模板

  1 <div class="dextra-bubble-pop-center" style="z-index: 3; position: relative; height: 50px; width: 160px;">
  2     <div class="dextra-bubble-pop-content"
  3          style="display: block; width: 160px; height: 50px; overflow-x: auto; overflow-y: hidden;">
  4         <div id="poi_info_window" class="dextra-poi-info-window">
  5             <div class="left name-wrap"><span class="name"></span></div>
  6         </div>
  7     </div>
  8 </div>
  9 <div class="dextra-bubble-pop-bottom" style="display: block; z-index: 2; width: 160px; left: 72px;">
 10     <span></span>
 11 </div>

CSS代码

  1
  2 .dextra-bubble-pop {
  3     position: absolute;
  4     z-index: 100;
  5     box-sizing: border-box;
  6     box-shadow: 1px 2px 1px rgba(0, 0, 0, .15);
  7     background-color: #FFF;
  8 }
  9
 10 .dextra-poi-info-window {
 11     padding: 4px 0;
 12 }
 13
 14 .dextra-poi-info-window .left {
 15     padding-left: 10px;
 16     padding-right: 10px;
 17     height: 40px;
 18     line-height: 40px;
 19     display: table;
 20     table-layout: fixed;
 21     width: 140px;
 22     text-align: center;
 23 }
 24
 25 .dextra-poi-info-window .name-wrap .name {
 26     vertical-align: middle;
 27     font-size: 14px;
 28     font-weight: 700;
 29     white-space: nowrap;
 30     overflow: hidden;
 31     text-overflow: ellipsis;
 32     display: block;
 33 }
 34
 35 .dextra-bubble-pop-bottom span {
 36     position: absolute;
 37     left:72px;
 38     width: 16px;
 39     height: 10px;
 40     background-image: url("../images/tail_shadow.png");
 41 }

2.2 编写BubblePopup

要实现BubblePopup,实际上就是自定义一个InfoWindow,我们可以通过继承InfoWindowBase来实现。要实现自定义的InfoWindow。我们可以先参考一下官方的例子Custom info window,注意,这个例子是有缺陷的,如果当infowindow超出当前视图边界就会出现滚动条。下载官方的实例,我们打开infoWindow.js文件。

  1 define([
  2     "dojo/Evented",
  3     "dojo/parser",
  4     "dojo/on",
  5     "dojo/_base/declare",
  6     "dojo/dom-construct",
  7     "dojo/_base/array",
  8     "dojo/dom-style",
  9     "dojo/_base/lang",
 10     "dojo/dom-class",
 11     "dojo/fx/Toggler",
 12     "dojo/fx",
 13     "dojo/Deferred",
 14     "esri/domUtils",
 15     "esri/InfoWindowBase"
 16
 17 ],
 18 function(
 19     Evented,
 20     parser,
 21     on,
 22     declare,
 23     domConstruct,
 24     array,
 25     domStyle,
 26     lang,
 27     domClass,
 28     Toggler,
 29     coreFx,
 30     Deferred,
 31     domUtils,
 32     InfoWindowBase
 33 ) {
 34     return declare([InfoWindowBase, Evented], {
 35
 36         isContentShowing :false,
 37
 38         constructor: function(parameters) {
 39
 40
 41           lang.mixin(this, parameters);
 42
 43
 44           domClass.add(this.domNode, "myInfoWindow");
 45
 46           this._closeButton = domConstruct.create("div",{"class": "close", "title": "Close"}, this.domNode);
 47           this._title = domConstruct.create("div",{"class": "title"}, this.domNode);
 48           this._content = domConstruct.create("div",{"class": "content"}, this.domNode);
 49
 50           this._toggleButton = domConstruct.create("div",{"class": "toggleOpen", "title": "Toggle"}, this.domNode);
 51
 52           var toggler = new  Toggler({
 53             "node": this._content,
 54             showFunc: coreFx.wipeIn,
 55             hideFunc: coreFx.wipeOut
 56           });
 57           toggler.hide();
 58
 59           on(this._closeButton, "click", lang.hitch(this, function(){
 60             //hide the content when the info window is toggled close.
 61             this.hide();
 62             if(this.isContentShowing){
 63               toggler.hide();
 64               this.isContentShowing = false;
 65               domClass.remove(this._toggleButton);
 66               domClass.add(this._toggleButton, "toggleOpen");
 67             }
 68           }));
 69           on(this._toggleButton, "click", lang.hitch(this, function(){
 70             //animate the content display
 71               if(this.isContentShowing){
 72
 73                 toggler.hide();
 74                 this.isContentShowing = false;
 75                 domClass.remove(this._toggleButton);
 76                 domClass.add(this._toggleButton,"toggleOpen");
 77
 78               }else{
 79                 toggler.show();
 80                 this.isContentShowing=true;
 81                 domClass.remove(this._toggleButton);
 82                 domClass.add(this._toggleButton,"toggleClose");
 83               }
 84
 85           }));
 86           //hide initial display
 87           domUtils.hide(this.domNode);
 88           this.isShowing = false;
 89
 90         },
 91         setMap: function(map){
 92           this.inherited(arguments);
 93           map.on("pan-start", lang.hitch(this, function(){
 94             this.hide();
 95           }));
 96           map.on("zoom-start", lang.hitch(this, function(){
 97             this.hide();
 98           }));
 99          // map.on("zoom-start", //this, this.hide);
100
101         },
102         setTitle: function(title){
103           this.place(title, this._title);
104
105         },
106         setContent: function(content){
107           this.place(content, this._content);
108         },
109         show: function(location){
110           if(location.spatialReference){
111             location = this.map.toScreen(location);
112           }
113
114           //Position 10x10 pixels away from the specified location
115           domStyle.set(this.domNode,{
116             "left": (location.x + 10) + "px",
117             "top": (location.y + 10) + "px"
118           });
119
120           //display the info window
121           domUtils.show(this.domNode);
122           this.isShowing = true;
123           this.onShow();
124         },
125         hide: function(){
126           domUtils.hide(this.domNode);
127           this.isShowing = false;
128           this.onHide();
129
130         },
131         resize: function(width, height){
132           domStyle.set(this._content,{
133             "width": width + "px",
134             "height": height + "px"
135           });
136           domStyle.set(this._title,{
137             "width": width + "px"
138           });
139
140         },
141         destroy: function(){
142           domConstruct.destroy(this.domNode);
143           this._closeButton = this._title = this._content = null;
144
145         }
146
147
148       });
149
150 });

我们就在此基础上进行改造,不但要实现需求还要解决缺陷。infoWindowBase是继承自_WidgetBase的,我们先来看一下infoWindowBase的官方描述.

我们可以重写infoWindowBase的一些方法,来实现自己的infoWindow。

首先我们先引入我们要用到的模块

  1 define([
  2         "dojo/Evented",
  3         "dojo/on",
  4         "dojo/query",
  5         "dojo/_base/declare",
  6         "dojo/dom-construct",
  7         "dojo/dom-attr",
  8         "dojo/_base/array",
  9         "dojo/dom-style",
 10         "dojo/_base/lang",
 11         "dojo/dom-class",
 12         "dijit/_TemplatedMixin",
 13         "esri/domUtils",
 14         "esri/InfoWindowBase",
 15         "esri/geometry/ScreenPoint",
 16         "esri/geometry/screenUtils",
 17         "esri/geometry/webMercatorUtils",
 18         "dojo/text!./templates/dextraPopup.html"
 19     ],
 20     function (Evented,
 21               on,
 22               query,
 23               declare,
 24               domConstruct,
 25               domAttr,
 26               array,
 27               domStyle,
 28               lang,
 29               domClass,
 30               _TemplatedMixin,
 31               domUtils,
 32               InfoWindowBase, ScreenPoint, screenUtils, webMercatorUtils, template) {
 33         var showMapPoint = null;
 34         return declare([InfoWindowBase, Evented, _TemplatedMixin], {
 35             isContentShowing: false,
 36             templateString: template,
 37             _events: [],
 38             constructor: function (parameters) {
 39                 lang.mixin(this, parameters);
 40             },
 41                 ...
 42               });

对比官方的例子,我去掉了部分模块(coreFx,Toggler),加入了dijit/_TemplateMixin,esri/geometry/webMecratorUtils,

esri/geomtry/srcreenUtils模块。_TemplateMixin是为了使用我在第一步拷贝下来的HTML模板,关于编写基于模板的widget可以到

dojo的官网进行查看;webMecratorUtils和srcreenUtils则是为了实现地理坐标和屏幕坐标的准确转换。

showMapPoint是一个全局的变量,用来记录popup的地理坐标位置。

templateString是_TemplateMixin模块的一个属性,用来保存HTML模板。

_events:是一个数组,用来存储相关的事件,在popup被释放时释放注册的事件。

先用一个私有方法来进行初始化。应为InfoWindowBase是继承自_WidgetBase的,domNode是_WidgetBase的一个属性,用于表示生成Widget的dom节点,可以通过在构造函数里用第二个参数来进行传入,或者在内部自己定义。

  1   _createInfoWindowInstance: function (map) {
  2                 this.domNode = domConstruct.create("div", null, map.id + "_root");
  3                 domClass.add(this.domNode, "dextra-bubble-pop");
  4                 domStyle.set(this.domNode, {
  5                     width: "160px",
  6                 });
  7
  8                 this.domNode.innerHTML = this.templateString;
  9
 10                 this._content = query("div.name-wrap span.name");
 11                 this._title=query("div.name-wrap");
 12                 //hide initial display
 13                 domUtils.hide(this.domNode);
 14                 this.isShowing = false;
 15             },

注意,我在这里创建了一个div节点,并把它添加到一个id为{map.id}_root({map.id}占位符,用于表示地图的id)的dom节点中,这一步就是解决当infowindow超出当前视图范围时会出现滚动条。我们可以先用arcgis提供的infowindow来试一试,在浏览器中按

f12,我们看一看infowindow是放在哪的。

利用arcgis自带的infowindow,我们可以看到这个infowindow的dom节点被添加到一个id为map_root的div中。在这里,我的map控件的id为“map”,所以它会生成一个id为“map_root”({map.id}_root)的div。所以我们只要把自定生成的popup放到这个节点中,当popup超出当前视图时,会被裁减了,而不是出现滚动条。这里最关键的部分已经完成了,接下来的操作就是如何在地图上展现这个popup。

  1   _showInfoWindow: function (extent) {
  2                 if (showMapPoint == null)return;
  3                 var showScreenPoint = screenUtils.toScreenGeometry(extent, this.map.width, this.map.height, showMapPoint);
  4                 domStyle.set(this.domNode, {
  5                     "left": (showScreenPoint.x - 80) + "px",
  6                     "top": (showScreenPoint.y - 76 ) + "px"
  7                 });
  8
  9                 domUtils.show(this.domNode);
 10                 this.isShowing = true;
 11                 this.onShow();
 12             },
 13
 14             show: function (location) {
 15                 showMapPoint = location;
 16                 if (webMercatorUtils.canProject(location, this.map)) {
 17                     showMapPoint = webMercatorUtils.project(location, this.map);
 18                 }
 19                 if (showMapPoint.spatialReference) {
 20                     var screenPoint = this.map.toScreen(showMapPoint);
 21                     domStyle.set(this.domNode, {
 22                         "left": (screenPoint.x - 80) + "px",
 23                         "top": (screenPoint.y - 76) + "px"
 24                     });
 25                 }
 26
 27                 //display the info window
 28                 domUtils.show(this.domNode);
 29                 this.isShowing = true;
 30                 this.onShow();
 31             },

_showInfoWindow方法是一个私有方法,用于在地图事件触发时调用。当地图平移,缩放时根据地理坐标从新计算BubblePopup的屏幕坐标。用screenUtils.toScreenGeometry(extent, width, height, mapGeometry)根据地图的范围,宽度,高度,和点计算出相应的屏幕坐标。

show方法是一个公有方法,用于在外部进行调用。在这里利用了arcgis js 提供webMercatorUtils模块,来进行坐标的转换。一般而言,我们都会用经纬度坐标,但是当地图是webMercator投影时,就需要先把经纬度坐标转化成米制坐标,才能在正确的位置显示出来来。

关键的部分已经完成,下面贴出全部代码

  1 define([
  2         "dojo/Evented",
  3         "dojo/on",
  4         "dojo/query",
  5         "dojo/_base/declare",
  6         "dojo/dom-construct",
  7         "dojo/dom-attr",
  8         "dojo/_base/array",
  9         "dojo/dom-style",
 10         "dojo/_base/lang",
 11         "dojo/dom-class",
 12         "dijit/_TemplatedMixin",
 13         "esri/domUtils",
 14         "esri/InfoWindowBase",
 15         "esri/geometry/ScreenPoint",
 16         "esri/geometry/screenUtils",
 17         "esri/geometry/webMercatorUtils",
 18         "dojo/text!./templates/dextraPopup.html"
 19     ],
 20     function (Evented,
 21               on,
 22               query,
 23               declare,
 24               domConstruct,
 25               domAttr,
 26               array,
 27               domStyle,
 28               lang,
 29               domClass,
 30               _TemplatedMixin,
 31               domUtils,
 32               InfoWindowBase, ScreenPoint, screenUtils, webMercatorUtils, template) {
 33         var showMapPoint = null;
 34         return declare([InfoWindowBase, Evented, _TemplatedMixin], {
 35
 36             templateString: template,
 37             _events: [],
 38             constructor: function (parameters) {
 39                 lang.mixin(this, parameters);
 40             },
 41             _createInfoWindowInstance: function (map) {
 42                 this.domNode = domConstruct.create("div", null, map.id + "_root");
 43                 domClass.add(this.domNode, "dextra-bubble-pop");
 44                 domStyle.set(this.domNode, {
 45                     width: "160px",
 46                 });
 47
 48                 this.domNode.innerHTML = this.templateString;
 49
 50                 this._content = query("div.name-wrap span.name");
 51                 this._title=query("div.name-wrap");
 52                 //hide initial display
 53                 domUtils.hide(this.domNode);
 54                 this.isShowing = false;
 55             },
 56
 57             setMap: function (map) {
 58                 this.inherited(arguments);
 59                 this._events = [];
 60                 this._createInfoWindowInstance(map);
 61                 this._events.push(map.on("pan", lang.hitch(this, function (evt) {
 62                     if (this.isShowing) {
 63                         this._showInfoWindow(evt.extent);
 64                     }
 65                 })));
 66
 67                 this._events.push(map.on("zoom-start", lang.hitch(this, function (evt) {
 68                     this.hide();
 69                 })));
 70
 71                 this._events.push(map.on("zoom-end", lang.hitch(this, function (evt) {
 72                     this._showInfoWindow(evt.extent);
 73                 })));
 74             },
 75
 76             unsetMap: function (map) {
 77                 this.inherited(arguments);
 78                 array.forEach(this._events, function (event) {
 79                     event.remove();
 80                 });
 81             },
 82             setTitle: function (title) {
 83                 this._title.forEach(function (node) {
 84                     domAttr.set(node, "title", title);
 85                 });
 86             },
 87
 88             setContent: function (content) {
 89                 this._content.forEach(function (node) {
 90                     node.innerHTML = content;
 91                 });
 92             },
 93
 94             _showInfoWindow: function (extent) {
 95                 if (showMapPoint == null)return;
 96                 var showScreenPoint = screenUtils.toScreenGeometry(extent, this.map.width, this.map.height, showMapPoint);
 97                 domStyle.set(this.domNode, {
 98                     "left": (showScreenPoint.x - 80) + "px",
 99                     "top": (showScreenPoint.y - 76 ) + "px"
100                 });
101
102                 domUtils.show(this.domNode);
103                 this.isShowing = true;
104                 this.onShow();
105             },
106
107             show: function (location) {
108                 showMapPoint = location;
109                 if (webMercatorUtils.canProject(location, this.map)) {
110                     showMapPoint = webMercatorUtils.project(location, this.map);
111                 }
112                 if (showMapPoint.spatialReference) {
113                     var screenPoint = this.map.toScreen(showMapPoint);
114                     domStyle.set(this.domNode, {
115                         "left": (screenPoint.x - 80) + "px",
116                         "top": (screenPoint.y - 76) + "px"
117                     });
118                 }
119
120                 //display the info window
121                 domUtils.show(this.domNode);
122                 this.isShowing = true;
123                 this.onShow();
124             },
125             hide: function () {
126                 if (this.isShowing) {
127                     domUtils.hide(this.domNode);
128                     this.isShowing = false;
129                     this.onHide();
130                 }
131             },
132             resize: function (width, height) {
133                 domStyle.set(this._content, {
134                     "width": width + "px",
135                     "height": height + "px"
136                 });
137             },
138             remove: function () {
139                 this.hide();
140                 showMapPoint = null;
141             },
142             destroy: function () {
143                 domConstruct.destroy(this.domNode);
144             }
145         });
146     });
147 

DEMO:

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>DExtra-BubublPoopup</title>
  6     <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
  7     <link rel="stylesheet" href="../dist/dijit/css/dextraPopup.css">
  8     <link rel="stylesheet" href="css/mainApp.css">
  9     <script>
 10         var dojoConfig = {
 11             parseOnLoad:true,
 12             packages: [{
 13                 name: ‘custom‘,
 14                 location: location.pathname.replace(/\/[^/]+$/, ‘‘) + ‘/custom‘//从cdn加载自己定义的模块方法
 15             },
 16                 {
 17                     name: ‘dextra‘,
 18                     location: ‘/extra.arcgis.3.x/dist/‘//从cdn加载自己定义的模块方法
 19                 }]
 20         };
 21     </script>
 22     <script src="https://js.arcgis.com/3.16/"></script>
 23     <script>
 24         require([
 25                     "dojo/dom",
 26                     "dojo/on",
 27                     "esri/map",
 28                     "esri/symbols/SimpleMarkerSymbol",
 29                     "esri/InfoTemplate",
 30                     "esri/layers/GraphicsLayer",
 31                     "dextra/layers/GoogleVectorLayer",
 32                     "dextra/dijit/DEBubblePopup",
 33                     "dojo/domReady!"],
 34                 function (dom, on,
 35                           Map,  Graphic, SimpleMarkerSymbol, InfoTemplate, GraphicsLayer,
 36                           GoogleVectorLayer,DEBubblePopup) {
 37
 38                     var infoWindow = new  DEBubblePopup();
 39                     var map = new Map("map", {
 40                         showAttribution: false,
 41                         center: [102.3, 24.6],
 42                         autoResize: true,
 43                         sliderPosition: "bottom-right",
 44                         logo: false,
 45                         infoWindow:infoWindow,
 46                         zoom:12
 47                     });
 48
 49                     var googleVect = new GoogleVectorLayer();
 50                     map.addLayer(googleVect);
 51
 52                     var measureLayer = new GraphicsLayer({id: "infoWindowTest"});
 53                     map.addLayer(measureLayer);
 54                     on(dom.byId("infowindow"), "click", function (e) {
 55                         on.once(map, "click", function (evt) {
 56                             console.log(map._container);
 57                             var sms = new SimpleMarkerSymbol({
 58                                 "color": [255, 0, 0],
 59                                 "size": 12,
 60                                 "xoffset": 0,
 61                                 "yoffset": 0,
 62                                 "type": "esriSMS",
 63                                 "style": "esriSMSCircle",
 64                                 "outline": {
 65                                     "color": [0, 0, 0, 255],
 66                                     "width": 1,
 67                                     "type": "esriSLS",
 68                                     "style": "esriSLSSolid"
 69                                 }
 70                             });
 71
 72                             var point = map.toMap(evt.screenPoint);
 73                             var attr = {"Xcoord": point.x, "Ycoord": point.y, "Plant": "Mesa Mint"};
 74                             var infoTemplate = new InfoTemplate("Locations", "Latitude: ${Ycoord} Longitude: ${Xcoord}Plant Name:${Plant}");
 75                             var graphic=new Graphic(point, sms,attr,infoTemplate);
 76                             measureLayer.add(graphic);
 77                         });
 78                     });
 79                 });
 80     </script>
 81     <style>
 82         #measureTools {
 83             position: absolute;
 84             top: 50px;
 85             left: 50px;
 86             z-index: 1000;
 87         }
 88     </style>
 89 </head>
 90 <body>
 91 <div id="measureTools">
 92     <button id="infowindow">弹出框</button>
 93 </div>
 94
 95 <div id="map" ></div>
 96 </body>
 97 </html>

效果截图:

3.1 小结

可以看到,通过继承InfoWindowBase我们完全可以实现自己的的infoWindow,编写更具个性化的插件。最后像新手玩家推荐一下

esri的github,这里有很多有用的东西,非常值得学习http://esri.github.io/

本文参考了 http://blog.csdn.net/gisshixisheng/article/details/26132921 谢谢lzugis的分享。

欢迎转载 http://www.cnblogs.com/deliciousExtra/p/5565787.html

时间: 2024-10-08 10:44:57

ArcGIS JS 学习笔记3 实现百度风格的BubblePopup的相关文章

ArcGIS JS 学习笔记1 用ArcGIS JS 实现仿百度地图的距离量测和面积量测

一.开篇 在博客注册了三年,今天才决定写第一篇博客,警告自己不要懒!!! 二.关于ArcGIS JS 版本选择 在写这篇博客时ArcGIS JS 4.0正式版已经发布.它和3.x版本的不同是,Map不在是一个控件,而真的只是一张“图”,Map(4.0版本)需要在一个View里面来展示,在MapView里面就是一张平面图,在SceneView里面就一张三维地图.同一张地图在不同的View里面就可以呈现出不同的效果.但是4.0版本才是一个最初的版本,还有很多3.x有的功能没有被加入到其中.所以我打算

ArcGIS JS 学习笔记2 实现仿百度的拖拽画圆

一.前言 吐槽一下,百度在国内除了百度地图是良心产品外,其他的真的不敢恭维.在上一篇笔记里,我已经实现了自定义的地图测量模块.在百度地图里面(其他地图)都有一个周边搜索的功能,拖拽画一个圆,然后以圆半径进行搜索(也就是缓冲区╮(╯_╰)╭). 这次的目标,就是要山寨这个拖拽画圆的功能,我先放一个效果图. 二.开始山寨 我们先想一想要实现这个功能需要哪些步骤. 拖拽 画圆 通知拖拽结束 2.1 实现拖拽 关于拖拽,有graphicslayer的拖拽事件和map的拖拽事件,如何选择呢?先来看一看官方

ArcGIS JS 学习笔记4 实现地图联动

1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而且鼠标也有联动,我就照着这个目标进行山寨. 2.准备 地图联动其实就是当一张的extent发生了变化,另一张图的extent也要同步变化,这样就可以两张图的范围同步了.同理,这样就可以扩展到N张图进行联动.所以这次的目标就是实现添加任意的地图都要可以联动.首先依然是先看一下官方文档.找到有用的方法或者事件. 整体的难点在于如何判断主地图(有鼠标动作的

Vue.js学习笔记:在元素 和 template 中使用 v-if 指令

f 指令 语法比较简单,直接上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title></title> <script src="https://cdn.bootcss.com/vue/2.2.

[Pro Angular.JS]学习笔记1.1:设置开发环境

可以使用yeoman.io,很方便.我已经写了一篇随笔,介绍如何使用.这里也有一篇介绍的文章:http://www.cnblogs.com/JoannaQ/p/3756281.html 代码编辑器,在Mac下用了一下WebStorm,太恶心了.另外发现书的作者使用的开发环境是Windows + VS Express 2013,为了方便学习,我也使用VS Express 2013 Update2.VS2013用起来蛮舒服的,把WebStorm比得跟驼屎一样.也许是因为我没用习惯吧. 1.安装Nod

【转】Backbone.js学习笔记(二)细说MVC

文章转自: http://segmentfault.com/a/1190000002666658 对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一) Backbone源码结构 1: (function() { 2: Backbone.Events // 自定义事件 3: Backbone.Model // 模型构造函数和原型扩展 4: Backbone.Collection // 集合构造函数和原型扩展 5: Backbone.Router // 路由

Angular JS 学习笔记

特定领域语言 编译器:遍历DOM来查找和它相关的属性, 分为编译和链接两个阶段, 指令:当关联的HTML结构进入编译阶段时应该执行的操作,可以写在名称里,属性里,css类名里:本质上是函数 稳定的DOM:绑定了数据模型的DOM元素的实例不会在绑定的生命周期发生改变 作用域:用来检测模型的改变和为表达式提供执行上下文的 AngularJS 和其它模板系统不同,它使用的是DOM而不是字符串 指令: 由某个属性.元素名称.css类名出现而导致的行为,或者说是DOM的变化 Filter过滤器:扮演着数据

Node.js学习笔记(3) - 简单的curd

这个算是不算完结的完结吧,前段时间也是看了好久的Node相关的东西,总想着去整理一下,可是当时也没有时间: 现在看来在整理的话,就有些混乱,自己也懒了,就没在整理,只是简单的记录一下 一.demo的简单介绍 这次demo,只涉及到简单的curd操作,用到的数据库是mongo,所以要安装mongo数据库,数据库连接驱动是mongoose: 当然关于mongo的驱动有很多,比如mongous mongoskin等:(详见http://cnodejs.org/topic/4f4ca8e0940ce2e

JS学习笔记-OO疑问之封装

封装是面向对象的基础,今天所要学习的匿名函数与闭包就是为了实现JS的面向对象封装.封装实现.封装变量,提高数据.系统安全性,封装正是面向对象的基础. 匿名函数 即没有名字的函数,其创建方式为 function(){...} 单独存在的匿名函数,无法运行,可通过赋值给变量调用或通过表达式自我执行来实现运行. 1.赋值给变量为一般的函数使用方式 var run = function(){ return '方法运行中'; }; alert(run()); 2.通过表达式自我执行 (function(a