离线检测
该小结重点:一个属性(navigator.online)两个事件(online/offline)
navigator.onLine: true->设备能上网;false->设备离线。
navigator.onLine 在不同浏览器间有小差异
- IE6+ Safari5+ 能正确应用
- Firefox3+ Opera10.6+ 手动设置“文件->Web开发人员(设置)->脱机工作”
- Chrome11及之前 navigator.onLine 始终为true
if (navigator.onLine) {
// 正常工作
} else {
// 执行离线状态时的任务
}
online: 当网络从离线变为在线时(在window对象上)触发该事件
offline: 当网络从在线变为离线时(在window对象上)触发该事件
EventUtil.addHandler(window, 'online', function() {
alert('Online')
})
EventUtil.addHandler(window, 'offline', function() {
alert('Offline')
})
用法:
先通过 navigator.onLine 取得初始状态,
然后通过 online,offline 事件确定网络连接状态是否变化,
最后事件触发时,navigator.online属性的值也会改变,不过必须手工轮询这个属性才能检测到网络状态的变化
应用缓存
HTML5的应用缓存(appplication cache)简称appcache,是专门为开发离线Web应用设计的
Appcache是从浏览器缓存中分出来的一块缓存区
要想在这个缓存区保存数据可以使用一个描述文件(manifest file),列出要下载和缓存的资源
将描述文件和页面关联起来: 在manifest属性中指定这个文件路径
<html manifest="/offline.manifest">
这个文件的MIME类型必须是 text/cache-manifest
描述文件的扩展名推荐使用已从 manifest 改为 appcache
离线API核心对象applicationCache对象的status属性和相关事件:
0: 无缓存
1: 闲置 即应用缓存未得到更新
2: 检查中 即正在下载描述文件并检查更新
3: 下载中 即应用缓存正在下载描述文件中指定资源
4: 更新完成 即资源已更新且下载完毕,可以通过swapCache()使用
5: 废弃 即应用缓存的描述文件已经不存在,页面无法再访问应用缓存
表示状态改变的事件:(会随着页面加载按顺序触发)
checking: 在浏览器为应用缓存查找更新时触发
error: 在检查更新或下载资源期间发生错误时触发
noupdate: 在检查描述文件发现文件无变化时触发
downloading: 在开始下载应用缓存的过程中触发
progress: 在文件下载应用缓存的过程中持续不断地触发
updateready: 在页面新的应用混啊村下载完毕且可以通过swapCache()使用时触发
cached: 在应用缓存完整时触发
applicationCache.update()
手动干预让应用缓存为检查更新触发上述事件
EventUtil.addHandler(applicationCache, 'updateready', function(){
applicationCache.swapCache()
})
// 在firefox4及之前版本调用swapCache()会抛出错误
数据存储
Cookie
1.可以作为响应的一部分
2.浏览器存储后为每个请求添加Cookies HTTP头将信息发回服务器
3. 用于唯一验证客户
1.限制
1.cookie在性质上是绑定在特定域名下的
2.每个域的cookie总数有限
- Firefox限制50个cookie每个域
- Opera限制30个
- Safari和Chrome没有硬性规定
3.浏览器对cookie的尺寸有限制,约4096B(一个域下所有cookie)
2.cookie的构成
名称、值、域、路径(可以指定cookie只有从xx域中才能访问)、失效时间、安全标志(指定后cookie只有使用SSL连接时才能发送,如https能http不能)
只有名值对会发送到服务器
// 示例
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Mon, 22-Jan-07 GMT; domain=.wrox.com; path=/; secure
Other-header: other-header-value
3.JavaScript中的cookie
1.document.cookie
- 获取属性值时,document.cookie返回当前页面可用的所有cookie的字符串,如
name1=value1;name2=value2;name3=value3……
所有名字和值都是经过URL编码的,所以必须使用decodeURIComponent()来解吗- 设置属性值时,和Set-Cookie头中格式一样
name=value; expires=expiration_time; path=domain_path; secure (只有名字和值是必须的)
document.cookie = encodeURIComponent('name') + '=' + encodeURIComponent('Nicholas')
追加更多信息时
document.cookie = encodeURIComponent('name') + '=' + encodeURIComponent('Nicholas') + "; domain=.wrox.com; path=/";2.cookie函数操作
- 读取
- 写入
- 删除
var CookieUtil = {
// 读取
get: function (name) {
var cookieName = encodeURIComponent(name) + '=',
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null
if (cookieStart > -1) {
var cookieEnd = document.cookie.indexOf(';', cookieStart)
if (cookieEnd == -1) {
cookieEnd = document.cookie.length
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd))
}
return cookieValue
},
// 写入
set: function (name, value, expires, path, domain, secure) {
var cookieText = encodeURIComponent(name) + '=' +
encodeURIComponent(value)
if (expires instanceof Date) {
cookieText += ";expires=" + expires.toGMTString()
}
if (path) {
cookieText += ";path=" + path
}
if (domain) {
cookieText += ";domain=" + domain
}
if (secure) {
cookieText += ";secure"
}
document.cookie = cookieText
},
// 删除
unset: function (name, path, domain, secure) {
this.set(name, "", new Date(0), path, domain, secure)
}
// 使用
// 设置cookie
CookieUtil.set('name', 'Nike')
CookieUtil.set('book', 'Professional JavaScript')
// 读取cookie的值
alert(CookieUtil.get('name')) // 'Nike'
alert(cookieUtil.get('book')) // 'Professional JavaScript'
// 删除cookie
CookieUtil.unset('name')
cookieUtil.unset('book')
// 设置cookie, 包括它的路径、域、失效日期
CookieUtil.set('name', 'Nike', '/books/projs/', 'www.wrox.com', new Date('January 1, 2010'))
// 删除刚刚设置的cookie
CookieUtil.unset('name', '/books/projs/', 'www.wrox.com')
// 设置安全的cookie
CookieUtil.set('name', 'Nike', null, null, null, true)
}
4.子cookie
var SubCookieUtil = {
get: function (name, subName){
var subCookies = this.getAll(name)
if (subCookies) {
return subCookies(subName)
} else {
return null
}
},
getAll: function (name) {
var cookieName = encodeURIComponent(name) + '=',
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null,
cookieEnd,
subCookies,
i,
parts,
result = {}
if (cookieStart > -1) {
cookieEnd = docoment.cookie.indexOf(';', cookieStart)
if (cookieEnd == -1) {
cookieEnd = document.cookie.length
}
cookieValue = document.cookie.substr(cookieStart + cookieName.length, cookieEnd)
}
if (cookieValue.length > 0) {
subCookies = cookieValue.split('&')
for(i=0, len=subCookies.length; i<len; i++){
parts = subCookies[i].split('=')
result[decodeURIComponent(parts[0])] =
decodeURIComponent(parts[1])
}
return result
}
}
return null
}
// 使用
// 假设document.cookie=data=name=Nicholas&book=Professional%20JavaScript
// 取得全部子cookie
var data = SubCookieUtil.getAll('data')
alert(data.name) // 'Nicholas'
alert(data.book) // 'Professional JavaScript'
// 逐个获取子cookie
alert(SubCookieUtil.get('data', 'name')) // 'Nicholas'
alert(SubCookieUtil.get('data', 'book')) // 'Professional JavaScript'
// 要设置子cookie,也有两种方法:set()和setAll()。
// 以下代码展示了它们的构造
var SubCookieUtil = {
// cookie名称 子cookie名称 子cookie值 可选的cookie失效日期或时间的Data对象 可选的cookie路径 可选的cookie域和可选的布尔secure标志
set: function (name, subName, value, expires, path, domain, secure) {
var subcookies = this.getAll(name) || {}
subcookies[subName] = value
this.setAll(name, subcookies, expires, path, domain, secure)
}
setAll: function (name, subcookies, expires, path, domain, secure) {
var cookiesText = encodeURIComponent(name) + '=',
subcookieParts = new Array(),
subName;
for (subName in subcookies) {
if (subName.length > 0 && subcookies.hasOwnProperty(subName)) {
subcookieParts.push(encodeURIComponent(subName) + '=' +
encodeURIComponent(subcookies[subName]))
}
}
if (cookieParts.length > 0) {
cookieText += subcookieParts.join('&')
if (expires instanceof Data) {
cookieText += ";expires=" + expires.toGMTString()
}
if (path) {
cookieText += ";path=" + path
}
if (domain) {
cookieText += ";domain=" + domain
}
if (secure) {
cookieText += ";secure"
}
} else {
cookieText += ";expires=" + (new Date(0).toGMTString())
}
document.cookie = cookieText
},
// 省略了更多代码
}
// 使用
// 假设document.cookie=data=name=Nicholas&book=Professional%20JavaScript
// 设置两个cookie
SubCookieUtil.set('data', 'name', 'Nicholas')
SubCookieUtil.set('data', 'book', 'Professional JavaScript')
// 设置全部子cookie和失效日期
SubCookieUtil.setAll('data', { name: 'Nicholas', book: 'Professional JavaScript' }, new Date('January 1, 2010'))
// 修改名字的值,并修改cookie的失效日期
SubCookieUtil.set('data', 'name', 'Michael', new Date('February 1, 2010'))
// 普通cookie可以通过设置失效时间为过去的时间来删除,但是子cookie不行
// 删除子cookie必须先获取包含在某个cookie中的所有子cookie然后仅删除需要删除的子cookie最后将余下cookie保存
var SubCookieUtil = {
// 这里省略了很多代码
// 删除某个子cookie
unset: function(name, subName, path, domain, secure) {
var subcookies = this.getAll(name)
if (subCookies) {
delete subcookies[subName]
this.setAll(name, subcookies, null, path, domain, secure)
}
},
// 删除整个cookie
unsetAll: function (name, path, domain, secure) {
this.setAll(name, null, new Date(0), path, domain, secure)
}
}
// 使用
// 仅删除名为name的子cookie
SubCookieUtil.unset('data', 'name')
// 删除整个cookie
SubCookieUtil.unsetAll('data')
5.关于cookie的思考
1."HTTP专有cookie"只能从服务器读取
2.cookie会作为请求头发送,太大会影响性能
3.不要在cookie存储重要和敏感信息
IE用户数据
Web存储机制
Web Storage的主要两个目的:
1.提供一种在cookie之外存储会话数据的途径
2.提供一种存储大量可以跨会话存在的数据的机制
最初的Web Storage规范包含了两种对象的定义:sessionStorage 和 globalStorage
1.Storage类型
方法:
clear(): 删除所有值Firefox没有实现
getItem(name): 根据指定的名字name获取对应值
key(index): 获得index位置处的值的名字
removeItem(name): 删除由name指定的名值对儿
setItem(name, value): 为指定的name设置一个对应的值
2.sessionStorage对象
seeesionStorage其实是Storage的一个实例
该数据只保持到浏览器关闭,浏览器关闭后消失,但浏览器刷新后依旧存在
该数据只能最初给对象存储数据的页面访问到,跨页面有限制
// 使用方法存储数据
sessionStorage.setItem('name', 'Nicholas')
// 使用属性存储数据
sessionStorage.book = 'Professional JavaScript'
// 使用方法读取数据
var name = sessionStorage.getItem('name')
// 使用属性读取数据
var book = sessionStorage.book
// 通过length属性和key()方法来迭代sessionStorage的值
for (var i=0, len=sessionStorage.length; i<len; i++) {
var key = sessionStorage.key(i)
var value = sessionStorage.getItem(key)
alert(key + '=' + alue)
}
// 或者用for-in来循环迭代sessionStorage的值
for (var key in sessionStorage) {
var value = sessionStorage.getItem(key)
alert(key + '=' + value)
}
// 使用delete删除一个值--在wenkie中无效
delete sessionStorage.name
// 使用方法删除一个值
sessionStorage.removeItem('book')
3.globalStorage对象
如果不使用removeItem()或者delete删除,或者用户未清除浏览器缓存,存储在globalStorage属性中的数据会一直保留在磁盘中
// 可以指定哪些域可以访问
// 保存数据
globalStorage['wrox.com'].name = 'Nicholas'
// 获取数据
var name = globalStorage['wrox.com'].name
// 存储数据,任何人都可以访问(不要这样做)
globalStorage[''].name = 'Nicholas'
// 存储数据们可以让任何以.net结尾的域名访问(不要这样做)
globalStorage['net'].name = 'Nicholas'
// globalStorage的每个属性都是Storage的实例
globalStorage['www.wrox.com'].name = 'Nocholas'
globalStorage['www.wrox.com'].book = 'Profession JavaScript'
globalStorage['www.wrox.com'].removeItem('name')
var book = globalStorage['www.wrox.com'].getItem('book')
// 如果不确定域名,可以用location.host作为域名
globalStorage[location.host].name = 'Nocholas'
var book = globalStorage[location.host].getItem('book')
4.localStorage对象
要访问同一个localStorage对象,页面必须来自同一个域名(子域名无效),使用同一种协议,在同一个端口上。相当于globalStorage[location.host]
存储在localStorage中的数据和存储在globalStorage中的数据一样,都遵循相同规则:数据保留到JS删除或者用户清除浏览器缓存
不能指定任何访问规则
// 使用方法存储数据
localStorage.setItem('name', 'Nicholas')
// 使用属性存储数据
localStorage.book = 'Professional JavaScript'
// 使用方法读取数据
var name = localStorage.getItem('name')
// 使用属性读取数据
var book = localStorage.book
// 兼容只支持globalStorage的浏览器
function getLocalStorage() {
if (typeof localStorage == 'object' ) {
return localStorage
} else if(typeof globalStorage == 'object') {
return globalStorage[location.host]
} else {
throw new Error('Local storage not available')
}
}
var storage = getLocalStorage()
5.storage事件
无论对sessionStorage、globalStorage还是localStorage进行操作,都会触发该事件
该事件有以下属性:
domain: 发生变化的存储空间的域名
key: 设置或删除的键名
newValue: 如果是设置值,则是新值;如果是删除,则是null
oldValue: 键被更改之前的值
// 监听storage事件
EventUtil.addHandler(document, 'storage', function(event) {
alert('Storage changed for ' + event.domain)
})
6.限制
http://dev-test.nemikor.com/web-storage/support-test
IndexedDB
1.数据库
全称:Indexed Database API,是在浏览器中保存结构化数据的一种数据库。
IndexedDB设计的操作完全是异步进行的
差不多每一次操作IndexedDB操作都需要注册onerror 或 onsucdess事件处理程序
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB
最大特色:使用对象保存数据,而不是表
// 1.与数据库建立连接
var request, database
request = indexedDB.open('admin');
request.onerror = function (event) {
alert('Something bad happened while trying to open: ' + event.target.errorCode)
}
request.onsuccess = function (event) {
database = event.target.result
}
// 指定版本号
if (database.version != '1.0') {
request = database.setVersion('1.0')
request.onerror = function (event) {
alert('Something bad happened while trying to set version: ' + event.target.errorCode)
}
request.onsuccess = function(event) {
alert('Database initialization complate. Database name: ' + database.name + ',version: ' + database.version)
}
} else {
alert('Database already initialized. Database name: ' + database.name + ',version: ' + datbase.version)
}
2.对象存储空间
// 2.使用对象存储空间
// 创建一条记录
var user = {
username: '007',
firstName: 'James',
lastName: 'Bond',
psaaword: 'foo'
}
// 保存上述记录并创建对象存储空间
var store = db.createObjectStore('user', { keyPath: 'username' })
// users保存着一批用户对象
var i = 0,
len = user.length
while (i < len) {
store.add(users[i++])
}
// users中保存着一批用户对象
var i = 0,
request,
requests = [],
len = users.length
while (i < len) {
request = store.add(users[i++])
request.onerror = function() {
// 处理错误
}
request.onsuccess = function () {
// 处理成功
}
requests.push(request)
}
3.事物
想要读取或者修改数据,都要通过事务来组织所有操作
// 创建事务
// db database 数据库对象
// 加载所有数据(只读)
var transaction = db.transaction()
// 加载users存储空间中的数据(只读)
var transaction = db.transaction('users')
// 访问多个对象的存储空间(只读)
var transaction = db.transaction(['users', 'anotherStore'])
// IDBTransaction接口定义常量:只读 READ_ONLY(0) 读写 READ_WRITE(1) 改变 VERSION_CHANGE(2)
// IDBTransaction IE10+ Firefox4+ webkitIDBTransaction Chrome
var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction
// 读写
var transaction = db.transaction('users', IDBTransaction.READ_WRITE)
// 使用objectStore()方法并传入存储空间名称,可以访问特定的存储空间。
// get()取得值 delete()删除对象 clear()删除所有对象
var request = db.transaction('users').objectStore('users').get('007')
request.onerror = function (event) {
alert('Did not get the object!')
}
request.onsuccess = function (event) {
var result = event.target.result
alert(result.firstName) // 'James'
}
// 提供事务级的状态信息
transaction.onerror = function (event) {
// 整个事物都被取消
}
transaction.oncomplete = function (event) {
// 整个事务都成功完成
}
// incomplete事件的event访问不到get()请求返回的任何数据,必须onsuccess事件处理程序中才能访问到
4.使用游标查询
使用事务可以直接通过已知的键检索单个对象
在事务中创建游标,可以检索多个对象
游标就是指向结果集的指针
// openCursor()创建游标,返回的是一个请求对象,因此必须为该对象指定onsuccess和onerror事件处理程序
var store = db.transaction('users').objectStore('users'),
request = store.openCursor()
request.onsuccess = function (event) {
// 处理成功
// event.target.result可取得存储空间中的下一个对象
// 有值时是一个IDBCursor的实例,无值时为null
/* IDBCursor实例有以下几个属性:
** direction: 数值,表示游标移动的方向 。
** 默认值 IDBCursor.NEXT(0) 下一项
** IDBCursor.NEXT_NO_DUPLICATE(1) 下一个不重复的项
** DBCursor.PREV(2) 前一项
** IDBCursor.PREV_NO_DUPLICATE 前一个不重复的项
** key: 对象的键
** value: 实际的对象
** primaryKey: 游标使用的键。可能是对象键或索引键
**/
// 检索某一个对象的信息
request.onsuccess = function (event) {
var cursor = event.target.result
if (cursor) { // 必须要检查
// cursor.value是一个对象
console.log('Key: ' + cursor.key + ',Value: ' + JSON.stringify(cursor.value))
}
}
}
request.onerror = function (event) {
// 处理失败
}
// 调用update()也会创建一个新请求
// 调用update()方法可以用指定的对象更新当前游标的value
request.onsuccess = function (event) {
var cursor = event.target.result,
value,
updateRequest;
if (cursor) { // 必须要检查
if (cursor.key == 'foo') {
value = cursor.value // 取得当前的值
value.password = 'magic!' // 更新密码
updateRequest = cursor.update(value) // 请求保持更新
updateRequest.onsuccess = function () {
// 处理成功
}
updateRequest.onerror = function () {
// 处理失败
}
}
}
}
// 调用delete()也会创建一个新请求
// 调用delete()方法可以删除相应记录
request.onsuccess = function (event) {
var cursor = event.target.result,
value,
deleteRequest;
if (cursor) { // 必须要检查
if (cursor.key -== 'foo') {
deleteRequest = cursor.delete() // 请求删除当前项
deleteRequest.onsuccess = function () {
// 处理成功
}
deleteRequest.onerror = function () {
// 处理失败
}
}
}
}
// 如果当前事务没有修改对象存储空间,update()和delete()会抛出错误
/* 默认情况下,每个游标只发起一次请求。要想发起另一次请求,必须调用下面的一个方法:
** continue(key): 移动到“结果集”中的下一项。
** 参数key可选,不指定时游标移动到下一项,指定时游标移动到指定键的位置
** advance(count): 向前移动count指定的项数
**/
// 遍历了对象存储空间中的所有项
request.onsuccess = function (event) {
var cursor = event.target.result
if (cursor) { // 必须要检查
console.log('Key: ' + cursor.key + ', Value: ' + JSON.stringfy(cursor.value))
cursor.continue() // 移动到下一项
// 使用continue()会触发另一次请求
} else {
console.log('Done!')
}
}
5.键范围
键范围为使用游标增添了一些灵活性
IDBKeyRange IE10+ Firefox 4+ webkitIDBKeyRange Chrome
// 解决浏览器差异
var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange
// 四种定义键范围的方式
// 1.only() 传入想要取得的对象的键
var onlyRange = IDBKeyRange.only('007')
// 相当于直接访问存储空间并调用 get('007')
// 2.指定结果集的下界(游标开始的位置)
// 从键为 007 开始移动到最后
var lowerRange = IDBKeyRange.lowerBound('007')
// 从键为 007 的下一个对象开始移动到最后
var lowerRange = IDBKeyRange.lowerBound('007', true)
// 3.定义上界
// 从头开始到键为 ace 的对象为止
var upperRange = IDBKeyRange.upperBound('ace')
// 从头开始到键为ace的对象的上一个对象为止
var upperRange = IDBKeyRange.upperBound('ace', true)
// 4.同时指定上下界
// 从键 007 的对象开始到键为ace的对象为止
var boundRange = IDBKeyRange.bound('007', 'ace')
// 从键 007 的对象的下一个对象开始到键为ace的对象为止
var boundRange = IDBKeyRange.bound('007', 'ace', true)
// 从键 007 的对象的下一个对象开始到键为ace的对象的上一个对象为止
var boundRange = IDBKeyRange.bound('007', 'ace', true, true)
// 从键 007 的对象开始到键为ace的对象的上一个对象为止
var boundRange = IDBKeyRange.bound('007', 'ace', false, true)
// 定义键范围后传给openCursor()方法得到一个符合相应约束条件的游标
var store = db.transaction('users').objectStore('users'),
range = IDBKeyRange.bound('007', 'acs'),
request = store.openCursor(range)
request.onsuccess = function(event) {
var cursor = event.target.result
if (cursor) { // 必须要检查
console.log('Key: ' + cursor.key + ', Value: ' + JSON.stringfy(cursor.value))
cursor.continue()// 移动到下一项
} else {
console.log('Done!')
}
}
6.设定游标方向
1.IDBCursor.NEXT IDBCursor.NEXT_NO_DUPLICATE
游标从存储空间第一项开始,调用continue()或advance()前进到最后一项2.IDBCursor.PREV IDBCursor.PREV_NO_DUPLICATE
游标从存储空间最后一项开始,逐个迭代至第一个对象
使用上两项打开游标时,每次调用continue()或advance()都会在存储空间向后而不是向前移动openCursor()可以接收两个参数,第一个IDBKeyRange的实例,第二个表示方向的数值常量
// 消除浏览器差异
var IDBCursor = window.IDBCursor || window.webkitIDBCursor
// 方向默认参数是IDBCursor.NEXT 跳过重复项是IDBCursor.NEXT_NO_DUPLICATE
// 如果让游标跳过重复项
var store = db.transaction('users').objectStore('users'),
// null 包含所有对象
request = store.openCursor(null, IDBCursor.NEXT_NO_DUPLICATE)
var store = db.transaction('users').objectStore('users'),
// null 包含所有对象
request = store.openCursor(null, IDBCursor.PREV)
7.索引
例如要通过用户ID和用户名两种方式保存用户资料,需要通过这两个键来存取记录
可以将用户ID作为主键,为用户名创建索引
// 创建索引
var store = db.transaction('users').objectStore('users'),
index = store.createIndex('username', 'username', { unique: false })
// createIndex()第一个参数 索引的名字 第二个参数 索引的属性的名字 第三个参数 一个包含unique属性的选项对象
// 返回 IDBIndex 的实例
// 调用index()能返回同样的一个实例
var store = db.transaction('users').objectStore('users'),
index = store.index('username'),
request = index.openCursor();
request.onsuccess = function () {
// 处理成功
}
// 创建一个特殊的只返回每条记录主键的游标 openKeyCursor()
// 接收参数与openCursor()一样,但是event.result.key中保存着索引键,event.result.value 保存着主键
var store = db.transaction('users').objectStore('users'),
index = store.index('username'),
request = index.openKeyCursor();
request.onsuccess = function (event) {
// 处理成功
// event.result.key 保存索引键
// event.result.value 保存主键
}
// get()方法传入相应的索引键可以取得一个对象
var store = db.transaction('users').objectStore('users'),
index = store.index('username'),
request = index.get('007')
request.onsuccess = function (event) {
// 处理成功
}
request.onerror = function (event) {
// 处理失败
}
// getKey()方法可以根据给定的索引键取得主键
// event.result.value等于主键的值,而不是包含整个对象
var store = db.transaction('users').objectStore('users'),
index = store.index('username'),
request = index.getKey('007');
request.onsuccess = function (event) {
// 处理成功
// event.result.key 保存索引键 event.result.value 保存主键
}
/* 通过IDBIndex对象的下列属性都可以取得有关索引的相关信息
** name: 索引的名字
** keyPath: 传入的对象存储空间
** objectStore: 索引的对象存储空间
** unique: 表示索引键是否唯一的布尔值
**/
// 存储对象的 indexName 属性可以访问到为该空间建立的所有索引
// 编辑每个索引并打印信息
var store = db.transaction('users').objectStore('users'),
indexNames = store.indexNames,
index,
i = 0,
len = indexNames.length;
while (i < len) {
index = store.index(indexNames[i++])
console.log('Index name: ' + index.name + ', KeyPath: ' + index.keyPath + ', Unique: ' + index.unique)
}
// 删除索引
var store = db.transaction('users').objectStore('users');
store.deleteIndex('username')
// 删除索引不会影响对象存储空间中的数据,所以这个操作没有任何回调函数
8.并发问题
虽然IndexedDB提供的是异步API,但仍然存在并发问题
// 浏览器的两个不同的标签页打开了同一个页面,那么一个页面试图更新另一个页面尚未准备就绪
var request, database;
request = indexedDB.open('admin');
request.onsuccess = function (event) {
database = event.target.result
database.onversionchange = function() {
database.close()
}
}
// 想要更新数据库的版本但是另一个标签页已经打开数据库
var request = database.setVersion('2.0')
request.onblocked = function () {
alert('Please close all other tabs and again.')
}
request.onsuccess = function () {
// 处理成功,继续
}
9.限制
1.IndexedDB和Web Storage类似只能由同源(相同协议,域名和端口)页面操作,不能跨域共享信息
即www.wrox.com和p2p.wrox.com的数据库完全独立2.每个来源数据库占用磁盘空间有限
Firefox 4+ 50MB Chrome 5MB 移动端 Firefox超过5MB请求用户许可3.Firefox不允许本地文件访问IndexedDB
本文探讨了离线应用的检测方法,包括navigator.onLine属性和online/offline事件,以及HTML5应用缓存机制。深入讲解了Cookie的使用、限制和子Cookie的概念。介绍了IndexedDB数据库的使用,包括数据库操作、对象存储空间、事务处理、游标查询、键范围设定、索引创建和并发问题。
1102

被折叠的 条评论
为什么被折叠?



