首页 > 其他分享 >用PWA提升Web应用的性能和用户体验

用PWA提升Web应用的性能和用户体验

时间:2023-03-03 16:24:07浏览次数:56  
标签:Web transaction const completed PWA 体验 todo event png

 

 

 

PWA 是一种 Web 应用的新范式,它将 Web 应用和原生应用的体验结合在一起。PWA 可以让 Web 应用离线缓存、全屏模式、桌面快捷方式等,提供与原生应用类似的用户体验。此外,PWA 还能够通过 Service Worker 技术实现增量更新,提高 Web 应用的性能。

 

PWA 的优势不仅在于它可以提供类似于原生应用的体验,更重要的是它可以通过一系列技术手段提高 Web 应用的性能。PWA 可以在应用启动时预加载资源,这可以大大缩短应用的启动时间。PWA 还支持离线缓存,这可以让用户在没有网络连接的情况下继续使用应用,提高用户的满意度。

 

PWA 还可以使用本地通知、推送通知等功能,让用户更方便地接收到应用的消息和提醒,提高应用的互动性和用户留存率。此外,PWA 还支持桌面快捷方式,用户可以在桌面上直接启动应用,减少寻找应用的时间,提高用户的使用频率。

 

在使用PWA时,开发者需要注意一些细节,以确保应用的性能和用户体验。首先,需要考虑应用的加载速度,保证应用能够在最短时间内启动。其次,需要优化应用的缓存策略,确保用户能够在没有网络连接的情况下继续使用应用。最后,需要注意用户体验,尽可能提供与原生应用相似的体验,以吸引更多的用户。

 

以下是一个简单的 PWA 应用的 demo,它是一个待办事项应用,用户可以添加和管理自己的待办事项列表,并在需要时将它们标记为已完成。

 

首先,在 index.html 文件中,我们需要添加一个 manifest.json 文件的链接,以及一个 Service Worker 的注册脚本:

 

Markup
<!DOCTYPE html>
<html>
  <head>
    <title>PWA Todo App</title>
    <link rel="manifest" href="/manifest.json">
  </head>
  <body>
    <h1>Todo List</h1>
    <ul id="todo-list"></ul>
    <form>
      <input type="text" id="new-todo" placeholder="Add a new todo...">
      <button type="submit">Add</button>
    </form>
    
    <script src="/sw.js"></script>
    <script src="/app.js"></script>
  </body>
</html>

 

接下来,在 manifest.json 文件中,我们可以定义应用的名称、图标、主题色等信息:

 

Bash
{
  "name": "PWA Todo App",
  "short_name": "Todo App",
  "icons": [
    {
      "src": "/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#fff",
  "theme_color": "#3367D6"
}

 

然后,在 app.js 文件中,我们可以实现待办事项的添加、删除和标记为已完成等功能,同时使用 IndexedDB 存储数据:

 

JavaScript
const todoList = document.getElementById('todo-list');
const newTodoInput = document.getElementById('new-todo');
let db;
window.addEventListener('load', async () => {
  if ('serviceWorker' in navigator) {
    try {
      await navigator.serviceWorker.register('/sw.js');
    } catch (e) {
      console.log('SW registration failed');
    }
  }
  
  const request = indexedDB.open('todo-db', 1);
  request.onupgradeneeded = event => {
    db = event.target.result;
    db.createObjectStore('todos', { keyPath: 'id', autoIncrement: true });
  };
  request.onsuccess = event => {
db = event.target.result;
loadTodos();
};
async function loadTodos() {
const transaction = db.transaction(['todos'], 'readonly');
const store = transaction.objectStore('todos');
const todos = await store.getAll();
for (const todo of todos) {
addTodoToList(todo);
}
}
function addTodoToList(todo) {
const li = document.createElement('li');
li.dataset.id = todo.id;
li.innerText = todo.title;
if (todo.completed) {
li.classList.add('completed');
}
li.addEventListener('click', event => {
const completed = !li.classList.contains('completed');
updateTodoStatus(todo.id, completed);
li.classList.toggle('completed');
});
todoList.appendChild(li);
}
function addNewTodo() {
const title = newTodoInput.value;
if (title.trim() === '') {
return;
}
const transaction = db.transaction(['todos'], 'readwrite');
const store = transaction.objectStore('todos');
const request = store.add({ title, completed: false });
request.onsuccess = event => {
const todo = { id: event.target.result, title, completed: false };
addTodoToList(todo);
newTodoInput.value = '';
};
}
function deleteTodo(id) {
const transaction = db.transaction(['todos'], 'readwrite');
const store = transaction.objectStore('todos');
store.delete(id);
}
function updateTodoStatus(id, completed) {
const transaction = db.transaction(['todos'], 'readwrite');
const store = transaction.objectStore('todos');
store.get(id).onsuccess = event => {
const todo = event.target.result;
todo.completed = completed;
store.put(todo);
};
}
document.querySelector('form').addEventListener('submit', event => {
event.preventDefault();
addNewTodo();
});
todoList.addEventListener('contextmenu', event => {
event.preventDefault();
const li = event.target.closest('li');
if (li) {
deleteTodo(parseInt(li.dataset.id));
li.remove();
}
});

最后,在 sw.js 文件中,我们可以缓存应用所需的资源,以便在离线时仍可访问:

 

JavaScript
const CACHE_NAME = 'todo-cache-v1';
const urlsToCache = [
  '/',
  '/index.html',
  '/app.js',
  '/manifest.json',
  '/icons/icon-72x72.png',
  '/icons/icon-96x96.png',
  '/icons/icon-128x128.png',
  '/icons/icon-144x144.png',
  '/icons/icon-152x152.png',
  '/icons/icon-192x192.png',
  '/icons/icon-384x384.png',
  '/icons/icon-512x512.png'
];
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response;
        }
        return fetch(event.request);
      })
  );
});

 

以上就是一个简单的 PWA 应用的 demo,它能够在离线时正常工作,并且可以像本地应用一样被用户添加到主屏幕上。

 

我们再来详细解释一下上述代码的逻辑:

 

首先,我们在 index.html 中定义了应用的基本结构和样式,包括一个输入框用于添加新任务,以及一个任务列表。

 

然后,我们在 app.js 中编写了 PWA 应用的核心逻辑,它包括:

 

1.判断浏览器是否支持 Service Worker,并注册 sw.js。

 

JavaScript
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js');
  });
}

 

2.使用 IndexedDB 存储任务列表。

 

JavaScript
const request = indexedDB.open('todo-db', 1);
request.onupgradeneeded = event => {
  const db = event.target.result;
  const store = db.createObjectStore('todos', { keyPath: 'id', autoIncrement: true });
  store.createIndex('completed', 'completed');
};
request.onsuccess = event => {
  db = event.target.result;
  loadTodos();
};
async function loadTodos() {
  const transaction = db.transaction(['todos'], 'readonly');
  const store = transaction.objectStore('todos');
  const todos = await store.getAll();
  for (const todo of todos) {
    addTodoToList(todo);
  }
}

 

3.将任务添加到任务列表中。

 

JavaScript
function addTodoToList(todo) {
  const li = document.createElement('li');
  li.dataset.id = todo.id;
  li.innerText = todo.title;
  if (todo.completed) {
    li.classList.add('completed');
  }
  li.addEventListener('click', event => {
    const completed = !li.classList.contains('completed');
    updateTodoStatus(todo.id, completed);
    li.classList.toggle('completed');
  });
  todoList.appendChild(li);
}

4.从任务列表中删除任务。

 

JavaScript
function deleteTodo(id) {
  const transaction = db.transaction(['todos'], 'readwrite');
  const store = transaction.objectStore('todos');
  store.delete(id);
}

 

5.更新任务的完成状态。

 

JavaScript
function updateTodoStatus(id, completed) {
  const transaction = db.transaction(['todos'], 'readwrite');
  const store = transaction.objectStore('todos');
  store.get(id).onsuccess = event => {
    const todo = event.target.result;
    todo.completed = completed;
    store.put(todo);
  };
}

 

6.使用 IndexedDB 存储新任务,并将其添加到任务列表中。

JavaScript
function addNewTodo() {
  const title = newTodoInput.value;
  if (title.trim() === '') {
    return;
  }
  const transaction = db.transaction(['todos'], 'readwrite');
  const store = transaction.objectStore('todos');
  const request = store.add({ title, completed: false });
  request.onsuccess = event => {
    const todo = { id: event.target.result, title, completed: false };
    addTodoToList(todo);
    newTodoInput.value = '';
  };
}

 

7.监听表单提交事件,并调用 addNewTodo 函数。

JavaScript
document.querySelector('form').addEventListener('submit', event => {
  event.preventDefault();
  addNewTodo();
});

8.监听任务列表中任务的右键点击事件,并调用 deleteTodo 函数。

 

 

最后,我们在 sw.js 中编写 Service Worker 的逻辑,包括:

 

1.缓存应用的静态资源。

JavaScript
const cacheName = 'todo-app-cache';
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(cacheName).then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        '/app.js',
        '/style.css',
        '/manifest.json'
      ]);
    })
  );
});

2.从缓存中读取静态资源,如果没有则从网络中获取。

JavaScript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      if (response) {
        return response;
      }
      return fetch(event.request);
    })
  );
});

 

3.删除旧的缓存,保留最新的缓存。

 

JavaScript
self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.filter(name => name !== cacheName).map(name => caches.delete(name))
      );
    })
  );
});

 

 

到此为止,我们的 PWA 应用就完成了。用户可以使用它添加、完成和删除任务,应用还具有离线缓存、添加到主屏幕等 PWA 特性,大大提升了应用的性能和用户体验。

 

如果你想体验一下这个应用,可以将上述代码保存到本地,然后在浏览器中打开 index.html 文件即可。

 

综上所述,PWA 是一种非常有前途的技术,可以提高 Web 应用的性能和用户体验。使用 PWA 可以让 Web 应用更像原生应用,更加快速、可靠和易用。在未来,PWA 将会成为 Web 应用的重要发展方向,带来更多的创新和变革。

 原文链接:http://lao-zhao.com/post/14.html

标签:Web,transaction,const,completed,PWA,体验,todo,event,png
From: https://www.cnblogs.com/lao-zhao/p/17176094.html

相关文章

  • Spring MVC 配置类 WebMvcConfigurerAdapter
    WebMvcConfigurerAdapter配置类是spring提供的一种配置方式,采用JavaBean的方式替代传统的基于xml的配置来对spring框架进行自定义的配置。因此,在springboot提倡的基于注解......
  • javaWeb学习一
    web开发(web就是网页):静态webhtml、css提供给所有人看到数据不会改变动态web提供给所有人看到数据会改变,不同用户、不同时间和地点都会不同技术栈:Se......
  • WebSocket 使用记录
    WebSocket主要解决的问题是后端数据更新主动像前端推送数据所需依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter......
  • 深入理解webpack的chunkId对线上缓存的思考(转载)
    转载自 https://juejin.cn/post/6844903924818771981#heading-6 作者:Kimm想必经常使用基于webpack打包工具的框架的同学们,无论是使用React还是Vue在性能优化上使用最......
  • webtest mobile adb shell
    s常见adb命令序号adb命令释义备注1adb--help查看帮助文档 2adbstart-server启动adb服务  adbkill-server关闭adb服务 3adbdevice......
  • 课程笔记整理 SOAP Web Service
    SOAPWebServiceSOAP基本概念服务器运行环境HTTP(Web)Server处理HTTP消息,解析HTML文件ApplicationServer应用运行隔离处理JSP页面(JSP=Java+HTML)SOA......
  • 课程笔记整理 RESTful Web Service
    RESTfulWebService基本概念REST伪全称:RepresentationalStateTransferREST真实全称:ApplicationStatesTransferamongtheresource'srepresentation资源表示(名......
  • 最热的前端Web组态工具(可视化)
    最热的前端Web组态工具(可视化)数维图零代码可视化www.sovitjs.com​关注他 152人赞同了该文章现在系统可视化需求越来越大,本文整理几个目前最......
  • .net中的Webform使用NPOI导出excel
    .net中的Webform使用NPOI导出excelprivatevoidExprotExcelGuanXiaYan(DataSetds,ZF.Model.UserInfouModel){try{......
  • Error: Cannot find module ‘webpack-cli/package.json‘
    webpack安装后需要安装webpackcli:npminstall-dwebpack-cli1运行后报错:Error:Cannotfindmodule'webpack-cli/package.json'1解决方案:全局安装webpack-clinpmi......