首先最应该说的就是pwa的应用安装了。先看下显示条件:这个应用安装可以理解为网页的快捷入口,不过更像是应用而不是网页。原生应用就不用说了。
显示应用安装横幅的条件:
浏览器在 PWA 站点满足以下条件时会自动显示横幅:
站点部署 manifest.json,该文件需配置如下属性:
short_name (用于主屏幕显示)
name (用于安装横幅显示)
icons (其中必须包含一个 mime 类型为 image/png 的图标声明)
start_url (应用启动地址)
display (必须为 standalone 或 fullscreen)
站点注册 Service Worker。
站点支持 HTTPS 访问。
站点在同一浏览器中被访问至少两次,两次访问间隔至少为 5 分钟。
显示原生应用安装横幅的条件
浏览器在 PWA 站点满足以下条件时会自动显示横幅:
站点部署 manifest.json,该文件需配置如下属性:
short_name (用于主屏幕显示)
name (用于安装横幅显示)
icons (其中必须包含一个 192x192 且 mime 类型为 image/png 的图标声明)
包含原生应用相关信息的 related_applications 对象
站点注册 Service Worker。
站点支持 HTTPS 访问。
站点在同一浏览器中被访问至少两次,两次访问间隔至少为 2 天。
其中 related_applications 的定义如下:
related_applications: Array. 关联应用列表
AppInfo 的属性值包括:
platform: {string} 应用平台
id: {string} 应用id
beforeinstallprompt
事件。事件mdn。 <button hidden id="installBtn">安装应用button>
<script>
window.addEventListener('load', function () {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js');
}
let appPromptEvent = null;
const installBtn = document.getElementById('installBtn');
window.addEventListener('beforeinstallprompt', function (event) {
console.log('触发事件:beforeinstallprompt');
event.preventDefault();
appPromptEvent = event;
installBtn.hidden = false;
return false;
});
installBtn.addEventListener('click', function () {
if (appPromptEvent !== null) {
console.log(appPromptEvent)
appPromptEvent.prompt();
appPromptEvent.userChoice.then(function (result) {
if (result.outcome === 'accepted') {
console.log('同意安装应用');
} else {
console.log('不同意安装应用');
}
appPromptEvent = null;
});
}
});
window.addEventListener('appinstalled', function () {
console.log('应用已安装');
installBtn.hidden = true;
});
});
script>
<link rel="manifest" href="./manifest.json">
manifest.json
{
"short_name": "短名称",
"name": "这是一个完整名称",
"icon": [
{
"src": "icon.png",
"type": "image/png",
"sizes": "48x48"
}
],
"start_url": "index.html"
}
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('./sw.js', {
scope: './' }).then(function(registration) {
// do domething...
}).catch(function(err) {
// do domething...
});
});
}
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('sw-cache').then(function(cache) {
return cache.addAll([
'/',
'/index.html',
'/main.css',
'/main.js',
'/image.jpg'
]);
})
);
});
self.addEventListener('install', function(event) {
self.skipWaiting();
//……
});
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
return cacheName != 'sw-cache';
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
});
self.addEventListener('activate', function(event) {
self.clients.claim()
//……
});
const serviceWorker = navigator.serviceWorker;
if (typeof serviceWorker.getRegistrations === 'function') {
serviceWorker.getRegistrations().then(function(registrations) {
registrations.forEach(function(registration) {
registration.unregister();
});
});
} else if (typeof serviceWorker.getRegistration === 'function') {
serviceWorker.getRegistration().then(function(registration) {
registration.unregister();
})
}
navigator.serviceWorker.register('./sw.js').then(function(registration) {
registration.addEventListener('updatefound', function() {
});
});
navigator.serviceWorker.addEventListener('controllerchange', function() {
});
const openRequest = window.indexedDB.open('TodoList', 1);
onupgradeneeded
获得event
回调来做:openRequest.onupgradeneeded = function(event) {
const db = event.target.result;
const todosStore = db.createObjectStore('todos', {
keyPath: 'id', autoIncrement : true });
todosStore.createIndex('status', 'status');
};
openRequest.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(['todos'], 'readonly');
const todosStore = transaction.objectStore('todos');
// ……
};
var transaction = db.transaction(["customers"], "readwrite");
db.transaction("customers").objectStore("customers").get("444-44-4444").onsuccess = function(event) {
alert("Name for SSN 444-44-4444 is " + event.target.result.name);
};
var request = db.transaction(["customers"], "readwrite")
.objectStore("customers")
.delete("444-44-4444");
request.onsuccess = function(event) {
// 删除成功!
};
先通过CacheStorage获取对象,然后通过Cache接口进行操作。
CacheStorage 接口
主要接口为:
open:获取指定名称的 Cache 对象。
keys:获取 CacheStorage 所有 Cache 对象中的 Response 条目键值列表。
has:判断是否存在指定名称的 Cache 对象。
delete:删除指定名称的 Cache 对象。
match:获取指定请求所对应的 Response 条目(如匹配到多个,则返回第一个)。
Cache 接口
match:获取指定请求所对应的 Response 条目(如匹配到多个,则返回第一个)。
matchAll:与 match 的唯一差别是该接口返回所有匹配项。
add:获取指定 URL 的资源,将返回的 Response 添加到 Cache 对象中。
addAll: 与 add 的唯一差别是该接口可以获取多个 URL 的资源,并将其依次添加到 Cache 对象中。
put:将指定 Request 的 Response 添加到 Cache 对象中。
delete: 删除指定 Request 的 Response 条目。
keys:获取指定 Request 的 Response 条目键值列表。