见意如题!本文主要来说说PWA开发!作为一个前端程序员,在没有任何Android/IOS的开发情况下,想想我们有多少种方法来开发一个原生移动应用程序!我们可以有非原生、混合开发,PWA等等手段。类似uniapp,Reactive native为我们提供了更简便的手段!抛开这些框架,我们该如何仅使用 HTML、CSS 和 Javascript 来开发一个多平台的标准移动程序!这就是本文要介绍的渐进式WEB应用程序(PWA)!
PWA
PWA(Progressive Web Apps,渐进式 Web 应用)运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序。这些应用无处不在、功能丰富,使其具有与原生应用相同的用户体验优势.
--MDN
通俗的说:PWA是风格类似移动应用程序的网站!它可以运行在浏览器中也可以直接安装在移动设备上!
PWA必须包含下面三个关键内容!
- Service Worker:它运行在一个与页面JavaScript主线程的独立线程上。它提供了离线功能,允许用户从网站下载和缓存设备上的文件。
- Web Manifest:实现了将PWA网页应用 添加至桌面的功。具体的配置文件manifest.json通常放在应用的根目录,包含类似应用标题、移动设备上的图标等安装信息!但该项技术目前仍处于实验性阶段,各浏览器支持度不高!
- HTTPS:HTTP是PWA强制要求的,用来保证程序的安全性!
优点
- 跨平台可用,可以安装和运行在跨各种系统各种设备上!
- 无需下载,我们只需要访问网址,添加到桌面即可!这样就不需要第三方商店的审核!
- 不需要开发Android和IOS两套代码!
劣势
- 浏览器支持存在差异,并不是所有浏览器都完美支持!
- 调用底层硬件比原生麻烦。
- 分发效果差,因为PWA不通过应用商店,这导致你的应用无法在应用商店展示搜索!
开发
上面我们介绍了PWA的一些基础概念,下面我们就来做一个爆火在各种教程的“待办事项管理-TODO”程序!
创建项目以及目录
📂 To-Do-List
📄 index.html
📄 index.css
📄 index.js
📄 sw.js
📂 asset
页面布局(HTML)
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metahttp-equiv="X-UA-Compatible"content="IE=edge"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><title>待办清单</title><linkrel="stylesheet"href="index.css"></head><body><header><h1>欢迎使用待办清单</h1><formid="todo-form"><inputtype="text"name="new-todo"id="new-todo"placeholder="请输入待办事项"/><buttonid="submit-todo">提交</button></form></header><main><h2>待办清单</h2><divid="todos"></div></main><scriptsrc="index.js"></script></body></html>
添加样式
操作/存储数据
IndexedDB是可以在浏览器访问的一个完整的数据库系统!这个数据库位于浏览器中而不是本地!
因为IndexedDB操作比较复杂,MDN推荐了localForage — 小而妙的 JavaScript 库,它能使客户端数据储存很简单;默认使用 IndexDB,在不支持 IndexedDB 的浏览器中还会降级使用 WebSQL 或 localStorage!
但也是因为他的这种降级处理,使得localForage更倾向于localStorage,仅仅是一个非常简单的键值对的存储,并没有对索引外键等的支持为了构建具有更复杂需求的数据库,我推荐使用PouchDB或Dexie 之类的东西。
这里使用第三方CDN。
<scriptsrc="https://npmcdn.com/dexie/dist/dexie.js"></script>
创建实例
这里我们创建了一个叫做ToDo的数据库,创建了一张todos的表。设置两个字段:自增主键id,todo。
const db = new Dexie("ToDo");
db.version(1).stores({ todos: "++id, todo" });
当我们刷新页面,打开开发者工具->Application->IndexedDB,可以看到我们创建的ToDo数据库!
提交事件
当按钮点击,获取input的值,然后使用add方法,添加当前数据!因为ID是自增的,所以我们不需要赋值!
const form = document.querySelector("#todo-form");const btn = document.querySelector("#submit-todo");
btn.onclick=async(event)=>{const todo = input.value;await db.todos.add({ todo });awaitshowTodos();
form.reset();};
展示数据
定义getTodos方法来获取数据,默认取出的顺序是写入的顺序,我们需要反转才能让新添加的待办事项位于前面!
const getTodos = () => {
return db.todos.reverse().toArray();
}
const showTodos = async () => {
const todos = await getTodos();
todos_el.innerHTML = todos && todos.map((todo) => `
<div class="todo">
<div class="content">
<p class="text" readonly="readonly" type="text" >${todo.todo}</p>
</div>
<div class="actions">
<button class="delete" οnclick="deleteTodo(event, ${todo.id})">删除</button>
</div>
</div>
`
).join("");
};
删除数据
const deleteTodo = async (event, id) => {
await db.todos.delete(id);
await showTodos();
};
配置manifest.json
在MDN上指出,可安装PWA必须存在一个配置清单。>>> https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Installable_PWAs, 具体的字段可以参照这个文档!
name
: 网站应用的全名。short_name
: 显示在主屏上的短名字。description
: 一两句话解释你的应用的用途。icons
: 一串图标信息:源 URL,大小和类型。多包含几个图标,这样就能选中一个最适合用户设备的。start_url
: 启动应用时打开的主页。display
: 应用的显示方式;可以是fullscreen
、standalone
、minimal-ui
或者browser
。theme_color
: UI 主颜色,由操作系统使用。background_color
: 背景色,用于安装和显示启动画面时。
{"name":"Todo PWA","short_name":"ToDo","icons":[{"src":"./assets/icon-100.png","sizes":"100x100","type":"image/png"},{"src":"./assets/icon-150.png","sizes":"150x150","type":"image/png"},{"src":"./assets/icon-250.png","sizes":"250x250","type":"image/png"}],"theme_color":"#FFFFFF","background_color":"#FFFFFF","start_url":"/PWA-Todo/","display":"standalone"}
最后我们还需要在index.html引入
<linkrel="manifest"href="manifest.json"/>
注册 Service Worker
上面我们提供了安装所需的配置文件,但是仅仅也支持配置了,我们想要可以安装,还必须注册 Service Worker。
一个注册好的 Service Worker,可以让应用离线工作(这仅对于安卓设备上的 Chrome 浏览器是必需的)
我们在sw.js中来添加service worker的事件,然后再index.js中注册。
详细的设置,请参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
install
事件一般是被用来填充你的浏览器的离线缓存能力。这里我们将文件加入到缓存中!fetch
自定义请求,每次任何被 service worker 控制的资源被请求到时,都会触发fetch
事件,这些资源包括了指定的 scope 内的文档,和这些文档内引用的其他任何资源(比如index.html
发起了一个跨域的请求来嵌入一个图片,这个也会通过 service worker 。)
const todo ="todo";const assets =["/","./index.html","./index.css","./index.js","./assets/icon-100.png","./assets/icon-150.png","./assets/icon-250.png",];
self.addEventListener("install",installEvent=>{
installEvent.waitUntil(
caches.open(todo).then(cache=>{
cache.addAll(assets);}));});
self.addEventListener("fetch",fetchEvent=>{
fetchEvent.respondWith(
caches.match(fetchEvent.request).then(res=>{return res ||fetch(fetchEvent.request);}));});
index.js注册:
window.onload=()=>{showTodos();if("serviceWorker"in navigator){
navigator.serviceWorker
.register("./sw.js").then(res=> console.log("注册serviceWorker:成功")).catch(err=> console.log("注册serviceWorker:失败", err));}};
安装
PC chrome
打开PC Chrome浏览器,我们会发现在上方搜素框右边出现了一个下载按钮,如果你已经安装过了,则会编程一个箭头。至此我们已经成功的完成了PWA的开发,发布,安装!
移动Chrome
打开移动端的Chrome,可以通过菜单中的添加到主屏幕,将程序安装到本地!
国产浏览器
支持添加网址到桌面的浏览器:360浏览器、搜狗浏览器、UC浏览器、华为浏览器、QQ浏览器。但是这种方式,其实类似window的添加快捷方式,而Chrome的体验就是实打实的安装一个软件!
以UC浏览器为例:
我们打开网站,找到收藏网址:
版权归原作者 搞前端的半夏 所有, 如有侵权,请联系我们删除。