当前位置: 首页 > 编程日记 > 正文

vue使用pwa_如何使用HTML,CSS和JavaScript从头开始构建PWA

vue使用pwa

Progressive web apps are a way to bring that native app feeling to a traditional web app. With PWAs we can enhance our website with mobile app features which increase usability and offer a great user experience.

渐进式Web应用程序是一种将本地应用程序的感觉带入传统Web应用程序的方法。 借助PWA,我们可以使用移动应用程序功能来增强我们的网站,这些功能可以提高可用性并提供出色的用户体验。

In this article, we are going to build a PWA from scratch with HTML, CSS, and JavaScript. Here are the topics we'll cover:

在本文中,我们将使用HTML,CSS和JavaScript从头开始构建PWA。 以下是我们将讨论的主题:

  • What is a Progressive Web App ?

    什么是渐进式Web应用程序?

  • Markup

    标记

  • Styling

    造型

  • Show data with JavaScript

    使用JavaScript显示数据

  • Web App Manifest

    Web App清单

  • What is a Service Worker?

    什么是服务人员?

  • Cache the assets

    缓存资产

  • Fetch the assets

    获取资产

  • Register the Service Worker

    注册服务人员

  • Final thoughts

    最后的想法

  • Next steps

    下一步

So, let's get started with an important question: What the heck is a PWA?

因此,让我们开始一个重要的问题:PWA到底是什么?

什么是渐进式Web应用程序? (What is a Progressive Web App ?)

A Progressive Web App is a web app that delivers an app-like experience to users by using modern web capabilities. In the end, it's just your regular website that runs in a browser with some enhancements. It gives you the ability:

渐进式Web应用程序是一种通过使用现代Web功能向用户提供类似于应用程序的体验的Web应用程序。 最后,只有常规网站才能在带有某些增强功能的浏览器中运行。 它具有以下功能:

  • To install it on a mobile home screen

    要将其安装在移动主屏幕上
  • To access it when offline

    离线访问
  • To access the camera

    存取相机
  • To get push notifications

    获取推送通知
  • To do background synchronization

    执行后台同步

And so much more.

还有更多。

However, to be able to transform our traditional web app to a PWA, we have to adjust it a little bit by adding a web app manifest file and a service worker.

但是,为了能够将传统的Web应用程序转换为PWA,我们必须通过添加Web应用程序清单文件和服务工作者来对其进行一些调整。

Don't worry about these new terms – we'll cover them below.

不用担心这些新术语-我们将在下面介绍它们。

First, we have to build our traditional web app. So let's start with the markup.

首先,我们必须构建传统的Web应用程序。 因此,让我们从标记开始。

标记 (Markup)

The HTML file is relatively simple. We wrap everything in the main tag.

HTML文件相对简单。 我们将所有内容包装在main标签中。

  • In index.html

    index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><link rel="stylesheet" href="css/style.css" /><title>Dev'Coffee PWA</title></head><body><main><nav><h1>Dev'Coffee</h1><ul><li>Home</li><li>About</li><li>Blog</li></ul></nav><div class="container"></div></main><script src="js/app.js"></script></body>
</html>

And create a navigation bar with the nav tag. Then, the div with the class .container will hold our cards that we add later with JavaScript.

并使用nav标签创建一个导航栏。 然后,类为.containerdiv将保存我们的卡,稍后我们将使用JavaScript添加它们。

Now that we've gotten that out of the way, let's style it with CSS.

现在我们已经解决了这个问题,让我们使用CSS对其进行样式设置。

造型 (Styling)

Here, as usual, we start by importing the fonts we need. Then we'll do some resets to prevent the default behavior.

在这里,像往常一样,我们从导入所需的字体开始。 然后,我们将进行一些重置以防止默认行为。

  • In css/style.css

    css/style.css

@import url("https://fonts.googleapis.com/css?family=Nunito:400,700&display=swap");
* {margin: 0;padding: 0;box-sizing: border-box;
}
body {background: #fdfdfd;font-family: "Nunito", sans-serif;font-size: 1rem;
}
main {max-width: 900px;margin: auto;padding: 0.5rem;text-align: center;
}
nav {display: flex;justify-content: space-between;align-items: center;
}
ul {list-style: none;display: flex;
}li {margin-right: 1rem;
}
h1 {color: #e74c3c;margin-bottom: 0.5rem;
}

Then, we limit the main element's maximum width to 900px to make it look good on a large screen.

然后,我们将main元素的最大宽度限制为900px以使其在大屏幕上看起来不错。

For the navbar, I want the logo to be at the left and the links at the right. So for the nav tag, after making it a flex container, we use justify-content: space-between; to align them.

对于导航栏,我希望徽标位于左侧,链接位于右侧。 因此,对于nav标签,在将其设为flex容器后,我们使用justify-content: space-between; 对齐它们。

  • In css/style.css

    css/style.css

.container {display: grid;grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));grid-gap: 1rem;justify-content: center;align-items: center;margin: auto;padding: 1rem 0;
}
.card {display: flex;align-items: center;flex-direction: column;width: 15rem auto;height: 15rem;background: #fff;box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);border-radius: 10px;margin: auto;overflow: hidden;
}
.card--avatar {width: 100%;height: 10rem;object-fit: cover;
}
.card--title {color: #222;font-weight: 700;text-transform: capitalize;font-size: 1.1rem;margin-top: 0.5rem;
}
.card--link {text-decoration: none;background: #db4938;color: #fff;padding: 0.3rem 1rem;border-radius: 20px;
}

We'll have several cards, so for the container element it will be displayed as a grid. And, with grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)), we can now make our cards responsive so that they use at least 15rem width if there is enough space (and 1fr if not).

我们将有几张卡片,因此对于容器元素,它将显示为网格。 并且,随着grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr))现在我们可以让我们的卡响应,使他们至少使用15rem宽度,如果有足够的空间(和1fr如果没有)。

And to make them look nice we double the shadow effect on the .card class and use object-fit: cover on .card--avatar to prevent the image from stretching.

为了使它们看起来更好,我们将.card类上的阴影效果加倍,并使用object-fit: cover .card--avatar上的.card--avatar防止图像拉伸。

Now it looks much better – but we still don't have data to show.

现在看起来好多了-但我们仍然没有数据可以显示。

Let's fix it in the next section

让我们在下一节中修复它

使用JavaScript显示数据 (Show data with JavaScript)

Notice that I used large images that take some time to load. This will show you in the best way the power of service workers.

请注意,我使用的大图像需要花费一些时间才能加载。 这将以最佳方式向您显示服务人员的力量。

As I said earlier, the .container class will hold our cards. Therefore, we need to select it.

正如我之前说的, .container类将持有我们的卡。 因此,我们需要选择它。

  • In js/app.js

    js/app.js

const container = document.querySelector(".container")
const coffees = [{ name: "Perspiciatis", image: "images/coffee1.jpg" },{ name: "Voluptatem", image: "images/coffee2.jpg" },{ name: "Explicabo", image: "images/coffee3.jpg" },{ name: "Rchitecto", image: "images/coffee4.jpg" },{ name: " Beatae", image: "images/coffee5.jpg" },{ name: " Vitae", image: "images/coffee6.jpg" },{ name: "Inventore", image: "images/coffee7.jpg" },{ name: "Veritatis", image: "images/coffee8.jpg" },{ name: "Accusantium", image: "images/coffee9.jpg" },
]

Then, we create an array of cards with names and images.

然后,我们创建一个包含名称和图像的卡片阵列。

  • In js/app.js

    js/app.js

const showCoffees = () => {let output = ""coffees.forEach(({ name, image }) =>(output += `<div class="card"><img class="card--avatar" src=${image} /><h1 class="card--title">${name}</h1><a class="card--link" href="#">Taste</a></div>`))container.innerHTML = output
}document.addEventListener("DOMContentLoaded", showCoffees)

With this code above, we can now loop through the array and show them on the HTML file. And to make everything work, we wait until the DOM (Document Object Model) content finishes loading to run the showCoffees method.

有了上面的代码,我们现在可以遍历数组并将其显示在HTML文件中。 为了使一切正常,我们要等到DOM(文档对象模型)内容完成加载后才能运行showCoffees方法。

We've done a lot, but for now, we just have a traditional web app. So, let's change that in the next section by introducing some PWA features.

我们做了很多事情,但是到目前为止,我们只有一个传统的Web应用程序。 因此,让我们在下一部分中通过介绍一些PWA功能来更改它。

Web App清单 (Web App Manifest)

The web app manifest is a simple JSON file that informs the browser about your web app. It tells how it should behave when installed on the user's mobile device or desktop. And to show the Add to Home Screen prompt, the web app manifest is required.

Web应用程序清单是一个简单的JSON文件,用于通知浏览器您的Web应用程序。 它说明了将其安装在用户的移动设备或台式机上时的行为。 为了显示“添加到主屏幕”提示,需要Web应用程序清单。

Now that we know what a web manifest is, let's create a new file named manifest.json (you have to name it like that) in the root directory. Then add this code block below.

现在我们知道了Web清单是什么,让我们在根目录中创建一个名为manifest.json的新文件(您必须这样命名)。 然后在下面添加此代码块。

  • In manifest.json

    manifest.json

{"name": "Dev'Coffee","short_name": "DevCoffee","start_url": "index.html","display": "standalone","background_color": "#fdfdfd","theme_color": "#db4938","orientation": "portrait-primary","icons": [{"src": "/images/icons/icon-72x72.png","type": "image/png", "sizes": "72x72"},{"src": "/images/icons/icon-96x96.png","type": "image/png", "sizes": "96x96"},{"src": "/images/icons/icon-128x128.png","type": "image/png","sizes": "128x128"},{"src": "/images/icons/icon-144x144.png","type": "image/png", "sizes": "144x144"},{"src": "/images/icons/icon-152x152.png","type": "image/png", "sizes": "152x152"},{"src": "/images/icons/icon-192x192.png","type": "image/png", "sizes": "192x192"},{"src": "/images/icons/icon-384x384.png","type": "image/png", "sizes": "384x384"},{"src": "/images/icons/icon-512x512.png","type": "image/png", "sizes": "512x512"}]
}

In the end, it's just a JSON file with some mandatory and optional properties.

最后,它只是一个带有一些必需和可选属性的JSON文件。

name: When the browser launches the splash screen, it will be the name displayed on the screen.

名称:浏览器启动初始屏幕时,它将是屏幕上显示的名称。

short_name: It will be the name displayed underneath your app shortcut on the home screen.

short_name:它将是显示在主屏幕上您应用快捷方式下方的名称。

start_url: It will be the page shown to the user when your app is open.

start_url:打开您的应用后,它将显示给用户。

display: It tells the browser how to display the app. There are several modes like minimal-ui, fullscreen, browser etc. Here, we use the standalone mode to hide everything related to the browser.

display:告诉浏览器如何显示应用程序。 有几种模式,如minimal-uifullscreenbrowser等。在这里,我们使用standalone模式隐藏与浏览器相关的所有内容。

background_color: When the browser launches the splash screen, it will be the background of the screen.

background_color:当浏览器启动初始屏幕时,它将是屏幕的背景。

theme_color: It will be the background color of the status bar when we open the app.

theme_color:这是我们打开应用程序时状态栏的背景色。

orientation: It tells the browser the orientation to have when displaying the app.

方向:它告诉浏览器显示应用程序时的方向。

icons: When the browser launches the splash screen, it will be the icon displayed on the screen. Here, I used all sizes to fit any device's preferred icon. But you can just use one or two. It's up to you.

图标:当浏览器启动启动屏幕时,它将是屏幕上显示的图标。 在这里,我使用了所有尺寸以适合任何设备的首选图标。 但是您只能使用一两个。 由你决定。

Now that we have a web app manifest, let's add it to the HTML file.

现在我们有了一个Web应用程序清单,让我们将其添加到HTML文件中。

  • In index.html (head tag)

    index.html (头标记)

<link rel="manifest" href="manifest.json" />
<!-- ios support -->
<link rel="apple-touch-icon" href="images/icons/icon-72x72.png" />
<link rel="apple-touch-icon" href="images/icons/icon-96x96.png" />
<link rel="apple-touch-icon" href="images/icons/icon-128x128.png" />
<link rel="apple-touch-icon" href="images/icons/icon-144x144.png" />
<link rel="apple-touch-icon" href="images/icons/icon-152x152.png" />
<link rel="apple-touch-icon" href="images/icons/icon-192x192.png" />
<link rel="apple-touch-icon" href="images/icons/icon-384x384.png" />
<link rel="apple-touch-icon" href="images/icons/icon-512x512.png" />
<meta name="apple-mobile-web-app-status-bar" content="#db4938" />
<meta name="theme-color" content="#db4938" />

As you can see, we linked our manifest.json file to the head tag. And add some other links which handle the iOS support to show the icons and colorize the status bar with our theme color.

如您所见,我们将manifest.json文件链接到head标签。 并添加其他一些处理iOS支持的链接,以显示图标并使用我们的主题颜色为状态栏着色。

With that, we can now dive into the final part and introduce the service worker.

这样,我们现在可以深入探讨最后一部分并介绍服务人员。

什么是服务人员? (What is a Service Worker?)

Notice that PWAs run only on https because the service worker can access the request and handle it. Therefore security is required.

请注意,由于服务工作者可以访问并处理请求,因此PWA仅在https上运行。 因此,需要安全性。

A service worker is a script that your browser runs in the background in a separate thread. That means it runs in a different place and is completely separate from your web page. That's the reason why it can't manipulate your DOM element.

服务工作者是一个脚本,您的浏览器在后台在单独的线程中运行。 这意味着它在其他位置运行,并且与您的网页完全分开。 这就是为什么它无法操纵DOM元素的原因。

However, it's super powerful. The service worker can intercept and handle network requests, manage the cache to enable offline support or send push notifications to your users.

但是,它超级强大。 服务人员可以拦截和处理网络请求,管理缓存以启用脱机支持或向您的用户发送推送通知。

S0 let's create our very first service worker in the root folder and name it serviceWorker.js (the name is up to you). But you have to put it in the root so that you don't limit its scope to one folder.

S0让我们在根文件夹中创建第一个服务工作者,并将其命名为serviceWorker.js (名称由您决定)。 但是您必须将其放在根目录中,以免将其范围限制为一个文件夹。

缓存资产 (Cache the assets)

  • In serviceWorker.js

    serviceWorker.js

const staticDevCoffee = "dev-coffee-site-v1"
const assets = ["/","/index.html","/css/style.css","/js/app.js","/images/coffee1.jpg","/images/coffee2.jpg","/images/coffee3.jpg","/images/coffee4.jpg","/images/coffee5.jpg","/images/coffee6.jpg","/images/coffee7.jpg","/images/coffee8.jpg","/images/coffee9.jpg",
]self.addEventListener("install", installEvent => {installEvent.waitUntil(caches.open(staticDevCoffee).then(cache => {cache.addAll(assets)}))
})

This code looks intimidating first but it just JavaScript (so don't worry).

该代码首先看起来令人生畏,但它只是JavaScript(因此不用担心)。

We declare the name of our cache staticDevCoffee and the assets to store in the cache. And to perform that action, we need to attach a listener to self.

我们声明缓存的名称staticDevCoffee以及要存储在缓存中的资产。 为了执行该操作,我们需要将一个侦听器附加到self

self is the service worker itself. It enables us to listen to life cycle events and do something in return.

self是服务工作者本身。 它使我们能够听取生命周期事件并做些回报。

The service worker has several life cycles, and one of them is the install event. It runs when a service worker is installed. It's triggered as soon as the worker executes, and it's only called once per service worker.

服务人员有多个生命周期,其中之一就是install事件。 它在安装Service Worker时运行。 工作程序执行后立即触发,每个服务工作程序仅调用一次。

When the install event is fired, we run the callback which gives us access to the event object.

install事件被触发时,我们运行回调,使我们可以访问event对象。

Caching something on the browser can take some time to finish because it's asynchronous.

在浏览器上缓存内容可能需要一些时间才能完成,因为它是异步的。

So to handle it, we need to use waitUntil() which, as you might guess, waits for the action to finish.

因此,要处理它,我们需要使用waitUntil() ,您可能会猜到它等待动作完成。

Once the cache API is ready, we can run the open() method and create our cache by passing its name as an argument to caches.open(staticDevCoffee).

缓存API准备就绪后,我们可以运行open()方法并通过将其名称作为参数传递给caches.open(staticDevCoffee)来创建缓存。

Then it returns a promise, which helps us store our assets in the cache with cache.addAll(assets).

然后,它返回一个promise,这有助于我们使用cache.addAll(assets)将资产存储在缓存中。

Hopefully, you're still with me.

希望你还和我在一起。

Now, we've successfully cached our assets in the browser. And the next time we load the page, the service worker will handle the request and fetch the cache if we are offline.

现在,我们已经成功地在浏览器中缓存了我们的资产。 下次我们加载页面时,如果我们处于脱机状态,则服务工作者将处理该请求并获取缓存。

So, let's fetch our cache.

因此,让我们获取缓存。

取得资产 (Fetch the assets)

  • In serviceWorker.js

    serviceWorker.js

self.addEventListener("fetch", fetchEvent => {fetchEvent.respondWith(caches.match(fetchEvent.request).then(res => {return res || fetch(fetchEvent.request)}))
})

Here, we use the fetch event to, well, get back our data. The callback gives us access to fetchEvent. Then we attach respondWith() to prevent the browser's default response. Instead it returns a promise because the fetch action can take time to finish.

在这里,我们使用fetch事件获取数据。 回调使我们可以访问fetchEvent 。 然后,我们附加respondWith()来防止浏览器的默认响应。 相反,它会返回一个Promise,因为获取操作可能需要一些时间才能完成。

And once the cache ready, we apply the caches.match(fetchEvent.request). It will check if something in the cache matches fetchEvent.request. By the way, fetchEvent.request is just our array of assets.

一旦缓存准备就绪,我们将应用caches.match(fetchEvent.request) 。 它将检查缓存中是否有与fetchEvent.request匹配的fetchEvent.request 。 顺便说一句, fetchEvent.request只是我们的资产数组。

Then, it returns a promise. And finally, we can return the result if it exists or the initial fetch if not.

然后,它返回一个承诺。 最后,我们可以返回结果(如果存在)或初始获取(如果不存在)。

Now, our assets can be cached and fetched by the service worker which increases the load time of our images quite a bit.

现在,服务人员可以缓存和获取我们的资产,这大大增加了图像的加载时间。

And most important, it makes our app available in offline mode.

最重要的是,它使我们的应用程序可以离线使用。

But a service worker alone can't do the job. We need to register it in our project.

但是仅服务人员无法完成这项工作。 我们需要在我们的项目中注册它。

注册服务人员 (Register the Service Worker)

  • In js/app.js

    js/app.js

if ("serviceWorker" in navigator) {window.addEventListener("load", function() {navigator.serviceWorker.register("/serviceWorker.js").then(res => console.log("service worker registered")).catch(err => console.log("service worker not registered", err))})
}

Here, we start by checking if the serviceWorker is supported by the current browser (as it's still not supported by all browsers).

在这里,我们首先检查当前浏览器是否支持serviceWorker (因为并非所有浏览器都支持它)。

Then, we listen to the page load event to register our service worker by passing the name of our file serviceWorker.js to navigator.serviceWorker.register() as a parameter to register our worker.

然后,通过将文件serviceWorker.js的名称传递给navigator.serviceWorker.register()作为注册我们的工作人员的参数,我们侦听页面加载事件以注册我们的服务工作人员。

With this update, we have now transformed our regular web app to a PWA.

通过此更新,我们现在将常规网络应用程序转换为PWA。

最后的想法 (Final thoughts)

Throughout this article, we have seen how amazing PWAs can be. By adding a web app manifest file and a service worker, it really improves the user experience of our traditional web app. This is because PWAs are fast, secure, reliable, and – most importantly – they support offline mode.

在本文中,我们已经看到了惊人的PWA。 通过添加Web应用程序清单文件和服务工作者,确实可以改善我们传统Web应用程序的用户体验。 这是因为PWA快速,安全,可靠,而且最重要的是,它们支持脱机模式。

Many frameworks out there now come with a service worker file already set-up for us. But knowing how to implement it with Vanilla JavaScript can help you understand PWAs.

现在,许多框架都已经为我们设置了服务工作者文件。 但是,知道如何使用Vanilla JavaScript实施它可以帮助您理解PWA。

And you can go even further with service workers by caching assets dynamically or limiting the size of your cache and so on.

通过动态缓存资产或限制缓存大小等,您可以与服务工作者一起走得更远。

Thanks for reading this article.

感谢您阅读本文。

You can check it out live here and the source code is here.

您可以在此处现场查看 ,源代码在此处 。

Read more of my articles on my blog

在我的博客上文章

下一步 (Next steps)

Web Manifest Documentation

Web清单文档

Service Worker Documentation

服务人员文档

Web Manifest Generator

Web清单生成器

Browser Support

浏览器支持

翻译自: https://www.freecodecamp.org/news/build-a-pwa-from-scratch-with-html-css-and-javascript/

vue使用pwa

相关文章:

仅需6步,教你轻易撕掉app开发框架的神秘面纱(4):网络模块的封装

程序框架确定了&#xff0c;还需要封装网络模块。 一个丰富多彩的APP少不了网络资源的支持&#xff0c;毕竟用户数据要存储&#xff0c;用户之间也要交互&#xff0c;用户行为要统计等等。 使用开源框架 俗话说得好&#xff0c;轮子多了路好走&#xff0c;我们不需要自己造轮…

结构体成员数组不定长如何实现

【目的】 定义一个结构体类&#xff0c;其中的成员变量数组长度不定&#xff0c;根据实例化的对象指定长度&#xff0c;所以想到用指针实现 【现状】 指针可以指向任意长度数组&#xff0c;但结构体类只分配指针本身4字节长度&#xff0c;所以无法扩展 1 /**2 ****************…

团队项目:二次开发

至此&#xff0c;我们有了初步的与人合作经验&#xff0c;接下来投入到更大的团队中去。 也具备了一定的个人能力&#xff0c;能将自己的代码进行测试。接下来尝试在别人已有的基础上进行开发。 上一界51冯美欣同学的项目&#xff1a;http://www.cnblogs.com/maxx/ 1.每个团队从…

arduino 呼吸灯_如何改善您的Arduino呼吸机:用于临时COVID-19呼吸机设计的RTS和SCS简介...

arduino 呼吸灯The world as we know it was recently taken by storm. That storm was the outbreak of the COVID-19 pandemic. This has in turn created a shortage of ventilators world wide which has led many people to foray into the world of ventilator design. 我…

reboot 百度网盘资源

提醒&#xff1a;同志们这是记录&#xff0c;视频文件是加密的&#xff0c;请勿下载 基础班第十三期&#xff1a;http://pan.baidu.com/s/1c2GcvKG 密码: 743j 基础班第十四期链接: http://pan.baidu.com/s/1c24AYa8 密码: x2sh 第十五期&#xff1a; https://pan.baidu.com…

仅需6步,教你轻易撕掉app开发框架的神秘面纱(5):数据持久化

遇到的问题 有的时候程序中需要全局皆可访问的变量&#xff0c;比如&#xff1a;用户是否登录&#xff0c;用户个人信息(用户名&#xff0c;地区&#xff0c;生日)&#xff0c;或者一些其他信息如&#xff1a;是否是首次登录&#xff0c;是否需要显示新手引导等等。 其中有些…

响应因特网端口ping命令_如何使用Ping命令识别基本的Internet问题

响应因特网端口ping命令Next time you call your help desk, do you want to wow them with your networking knowledge? Using a command called “ping”, built right into your existing Mac, Windows, or Linux computer, will help identify basic connection problems.…

Android 常见工具类封装

1&#xff0c;MD5工具类&#xff1a; public class MD5Util {public final static String MD5(String s) {char hexDigits[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,a, b, c, d, e, f };try {byte[] btInput s.getBytes();// 获得MD5摘要算法的 MessageDigest 对象MessageDigest md…

keras系列︱图像多分类训练与利用bottleneck features进行微调(三)

引自&#xff1a;http://blog.csdn.net/sinat_26917383/article/details/72861152 中文文档&#xff1a;http://keras-cn.readthedocs.io/en/latest/ 官方文档&#xff1a;https://keras.io/ 文档主要是以keras2.0。 训练、训练主要就”练“嘛&#xff0c;所以堆几个案例就知…

LIKE 操作符

LIKE 操作符LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式。SQL LIKE 操作符语法SELECT column_name(s)FROM table_nameWHERE column_name LIKE pattern原始的表 (用在例子中的)&#xff1a;Persons 表:IdLastNameFirstNameAddressCity1AdamsJohnOxford StreetLondon2Bush…

服务器云ide_语言服务器协议如何影响IDE的未来

服务器云ideThe release of Visual Studio Code single-handedly impacted the developer ecosystem in such a way that theres no going back now. Its open source, free, and most importantly, a super powerful tool. Visual Studio Code的发布以一种无可匹敌的方式对开发…

仅需6步,教你轻易撕掉app开发框架的神秘面纱(6):各种公共方法及工具类的封装

为什么要封装公共方法 封装公共方法有2方面的原因&#xff1a; 一是功能方面的原因&#xff1a;有些方法很多地方都会用&#xff0c;而且它输入输出明确&#xff0c;并且跟业务逻辑无关。比如检查用户是否登录&#xff0c;检查某串数字是否为合法的手机号。像这种方法就应该封…

MySQL优化配置之query_cache_size

原理MySQL查询缓存保存查询返回的完整结果。当查询命中该缓存&#xff0c;会立刻返回结果&#xff0c;跳过了解析&#xff0c;优化和执行阶段。 查询缓存会跟踪查询中涉及的每个表&#xff0c;如果这写表发生变化&#xff0c;那么和这个表相关的所有缓存都将失效。 但是随着服…

request.getSession()

request.getSession(); 与request.getSession(false);区别 服务器把session信息发送给浏览器 浏览器会将session信息存入本地cookie中 服务器本地内存中也会留一个此session信息 以后用户发送请求时 浏览器都会把session信息发送给服务器 服务器会依照浏览器发送过来的se…

alpine 交互sh_在这个免费的交互式教程中学习Alpine JS

alpine 交互shAlpine.js is a rugged, minimal framework for composing Javascript behavior in your markup. Thats right, in your markup! Alpine.js是一个坚固的最小框架&#xff0c;用于在标记中构成Javascript行为。 是的&#xff0c;在您的标记中&#xff01; It allo…

浅谈 MVP in Android

一、概述 对于MVP&#xff08;Model View Presenter&#xff09;&#xff0c;大多数人都能说出一二&#xff1a;“MVC的演化版本”&#xff0c;“让Model和View完全解耦”等等。本篇博文仅是为了做下记录&#xff0c;提出一些自己的看法&#xff0c;和帮助大家如何针对一个Acti…

test markdown

test test public void main(String[] args){System.out.println("test"); } 转载于:https://www.cnblogs.com/cozybz/p/5427053.html

java开发工具对比eclipse·myeclipse·idea

eclipse:不说了&#xff0c;习惯了 myeclipse&#xff1a;MyEclipse更适合企业开发者&#xff0c;更团队开发 idea:idea更适合个人开发者,细节优化更好转载于:https://www.cnblogs.com/gjack/p/8136964.html

软件测试质量过程检测文档_如何编写实际上有效的质量检查文档

软件测试质量过程检测文档A software product is like an airplane: it must undergo a technical check before launch.软件产品就像飞机&#xff1a;必须在发射前经过技术检查。 Quality Assurance is a necessary step towards launching a successful software product. I…

Android深度探索--HAL与驱动开发----第一章读书笔记

1.1 Android拥有非常完善的系统构架可以分为四层&#xff1a; 第一层&#xff1a;Linux内核。主要包括驱动程序以及管理内存、进程、电源等资源的程序 第二层&#xff1a;C/C代码库。主要包括Linux的.so文件以及嵌入到APK程序中的NDK代码 第三层&#xff1a;android SDK API …

[NOI2011]Noi嘉年华

题解:我们设计状态方程如下: num[i][j]表示从时间i到j中有多少个 pre[i][j]表示时间1~i中,A选了j个时的B能选的数量的最大值. nex[i][j]表示时间i~cnt中,A选了j个时的B能选的数量的最大值. mus[i][j]表示从时间i到j的保证选时,A和B选的数量中的较小值的最大值. ①对于num数组直…

只有20%的iOS程序员能看懂:详解intrinsicContentSize 及 约束优先级/content Hugging/content Compression Resistance

在了解intrinsicContentSize之前&#xff0c;我们需要先了解2个概念&#xff1a; AutoLayout在做什么约束优先级是什么意思。 如果不了解这两个概念&#xff0c;看intinsic content size没有任何意义。 注&#xff1a;由于上面这几个概念都是针对UIView或其子类(UILabel&…

redux rxjs_可观察的RxJS和Redux入门指南

redux rxjsRedux-Observable is an RxJS-based middleware for Redux that allows developers to work with async actions. Its an alternative to redux-thunk and redux-saga.Redux-Observable是Redux的基于RxJS的中间件&#xff0c;允许开发人员使用异步操作。 它是redux-t…

javascript数组排序和prototype详解

原型的概念:&#xff1a;原型对象里的所有属性和方法 被所有构造函数实例化出来的对象所共享&#xff0c;类似于java中的 static 正因为共享所以单一的操作 就会影响了全局&#xff0c;因此使用时需注意 基于prototype&#xff1a;为数组扩展方法 //获取数组最大值function get…

Qt 在Label上面绘制罗盘

自己写的一个小小的电子罗盘的一个小程序&#xff0c;不过是项目的一部分&#xff0c;只可以贴绘制部分代码 效果如下图 首先开始自己写的时候&#xff0c;虽然知道Qt 的坐标系是从左上角开始的&#xff0c;所以&#xff0c;使用了算法&#xff0c;在绘制后&#xff0c;在移动回…

终极方案!解决正确设置LaunchImage后仍然不显示的问题

对于如何设置LaunchImage&#xff0c;网络上有各种各样的教程。 主要分2点&#xff1a; 1. 正确设置图片尺寸 2. 取消LaunchScreen.xib 但是经过上述步骤之后&#xff0c;你觉得完全没有问题了&#xff0c;但是仍然无法显示LaunchImage。 或者&#xff0c;你在多个模拟器上…

c# 持续集成 单元测试_如何在不进行单元测试的情况下设置持续集成

c# 持续集成 单元测试Do you think continuous integration is not for you because you have no automated tests? Or no unit tests at all? Not true. Tests are important. But there are many more aspects to continuous integration than just testing. Lets see what…

Handlebars模板引擎

介绍 Handlebars 是 JavaScript 一个语义模板库&#xff0c;通过对view和data的分离来快速构建Web模板。它采用"Logic-less template"&#xff08;无逻辑模版&#xff09;的思路&#xff0c;在加载时被预编译&#xff0c;而不是到了客户端执行到代码时再去编译&#…

字符集图标制作

字符集图标&#xff1a; 将网页上常见的icon做成font&#xff08;字符集&#xff09;&#xff0c;以字体的方式插入到网页上&#xff0c;作用是减轻服务器负担&#xff0c;减少宽带。 我最常在这两个网站上下载字体图标&#xff1a; https://icomoon.io/app/#/select https://w…

Adobe源码泄漏?3行代码搞定,Flash动画无缝导入Android/iOS/cocos2dx(一)

[注] iOS代码已重构&#xff0c;效率提升90%&#xff0c;200层动画不卡。[2016.10.27] 项目介绍 项目名称&#xff1a;FlashAnimationToMobile 源码。 使用方法点这里。 这是一个把flash中的关键帧动画(不是序列帧)导出&#xff0c;然后在iOS&#xff0f;Android原生应用中解…