前端基础进阶,Web应用中的离线数据存储

三回九转的落实格局及原型概述

2015/07/15 · JavaScript · 原型, 继承

初藳出处: 名风流倜傥的博客   

对于 OO 语言,有一句话叫“伊芙rything is object”,纵然 JavaScript 不是严酷意义上的面向对象语言,但只要想要领会 JS 中的世袭,那句话必须要时刻记住于心。

JS 的语法极度灵活,所以有人认为它差相当少,因为怎么写都以对的;也可以有人以为它难,因为很难解释有些语法的宏图,什么人能告诉作者何以 typeof null 是 object 而 typeof undefined 是 undefined 吗?並且那是在 null == undefined 的前提下。非常多大家自认为“懂”了的知识点,细细探讨起来,照旧会发掘存不知凡几盲点,“无畏源于无知”吧……

6、拖拽的规律

当事件触发时,大家可以透过事件目的取获得鼠标的精切地方。那是贯彻拖拽的注重。当鼠标按下(mousedown触发)时,我们要求深深记住鼠标的始发地方与指标成分的始发地方,大家的对象就是完成当鼠标移动时,目的成分也随后移动,依据原理大家能够得出如下事关:

移动后的鼠标地点 - 鼠标起始地点 = 移动后的指标成分地方 - 目的成分的先河地方

1
移动后的鼠标位置 - 鼠标初始位置 = 移动后的目标元素位置 - 目标元素的初始位置

假诺鼠标地点的差值大家用dis来代表,那么指标成分的岗位就极其:

活动后目的成分之处 = dis + 目的成分的开头地点

1
移动后目标元素的位置 = dis + 目标元素的初始位置

经过事件目的,大家可以确切的领悟鼠标的当下地方,由此当鼠标拖动(mousemove)时,我们能够不停的计量出鼠标移动的差值,以此来求出指标成分的一时职分。那一个历程,就落到实处了拖拽。

而在鼠标松手(mouseup)结束拖拽时,大家供给管理部分了事工作。详细情况见代码。

总结

可以知道,在Web应用中运用离线数据并非十一分复杂。希望经过翻阅那篇文章,各位能够在Web应用中参与离线数据的法力,使得你们的行使越来越温馨易用。你能够在这里下载全数的源码,尝试一下,恐怕涂改,也许用在你们的施用中。

赞 收藏 评论

3. 引入 prototype

今昔为 Dog 函数加上 prototype,看三个事例:

JavaScript

function Dog(name) { this.name = name; this.bark = function() {}; } Dog.prototype.jump = function() {}; Dog.prototype.species = 'Labrador'; Dog.prototype.teeth = ['1', '2', '3', '4']; var dog1 = new Dog('tom'), dog2 = new Dog('jerry'); dog1.bark !== dog2.bark; // true dog1.jump === dog2.jump; // true dog1.teeth.push('5'); dog2.teeth; // ['1', '2', '3', '4', '5']

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Dog(name) {
  this.name = name;
  this.bark = function() {};
}
 
Dog.prototype.jump = function() {};
Dog.prototype.species = 'Labrador';
Dog.prototype.teeth = ['1', '2', '3', '4'];
 
var dog1 = new Dog('tom'),
    dog2 = new Dog('jerry');
 
dog1.bark !== dog2.bark; // true
dog1.jump === dog2.jump; // true
 
dog1.teeth.push('5');
dog2.teeth; // ['1', '2', '3', '4', '5']

来看有注释的这三行应该能够精晓“援引”和“新建”的界别了。

那便是说大家平日聊到的“原型链”到底是怎么呢?那些术语出今后三回九转个中,它用于表示对象实例中的属性和格局来自于哪儿(哪个父类卡塔 尔(英语:State of Qatar)。好吧,那是作者的演讲。

JavaScript

- Object bark: Dog/this.bark() name: 'tom' - __proto__: Object jump: Dog.prototype.jump() species: 'Labrador' + teeth: Array[4] + constructor: Dog() + __proto__: Object

1
2
3
4
5
6
7
8
9
- Object
  bark: Dog/this.bark()
  name: 'tom'
- __proto__: Object
    jump: Dog.prototype.jump()
    species: 'Labrador'
  + teeth: Array[4]
  + constructor: Dog()
  + __proto__: Object  

上边的是 dog1 的原型链,不明了够远远不够直观地描述“链”这几个概念。

  1. 个中,bark 和 name 是概念在 this 中的,所以最顶层能够见到它俩。
  2. 下一场,每贰个对象都会有三个 __proto__ 属性(IE 11+卡塔尔,它代表定义在原型上的习性和格局,所以 jump、species 和 teeth 自然就在这里刻了。
  3. 聊到底就平昔发展找 __proto__ 中的属性和艺术。

  4. 后续的两种达成


3、 怎么样赢得成分的启幕地方

大家首先必要取获得对象成分的开头地点,因而这里我们需求二个极其用来赢得成分样式的功用函数。

然则获取成分样式在IE浏览器与别的浏览器有生机勃勃部分两样,因而大家须要多个包容性的写法。

JavaScript

function getStyle(elem, property) { // ie通过currentStyle来收获成分的体裁,别的浏览器通过getComputedStyle来取得return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property]; }

1
2
3
4
function getStyle(elem, property) {
    // ie通过currentStyle来获取元素的样式,其他浏览器通过getComputedStyle来获取
    return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property];
}

有了那几个措施之后,就足以初步出手写获取目的成分初步地点的方法了。

JavaScript

function getTargetPos(elem) { var pos = {x: 0, y: 0}; var transform = getTransform(); if(transform) { var transformValue = getStyle(elem, transform); if(transformValue == 'none') { elem.style[transform] = 'translate(0, 0)'; return pos; } else { var temp = transformValue.match(/-?d+/g); return pos = { x: parseInt(temp[4].trim()), y: parseInt(temp[5].trim()) } } } else { if(getStyle(elem, 'position') == 'static') { elem.style.position = 'relative'; return pos; } else { var x = parseInt(getStyle(elem, 'left') ? getStyle(elem, 'left') : 0); var y = parseInt(getStyle(elem, 'top') ? getStyle(elem, 'top') : 0); return pos = { x: x, y: y } } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function getTargetPos(elem) {
    var pos = {x: 0, y: 0};
    var transform = getTransform();
    if(transform) {
        var transformValue = getStyle(elem, transform);
        if(transformValue == 'none') {
            elem.style[transform] = 'translate(0, 0)';
            return pos;
        } else {
            var temp = transformValue.match(/-?d+/g);
            return pos = {
                x: parseInt(temp[4].trim()),
                y: parseInt(temp[5].trim())
            }
        }
    } else {
        if(getStyle(elem, 'position') == 'static') {
            elem.style.position = 'relative';
            return pos;
        } else {
            var x = parseInt(getStyle(elem, 'left') ? getStyle(elem, 'left') : 0);
            var y = parseInt(getStyle(elem, 'top') ? getStyle(elem, 'top') : 0);
            return pos = {
                x: x,
                y: y
            }
        }
    }
}

在拖拽进程中,大家须求不停的设置目的成分的新职责,这样它才会移动起来,由此大家须要叁个装置目的成分地方的措施。

JavaScript

// pos = { x: 200, y: 100 } function setTargetPos(elem, pos) { var transform = getTransform(); if(transform) { elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)'; } else { elem.style.left = pos.x + 'px'; elem.style.top = pos.y + 'px'; } return elem; }

1
2
3
4
5
6
7
8
9
10
11
// pos = { x: 200, y: 100 }
function setTargetPos(elem, pos) {
    var transform = getTransform();
    if(transform) {
        elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)';
    } else {
        elem.style.left = pos.x + 'px';
        elem.style.top = pos.y + 'px';
    }
    return elem;
}

IndexedDB

在自己个人看来,那是最棒玩的风度翩翩种技艺。它能够保存一大波透过索引(indexed卡塔尔国的数目在浏览器端。那样一来,就能够在客商端保存复杂对象,大文书档案等等数据。何况顾客能够在离线意况下访谈它们。那生机勃勃性情大概适用于拥有项目标Web应用:假若您写的是邮件顾客端,你能够缓存顾客的邮件,以供稍后再看;要是您写的是相册类应用,你能够离线保存客商的照片;假令你写的是GPS导航,你能够缓存顾客的不二秘籍……不计其数。

IndexedDB是三个面向对象的数据库。这就意味着在IndexedDB中既子虚乌有表的概念,也从没SQL,数据是以键值对的情势保留的。个中的键不仅可以够是字符串和数字等幼功项目,也得以是日期和数组等繁缛类型。这些数据库本身营造于储存(store,三个store相近于关系型数据中表的定义卡塔尔的基础上。数据库中每一种值都不得不要有照顾的键。种种键既可以够自动生成,也足以在插入值的时候钦定,也能够取自于值中的有些字段。假令你调节动用值中的字段,那么只可以向里面增加Javascript对象,因为底子数据类型不像Javascript对象那样有自定义属性。

5. 私有小结

当大家在座谈世襲的得以完成情势时,给小编的感到到如同孔乙己在炫丽“香丝菜豆”的“茴”有二种写法相似。世袭是 JS 中占比一点都不小的一块内容,所以众多库都有谈得来的得以完毕格局,它们并从未选拔小编觉着的“最妥贴”的方法,为啥?JS 正是 JS,它生来就安排得特别灵活,所以大家为啥不利用这几个特点,而非得将 OO 的做法强加于它吗?

由此持续,大家愈来愈多的是期望获得父类的习性和方法,至于是否要保险严酷的父类/子类关系,非常多时候并不在乎,而拷贝世襲最能显示那点。对于基于原型的继续,会在代码中看出各类用 function 定义的种类,而拷贝世袭更通用,它只是将三个目的的习性和情势拷贝(扩张卡塔尔国到另三个对象而已,并不关怀原型链是何许。

自然,在自家鼓吹拷贝世襲多么多么好时,基于原型的三回九转自然有它不行替代的说辞。所以具体难点得具体剖判,当实际的施用状况没定下来时,就不设有最棒的措施。

个人见解,能帮助大家尤其明白世襲一点就最棒,即使有哪些窘迫的,请多都赐教!

1 赞 4 收藏 评论

图片 1

2、怎么样获得当前浏览器帮助的transform包容写法

transform是css3的习性,当我们使用它时就只好面前碰着宽容性的标题。差别版本浏览器的相当写法大约犹如下二种:

['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform']

故而我们需求判断当前浏览器情况扶助的transform属性是哪大器晚成种,方法如下:

JavaScript

// 获取当前浏览器扶持的transform包容写法 function getTransform() { var transform = '', divStyle = document.createElement('div').style, // 大概涉嫌到的两种包容性写法,通过轮回搜索浏览器度和胆识其他那三个 transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'], i = 0, len = transformArr.length; for(; i < len; i++) { if(transformArr[i] in divStyle) { // 找到之后立即回去,甘休函数 return transform = transformArr[i]; } } // 若无找到,就平素回到空字符串 return transform; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 获取当前浏览器支持的transform兼容写法
function getTransform() {
    var transform = '',
        divStyle = document.createElement('div').style,
        // 可能涉及到的几种兼容性写法,通过循环找出浏览器识别的那一个
        transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
 
        i = 0,
        len = transformArr.length;
 
    for(; i < len; i++)  {
        if(transformArr[i] in divStyle) {
            // 找到之后立即返回,结束函数
            return transform = transformArr[i];
        }
    }
 
    // 如果没有找到,就直接返回空字符串
    return transform;
}

该办法用于获取浏览器帮忙的transform属性。假诺回去的为空字符串,则意味近年来浏览器并不支持transform,当时大家就要求使用left,top值来改形成分的地点。借使帮衬,就改成transform的值。

引言

趁着HTML5的光降,各类Web离线数据本领踏入了开辟职员的视界。诸如AppCache、localStorage、sessionStorage和IndexedDB等等,每风度翩翩种技能皆有它们各自适用的范围。比方AppCache就比较切合用来离线起动应用,或许在离线状态下使利用的生龙活虎部分功用照常运作。接下来笔者将会为大家作详细介绍,何况用有个别代码片段来展现什么行使那些才具。

4.2 通过 prototype 落成持续

要得以完结三番三次,必需满含“原型”的概念。下边是很常用的世袭格局。

JavaScript

function Dog(name) { Animal.call(this); } Dog.prototype = new Animal(); // 先借使 Animal 函数未有参数 Dog.prototype.constructor = Dog; var dog = new Dog('tom'); dog instanceof Animal; // true

1
2
3
4
5
6
7
8
9
10
function Dog(name) {
  Animal.call(this);
}
 
Dog.prototype = new Animal(); // 先假设 Animal 函数没有参数
Dog.prototype.constructor = Dog;
 
var dog = new Dog('tom');
 
dog instanceof Animal; // true

接轨的结果有五个:生机勃勃、得到父类的习性和艺术;二、精确通过 instanceof 的测量试验。

prototype 也是目的,它是创办实例时的装配机,这些在前面有提过。new Animal() 的值包罗 Animal 实例全部的品质和办法,既然它赋给了 Dog 的 prototype,那么 Dog 的实例自然就获取了父类的全部属性和措施。

还要,通过这一个例子能够领略,改换 Dog 的 prototype 属性能够变动 instanceof 的测量检验结果,也正是改革了父类。

下一场,为啥要在 Dog 的构造函数中调用 Animal.call(this)?

因为 Animal 中大概在 this 上定义了艺术和函数,若无那句话,那么具备的那总体都会给到 Dog 的 prototype 上,依据前边的学问我们了然,prototype 中的属性和措施在实例间是分享的。

作者们期待将那个属性和措施依旧保留在实例本人的空间,而不是分享,因而须求重写生龙活虎份。

至于为什么要校勘constructor,只可以算得为了科学的来得原型链吧,它并不会影响 instanceof 的判别。或许有任何更加深的道理小编并不知道……

9、封装拖拽对象

在前头意气风发章作者给大家大饱眼福了面向对象如何得以达成,基于那个底蕴知识,我们来将地点实现的拖拽封装为二个拖拽对象。大家的对象是,只要大家声雅培(Abbott卡塔 尔(英语:State of Qatar)个拖拽实例,那么传入的靶子成分将电动具备能够被拖拽的机能。

在事实上付出中,八个指标大家平常会独自放在二个js文件中,这些js文件将独立作为一个模块,利用各样模块的方法协会起来使用。当然这里未有复杂的模块交互作用,因为那一个事例,大家只需求叁个模块就可以。

为了防止变量污染,我们须求将模块放置于八个函数自实践措施模拟的块级效能域中。

JavaScript

; (function() { ... })();

1
2
3
4
;
(function() {
    ...
})();

在日常的模块组织中,我们只是单纯的将过多js文件收缩成为三个js文件,由此这里的第三个分行则是为着幸免上二个模块的末梢不用分号招致报错。重中之重。当然在经过require或然ES6模块等艺术就不会自然则然那样的景况。

我们领略,在包装八个目的的时候,大家得以将质量与方法放置于构造函数可能原型中,而在增添了自实践函数之后,我们又有啥不可将质量和方法制止与模块的当中功能域。这是闭包的学问。

那么我们面前际遇的挑衅就在于,如何客观的拍卖属性与情势的岗位。

自然,每一个对象的景色都不平等,无法一视同仁,大家要求显著的知晓这三种职位的特征本事做出最相符的决定。

  • 构造函数中: 属性与方法为眼下实例单独具有,只好被眼下实例访谈,况且每声雅培(Abbott卡塔 尔(阿拉伯语:قطر‎个实例,在那之中的点子都会被重新创立一次。
  • 原型中: 属性与措施为富有实例协同具备,能够被有着实例访谈,新注解实例不会再度成立方法。
  • 模块成效域中:属性和方法不能被别的实例访谈,可是能被里面方法访谈,新表明的实例,不会重新创造相同的秘诀。

对此艺术的论断比较简单。

因为在构造函数中的方法总会在声贝因美个新的实例时被重新创造,由此我们注解的办法都尽量制止出现在构造函数中。

而只要你的章程中必要用到构造函数中的变量,可能想要公开,那就要求放在原型中。

后生可畏旦艺术必要个人不被外边访问,那么就停放在模块功效域中。

对此属性放置于怎么样地点有个别时候很难做出准确的论断,由此作者很难交付叁个纯正的概念告诉您怎样性质应当要放在什么地点,那亟需在事实上付出中连连的下结论经历。然则综上可得,还是要结合那多少个地点的特征来做出最合适的决断。

若果属性值只可以被实例单独具有,举例person对象的name,只可以归属某三个person实例,又举例此处拖拽对象中,某二个因素的伊始地方,也仅仅只是那一个因素的脚失去工作位,那性子情,则切合放在构造函数中。

而要是两本品质仅仅供内部方法访谈,这么些性情就相符放在模块效率域中。

关于面向对象,下边的几点考虑本身感到是那篇作品最值得认真思考的精髓。借使在封装时没有思虑清楚,很也许会遇见大多您意外的bug,所以提议大家结合自身的付出阅世,多多思谋,计算出自个儿的观点。

依据那个寻思,我们能够友善尝尝封装一下。然后与本身的做一些比照,看看大家的主张有哪些两样,在底下例子的注释中,笔者将和睦的主见表明出来。

点击查阅已经封装好的demo

js 源码

JavaScript

; (function() { // 那是三个私有属性,没有供给被实例访问 var transform = getTransform(); function Drag(selector) { // 放在构造函数中的属性,都以归于每个实例单独具有 this.elem = typeof selector == 'Object' ? selector : document.getElementById(selector); this.startX = 0; this.startY = 0; this.sourceX = 0; this.sourceY = 0; this.init(); } // 原型 Drag.prototype = { constructor: Drag, init: function() { // 最初时供给做些什么职业 this.setDrag(); }, // 稍作更换,仅用于获取当前因素的质量,相近于getName getStyle: function(property) { return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property]; }, // 用来取伏贴前成分之处消息,注意与事先的分歧的地方 getPosition: function() { var pos = {x: 0, y: 0}; if(transform) { var transformValue = this.getStyle(transform); if(transformValue == 'none') { this.elem.style[transform] = 'translate(0, 0)'; } else { var temp = transformValue.match(/-?d+/g); pos = { x: parseInt(temp[4].trim()), y: parseInt(temp[5].trim()) } } } else { if(this.getStyle('position') == 'static') { this.elem.style.position = 'relative'; } else { pos = { x: parseInt(this.getStyle('left') ? this.getStyle('left') : 0), y: parseInt(this.getStyle('top') ? this.getStyle('top') : 0) } } } return pos; }, // 用来安装当前因素的地方 setPostion: function(pos) { if(transform) { this.elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)'; } else { this.elem.style.left = pos.x + 'px'; this.elem.style.top = pos.y + 'px'; } }, // 该措施用来绑定事件 setDrag: function() { var self = this; this.elem.add伊芙ntListener('mousedown', start, false); function start(event) { self.startX = event.pageX; self.startY = event.pageY; var pos = self.getPosition(); self.sourceX = pos.x; self.sourceY = pos.y; document.addEventListener('mousemove', move, false); document.addEventListener('mouseup', end, false); } function move(event) { var currentX = event.pageX; var currentY = event.pageY; var distanceX = currentX - self.startX; var distanceY = currentY - self.startY; self.setPostion({ x: (self.sourceX + distanceX).toFixed(), y: (self.sourceY + distanceY).toFixed() }) } function end(event) { document.remove伊夫ntListener('mousemove', move); document.removeEventListener('mouseup', end); // do other things } } } // 私有方法,仅仅用来获取transform的合营写法 function getTransform() { var transform = '', divStyle = document.createElement('div').style, transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'], i = 0, len = transformArr.length; for(; i < len; i++) { if(transformArr[i] in divStyle) { return transform = transformArr[i]; } } return transform; } // 生龙活虎种对外暴光的办法 window.Drag = Drag; })(); // 使用:申明2个拖拽实例 new Drag('target'); new Drag('target2');

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
;
(function() {
    // 这是一个私有属性,不需要被实例访问
    var transform = getTransform();
 
    function Drag(selector) {
        // 放在构造函数中的属性,都是属于每一个实例单独拥有
        this.elem = typeof selector == 'Object' ? selector : document.getElementById(selector);
        this.startX = 0;
        this.startY = 0;
        this.sourceX = 0;
        this.sourceY = 0;
 
        this.init();
    }
 
 
    // 原型
    Drag.prototype = {
        constructor: Drag,
 
        init: function() {
            // 初始时需要做些什么事情
            this.setDrag();
        },
 
        // 稍作改造,仅用于获取当前元素的属性,类似于getName
        getStyle: function(property) {
            return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property];
        },
 
        // 用来获取当前元素的位置信息,注意与之前的不同之处
        getPosition: function() {
            var pos = {x: 0, y: 0};
            if(transform) {
                var transformValue = this.getStyle(transform);
                if(transformValue == 'none') {
                    this.elem.style[transform] = 'translate(0, 0)';
                } else {
                    var temp = transformValue.match(/-?d+/g);
                    pos = {
                        x: parseInt(temp[4].trim()),
                        y: parseInt(temp[5].trim())
                    }
                }
            } else {
                if(this.getStyle('position') == 'static') {
                    this.elem.style.position = 'relative';
                } else {
                    pos = {
                        x: parseInt(this.getStyle('left') ? this.getStyle('left') : 0),
                        y: parseInt(this.getStyle('top') ? this.getStyle('top') : 0)
                    }
                }
            }
 
            return pos;
        },
 
        // 用来设置当前元素的位置
        setPostion: function(pos) {
            if(transform) {
                this.elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)';
            } else {
                this.elem.style.left = pos.x + 'px';
                this.elem.style.top = pos.y + 'px';
            }
        },
 
        // 该方法用来绑定事件
        setDrag: function() {
            var self = this;
            this.elem.addEventListener('mousedown', start, false);
            function start(event) {
                self.startX = event.pageX;
                self.startY = event.pageY;
 
                var pos = self.getPosition();
 
                self.sourceX = pos.x;
                self.sourceY = pos.y;
 
                document.addEventListener('mousemove', move, false);
                document.addEventListener('mouseup', end, false);
            }
 
            function move(event) {
                var currentX = event.pageX;
                var currentY = event.pageY;
 
                var distanceX = currentX - self.startX;
                var distanceY = currentY - self.startY;
 
                self.setPostion({
                    x: (self.sourceX + distanceX).toFixed(),
                    y: (self.sourceY + distanceY).toFixed()
                })
            }
 
            function end(event) {
                document.removeEventListener('mousemove', move);
                document.removeEventListener('mouseup', end);
                // do other things
            }
        }
    }
 
    // 私有方法,仅仅用来获取transform的兼容写法
    function getTransform() {
        var transform = '',
            divStyle = document.createElement('div').style,
            transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
 
            i = 0,
            len = transformArr.length;
 
        for(; i < len; i++)  {
            if(transformArr[i] in divStyle) {
                return transform = transformArr[i];
            }
        }
 
        return transform;
    }
 
    // 一种对外暴露的方式
    window.Drag = Drag;
})();
 
// 使用:声明2个拖拽实例
new Drag('target');
new Drag('target2');

如此那般一个拖拽对象就封装完结了。

提议大家遵照自身提供的研究方法,多多尝试封装一些零零部件。举例封装一个弹窗,封装一个周而复始轮播等。练得多了,面向对象就不再是难题了。这种思维方法,在今后别的时候都以还可以的。

下生机勃勃章分析jQuery对象的贯彻,与哪些将大家那边封装的拖拽对象增加为jQuery插件。

2 赞 1 收藏 评论

图片 2

示例

第豆蔻梢头,你须求在页面上内定AppCache的配置文件:

XHTML

<!DOCTYPE html> <html manifest="manifest.appcache"> ... </html>

1
2
3
4
<!DOCTYPE html>
<html manifest="manifest.appcache">
...
</html>

在这里地绝对记得在服务器端公布上述配置文件的时候,必要将MIME类型设置为text/cache-manifest,不然浏览器不可能不荒谬剖判。

接下去是创设以前定义好的种种财富。大家假若在此个示例中,你付出的是二个相互类站点,客户能够在地点联系外人并且发布争辩。顾客在离线的处境下仍旧得以访谈网址的静态部分,而关系以至发布批评的页面则会被别的页面代替,不可能访问。

好的,大家那就起初定义那多少个静态能源:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html /portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg /info.html /style.css /main.js /jquery.min.js

1
2
3
4
5
6
7
8
9
10
11
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js

旁注:配置文件写起来有一点点特不便利。譬释迦牟尼讲,假若你想缓存整个目录,你不可能一贯在CACHE部分应用通配符(*卡塔 尔(阿拉伯语:قطر‎,而是只可以在NETWO奥迪Q5K部分应用通配符把全数不应有被缓存的财富写出来。

你不须求显式地缓存包蕴配置文件的页面,因为那么些页面会自动被缓存。接下来大家为调换和商议的页面定义FALLBACK部分:

JavaScript

FALLBACK: /contact.html /offline.html /comments.html /offline.html

1
2
3
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html

最终大家用一个通配符来阻止别的的财富被缓存:

JavaScript

NETWORK: *

1
2
NETWORK:
*

末尾的结果便是下边那样:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html /portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg /info.html /style.css /main.js /jquery.min.js FALLBACK: /contact.html /offline.html /comments.html /offline.html NETWORK: *

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js
 
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html
 
NETWORK:
*

还会有生龙活虎件很要紧的事体要记得:你的财富只会被缓存叁回!也便是说,假使财富立异了,它们不会自动更新,除非您改改了安顿文件。所以有三个特级实行是,在布署文件中扩大大器晚成项版本号,每一遍换代能源的时候顺便更新版本号:

JavaScript

CACHE MANIFEST # version 1 CACHE: ...

1
2
3
4
5
6
CACHE MANIFEST
 
# version 1
 
CACHE:
...

本文由澳门新葡亰平台官网发布于web前端,转载请注明出处:前端基础进阶,Web应用中的离线数据存储

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。