从零入门Chrome插件开发

news2025/1/12 21:04:27

什么是 Chrome 插件

谷歌浏览器在推出时就以其快速、安全和简洁的特点受到了广大用户的欢迎。随着浏览器的不断发展,谷歌为用户提供了插件开发平台,使开发者能够为浏览器添加各种功能和定制化选项。从此,插件成为了提升用户体验和个性化的重要工具。

谷歌浏览器插件是一种小型程序,可以增强浏览器的功能。谷歌浏览器插件使用HTML、CSS和JavaScript等网页开发技术,开发者可以使用这些技术来创建自己的谷歌浏览器插件。

谷歌浏览器插件的常见作用:

  • 广告拦截:广告拦截插件可以帮助用户屏蔽网页上的广告,提高用户的浏览体验。
  • 下载管理:下载管理插件可以帮助用户更好地管理他们的下载任务,包括暂停、恢复、取消等操作。
  • 阅读模式:阅读模式插件可以将网页转换为更易于阅读的格式,去除不必要的元素和广告等。
  • 密码管理:密码管理插件可以帮助用户管理他们的密码,并自动填写表单。
  • 翻译:翻译插件可以帮助用户在浏览网页时翻译其他语言的内容,提高用户的阅读体验。
  • 社交媒体:社交媒体插件可以帮助用户快速访问他们的社交媒体账户,分享内容和与朋友互动。
  • 开发者工具:开发者工具插件可以帮助开发者调试和测试他们的网站和应用程序。

根据功能和使用方式的不同,可以将 Chrome 插件分为多种类型,例如:

  • 浏览器操作类插件:如广告拦截器、密码管理器等,主要用于增强用户对浏览器的控制能力;
  • 网页修改类插件:如用户样式表、网页字体修改器等,主要用于改变网页的外观和布局;
  • 其他类型:如翻译软件、天气预报插件等。

它们能够个性化定制浏览器、增强功能、提升效率,并且通过开发者社区促进插件开发的创新和进步。

谷歌插件不仅提升了用户的浏览体验,还为开发者提供了一个创造和分享自己工具的平台。通过使用和探索谷歌插件,我们可以充分发挥浏览器的潜力,提高工作效率和生活品质。

Chrome 插件的运行原理

Chrome 插件采用了一种基于事件的编程模型,其运行原理如下:

  1. 插件加载:当用户在浏览器中安装并启用插件时,插件将被加载到浏览器中。此时,浏览器会读取插件目录中的 manifest.json 文件,根据其中的配置信息来加载插件。

  2. 插件初始化:一旦插件被加载到浏览器中,就会初始化插件。在这个过程中,插件会创建必要的对象和变量,并准备好处理来自浏览器和其他网站的请求和事件。

  3. 插件事件处理:当用户与浏览器交互时,例如单击插件图标或在网页中执行某些操作时,插件会收到事件。在这种情况下,插件会根据事件类型执行相应的操作。

  4. 插件响应:当插件接收到事件时,它会执行相应的操作。例如,如果用户单击插件图标,则插件可能会显示一个弹出窗口或打开一个新的标签页。

  5. 插件卸载:当用户不再需要插件时,可以从浏览器中卸载它。在这种情况下,浏览器会删除插件文件并清除相关的设置和数据。

当用户安装了一个 Chrome 插件后,该插件的代码将会被下载到用户的本地计算机上,并在以后的浏览器会话中执行。用户可以通过 Chrome 浏览器的扩展管理器对已安装的插件进行启用或禁用。

Chrome 插件开发基本结构

谷歌插件的内部机制是通过一系列的文件和目录来实现的,一个 Chrome 插件通常由以下组成部分组成:

  • 清单文件(manifest.json):manifest.json是插件的配置文件,这是插件的核心,它定义了插件的元数据和行为,包含插件名称、版本号、作者信息、插件的权限和其他元数据等。在这个文件中,可以指定插件的图标、背景页、内容脚本和其他资源。
  • 背景页面(background.js):background.js是插件的后台脚本,可以在后台运行,处理插件的事件和请求。例如,您可以使用background.js来处理插件的启动和关闭事件,或者处理来自其他网站的请求。
  • 内容脚本(content_script):content_scripts是插件的内容脚本,可以注入到网页中与网页进行交互。它可以访问当前页面的 DOM 结构和 JavaScript 对象,以实现对页面的修改和操作。例如,您可以使用content_scripts来修改网页元素、监听网页事件或者向网页注入自定义样式或脚本等。
  • 弹出页面(popup.html):popup.html是插件的弹出窗口页面,可以在用户点击插件图标时显示。可以在popup.html中添加任何HTML、CSS和JavaScript代码,以显示有用的信息或提供交互式功能。
  • 插件图标(icon.png):icon.png是插件的图标文件,用于在谷歌浏览器中显示插件图标。

除了上述文件之外,还可以包含其他资源文件,例如CSS样式表、JavaScript脚本、图片和字体等。

OK,那我们话不多说,接下来我用两个插件来带你完全入门 Google 插件开发!

实战:Chrome 滤镜插件

首先,我们需要创建一个新的 Chrome 插件项目叫滤镜插件:

mkdir google_extensions_filter # 创建滤镜插件项目
cd google_extensions_filter # 进入项目根目录
touch manifest.json # 在你的项目根目录中创建一个名为 manifest.json 的文件

接下来我们来编写 manifest.json

{
    "manifest_version": 2,  // manifest.json 文件版本号
    "name": "网页滤镜🔍",  // 插件名称,字符串类型
    "version": "1.0",  // 插件版本号,字符串类型
    "description": "更改当前网页滤镜🔍", // 插件描述,字符串类型
    "permissions": [ // 权限,该字段定义了插件需要访问的资源和功能,例如浏览器标签、存储、网络等等
        "activeTab" // 允许插件访问当前激活的标签页
      ],
    "browser_action": { // 浏览器动作,该字段用于定义当用户单击浏览器操作按钮时执行的操作
        "default_title": "网页滤镜🔍", // 鼠标指针悬停在浏览器操作按钮上显示的默认标题
        "default_popup": "popup/popup.html", // 弹出窗口的 HTML 文件路径
        "default_icon": { // 默认图标的文件路径
            "128": "icon/icon128.png"  // 128x128 像素的图标文件路径
        }
    },
    // 此属性对应用程序可以加载的资源设置限制
    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}

在清单配置文件里我们定义了插件的名称、版本、描述和所需的权限,还指定了插件的图标和默认弹出窗口

接下来我们在根目录创建 popup 文件夹,然后在里面创建一个名为 popup.html 的文件,并添加以下代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>添加网页滤镜🔍</title>
    <link rel="stylesheet" href="popup.css">
  </head>

  <body>
    <h1>添加网页滤镜🔍</h1>
    <div class="box">
      <button id="changeFilterBtn">
        <span class="text">添加滤镜</span>
      </button>
      <button id="changeBlackFilterBtn">
        <span class="text">黑白滤镜</span>
      </button>
      <button id="resetFilterBtn">
        <span class="text">去除滤镜</span>
      </button>
    </div>
    <script src="popup.js"></script>
  </body>

</html>

我们写了一个简单的弹出窗口页面:包含一个标题(添加网页滤镜🔍)和三个按钮(添加滤镜、黑白滤镜、去除滤镜),然后我们来加一点css让这个页面变得炫酷起来:

body {
    min-width: 300px;
    min-height: 100px;
  }
  
  h1 {
    font-size: 28px;
    font-weight: bold;
    text-align: center;
    text-shadow: 2px 2px #f0f0f0;
  }
  
  .box {
    width: 100%;
    display: flex;
    justify-content: space-around;
    align-items: center;
  }

button {
  align-items: center;
  background-image: linear-gradient(144deg,#AF40FF, #5B42F3 50%,#00DDEB);
  border: 0;
  border-radius: 8px;
  box-shadow: rgba(151, 65, 252, 0.2) 0 15px 30px -5px;
  box-sizing: border-box;
  color: #FFFFFF;
  display: flex;
  font-family: Phantomsans, sans-serif;
  font-size: 18px;
  justify-content: center;
  line-height: 1em;
  max-width: 100%;
  min-width: 140px;
  margin: 5px;
  padding: 3px;
  text-decoration: none;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  white-space: nowrap;
  cursor: pointer;
  transition: all .3s;
 }
 
 button:active,
 button:hover {
  outline: 0;
 }
 
 button span {
  background-color: rgb(5, 6, 45);
  padding: 16px 24px;
  border-radius: 6px;
  width: 100%;
  height: 100%;
  transition: 300ms;
 }
 
 button:hover span {
  background: none;
 }
 
 button:active {
  transform: scale(0.9);
 }
  

好我们来看看现在的效果:

在这里插入图片描述

看起来还是蛮不错的,接下来为了使弹出窗口有更多的交互功能,我们需要为按钮添加 JavaScript

在popup文件夹中创建一个名为 popup.js 的文件,并添加以下代码:

// 添加滤镜
document.getElementById('changeFilterBtn').addEventListener('click', function () {
  chrome.tabs.executeScript({
    code: 'document.documentElement.style.filter = "hue-rotate(180deg)"'
  });
});

// 添加黑白滤镜
document.getElementById('changeBlackFilterBtn').addEventListener('click', function () {
  chrome.tabs.executeScript({
    code: 'document.documentElement.style.filter = "grayscale(100%)"'
  });
});

//去除滤镜
document.getElementById('resetFilterBtn').addEventListener('click', function () {
  chrome.tabs.executeScript({
    code: `document.documentElement.style.filter = "none"`
  });
});

代码非常简单,就是为每个按钮添加了事件监听器,分别监听添加滤镜、黑白滤镜、去除滤镜按钮的单击事件

在更改滤镜按钮的回调函数中,我们使用了 chrome.tabs.executeScript 方法,这个方法的作用是向当前选项卡中注入写入的 JavaScript 代码

现在我们的滤镜插件就完成了,接下来我们来使用一下看看有没有生效

打开谷歌浏览器,在地址栏中输入 chrome://extensions/ 并回车。在扩展程序页面的右上角,点击 “开发者模式” 按钮,然后点击左上角的 “加载已解压的扩展程序” 按钮,选择刚刚我们的google_extensions_filter文件夹

在这里插入图片描述

让我们来看看滤镜插件最后的效果:(完美!)

在这里插入图片描述

实战:Chrome 记事本插件

你是不是觉得上面的例子太简单了?

那我们接着来写一个逻辑稍微复杂一点的记事本插件

我们和之前一样,先来创建一个新的 Chrome 插件项目叫 notebook:

mkdir google_extensions_notebook # 创建记事本插件项目
cd google_extensions_notebook # 进入项目根目录
touch manifest.json # 在项目根目录中创建一个名为 manifest.json 的文件

接下来我们也来编写 manifest.json文件,参数配置基本上和刚刚的项目差不多:

{
    "manifest_version": 2,
    "name": "瑞萌萌的记事本🗒️",
    "version": "1.0",
    "description": "一个随便写写的记事本插件",
    "browser_action": {
      "default_icon": {
        "16": "icon/icon16.png",
        "128": "icon/icon128.png"
      },
      "default_title": "瑞萌萌的记事本🗒️",
      "default_popup": "popup.html"
    },
    "permissions": [
      "storage"
    ],
    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
  }
  

然后我们在根目录创建一个名为 popup.html 的文件,并添加以下HTML代码:

<!DOCTYPE html>
<html>
  <head>
    <title>瑞萌萌的记事本🗒️</title>
    <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="popup.css">
    <script src="popup.js"></script>
  </head>
  <body>
    <h1>瑞萌萌的记事本🗒️</h1>
    <div id="note-list"></div>
    <textarea id="note-textarea" rows="5" placeholder="请输入您的笔记"></textarea>
    <!-- <div id="note-content" contenteditable="true"></div> -->
    <button id="add-button">添加笔记</button>
    <button id="clear-button">清空笔记</button>
  </body>
</html>

来点 CSS 装饰一下:

body {
  font-family: Arial, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  margin: 0;
  padding: 0;
  min-width: 600px;
  background: linear-gradient(to bottom right, #ffafbd, #ffc3a0);
}

h1 {
  font-size: 28px;
  font-weight: bold;
  text-align: center;
  text-shadow: 2px 2px #f0f0f0;
}

#note-list {
  margin: 0 10px;
  padding: 0 20px;
}

.note-item {
  border: 1px solid #ccc;
  border-radius: 15px;
  margin-bottom: 20px;
  padding: 10px 150px 10px 10px;
  position: relative;
  background-color: white;
}

.note-text {
  margin-bottom: 10px;
}

.copy-button {
	box-shadow:inset 0px 1px 0px 0px #efdcfb;
	background:linear-gradient(to bottom, #dfbdfa 5%, #bc80ea 100%);
	background-color:#dfbdfa;
	border-radius:27px;
	border:3px solid #c584f3;
    color: #fff;
    cursor: pointer;
    font-size: 14px;
    margin-left: 10px;
    padding: 5px 15px;
    position: absolute;
    right: 80px;
    top: 50%;
    text-decoration:none;
	text-shadow:0px 1px 0px #9752cc;
    transform: translateY(-50%);
    transition: background-color 0.3s ease-in-out;
  }
  .copy-button:hover {
	background:linear-gradient(to bottom, #bc80ea 5%, #dfbdfa 100%);
	background-color:#bc80ea;
  }
.delete-button {
  box-shadow:inset 0px 1px 0px 0px #8a2a21;
  background:linear-gradient(to bottom, #c62d1f 5%, #f24437 100%);
  border-radius:27px;
  border:3px solid #ffffff;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  margin-left: 10px;
  padding: 8px 17px;
  position: absolute;
  text-decoration: none;
  text-shadow: 0px 1px 0px #b23e35;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  transition: background-color 0.3s ease-in-out;
}

.delete-button:hover {
	background:linear-gradient(to bottom, #f24437 5%, #c62d1f 100%);
	background-color:#f24437;
}

#note-textarea {
  border: 1px solid #ccc;
  border-radius: 15px;
  font-family: Arial, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  margin: 0 35px;
  padding: 10px;
  resize: none;
  width: calc(85%);
}

#add-button, #clear-button {
  background-color: #4caf50;
  border: none;
  border-radius: 20px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.3);
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  padding: 10px 30px;
  margin: 10px 10px 20px 120px;
  transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}

#add-button:hover, #clear-button:hover {
  background-color: #388e3c;
}

在这里插入图片描述

效果还不错,大家也可以根据自己的审美来设计

现在我们就可以开始写我们记事本的逻辑啦,我希望这个记事本插件能做到:

  • 文本框输入笔记内容后添加笔记进入笔记列表
  • 点击复制按钮可以复制添加的任意一条笔记内容
  • 点击删除按钮可以删除笔记列表中的任意一条笔记
  • 点击清空笔记可以删除所有记录的笔记
  • 复制内容到文本框添加笔记,点击复制按钮时保留复制文本的格式
  • 笔记列表存储在Chrome浏览器中,所有标签页共用

🆗 需求明确,还等什么,JS直接冲:

// 渲染笔记列表
function renderNoteList(notes) {
  var noteList = document.getElementById("note-list");
  noteList.innerHTML = "";
  for (var i = 0; i < notes.length; i++) {
    // 创建笔记项
    var noteItem = document.createElement("div");
    noteItem.className = "note-item";
    // 创建笔记文本
    var noteText = document.createElement("div");
    noteText.className = "note-text";
    noteText.textContent = notes[i];
    // 创建复制按钮
    var copyButton = document.createElement("button");
    copyButton.className = "copy-button";
    copyButton.textContent = "复制";
    // 创建删除按钮
    var deleteButton = document.createElement("button");
    deleteButton.className = "delete-button";
    deleteButton.textContent = "删除";
    // 绑定删除按钮的点击事件
    deleteButton.addEventListener("click", (function(index) {
      return function() {
        // 删除对应的笔记
        notes.splice(index, 1);
        // 更新笔记列表
        chrome.storage.sync.set({notes: notes}, function() {
          renderNoteList(notes);
        });
      };
    })(i));

    // 获取所有复制按钮
    var copyButtons = document.querySelectorAll('.copy-button');
    // 给每个复制按钮添加点击事件
    copyButtons.forEach(copyButton => {
      copyButton.addEventListener('click', () => {
        // 获取要复制的文本内容
        const noteContent = copyButton.previousElementSibling ? copyButton.previousElementSibling.textContent.trim() : copyButton.previousSibling.textContent.trim();
        // 创建一个临时textarea元素
        const tempTextarea = document.createElement('textarea');
        tempTextarea.value = noteContent;
        // 将临时textarea元素添加到body中,并选中其中的文本
        document.body.appendChild(tempTextarea);
        tempTextarea.select();
        // 复制文本内容到剪贴板
        document.execCommand('copy');
        // 移除临时textarea元素
        document.body.removeChild(tempTextarea);
      });
    });
    // 添加笔记文本和删除按钮到笔记项
    noteItem.appendChild(noteText);
    noteItem.appendChild(copyButton);
    noteItem.appendChild(deleteButton);
    // 添加笔记项到笔记列表
    noteList.appendChild(noteItem);
  }
}

// 当DOM加载完成时执行以下代码
document.addEventListener("DOMContentLoaded", function() {
  var noteList = [];
  var noteTextarea = document.getElementById("note-textarea");
  var addButton = document.getElementById("add-button");
  var clearButton = document.getElementById("clear-button");

  // 绑定添加按钮的点击事件
  addButton.addEventListener("click", function() {
    var note = noteTextarea.value;
    if (note) {
      // 将笔记添加到笔记列表
      noteList.push(note);
      // 更新笔记列表
      chrome.storage.sync.set({notes: noteList}, function() {
        renderNoteList(noteList);
      });
      // 清空笔记输入框
      noteTextarea.value = "";
    }
  });

  // 保留复制文本的格式信息
  noteTextarea.addEventListener("paste", function(e) {
    e.preventDefault();
    var text = e.clipboardData.getData("text/plain");
    document.execCommand("insertHTML", false, text);
  });

  // 绑定清空按钮的点击事件
  clearButton.addEventListener("click", function() {
    // 清空笔记列表
    noteList = [];
    // 更新笔记列表
    chrome.storage.sync.remove("notes", function() {
      renderNoteList(noteList);
    });
  });

  // 获取存储在Chrome浏览器中的笔记列表
  chrome.storage.sync.get("notes", function(data) {
    if (data.notes) {
      // 如果存在笔记列表,则将其赋值给noteList变量
      noteList = data.notes;
      // 渲染笔记列表
      renderNoteList(noteList);
    }
  });

  // 设置插件图标
  chrome.browserAction.setIcon({ path: 'icon/icon128.png' });

  // 设置插件标题
  chrome.browserAction.setTitle({ title: '瑞萌萌的记事本🗒️' });
});

代码每一部分我都写了注释,具体实现过程可以自己看一下上面的代码

现在我们的记事本插件就完成啦,我们来在浏览器里加载一下插件,看看实地效果怎么样

在这里插入图片描述

在这里插入图片描述

完美!所有需求功能都已实现!

怎么样,经过上面两个 Chrome 插件实战,你有没有觉得 Chrome 插件开发其实没有你想的那么难!

写在最后:

Chrome 插件是一种非常有用的工具,它可以帮助开发者扩展浏览器的功能,提高用户体验

在本文中,我们详细讲解了谷歌浏览器插件的基础知识、运行原理、开发实战等方面

通过本文的学习,你应该已经掌握了如何创建一个谷歌浏览器插件,并且了解如何在浏览器里使用它

希望本文能够帮助你更好地理解 Chrome 插件开发,并激发对 Chrome 插件开发的兴趣,进一步探索和创造更多有趣、实用的插件。加油!

本文所有的代码都放到了https://github.com/KongC-X/chrome_extensions,欢迎自取!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1178886.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02|LangChain | 从入门到实战 -六大组件之Models IO

by&#xff1a;wenwenC9 上一篇文章 01&#xff5c;LangChain | 从入门到实战-介绍 一、Models IO 组成及其说明 与语言模型的交互&#xff0c;比如在线GPT系列&#xff0c;或各种离线模型 任何语言模型应用程序的核心元素都是XXX模型。LangChain 提供了与任何语言模型交互的…

[第二章—Spring MVC的高级技术] 2.1Spring MVC配置的替代方案

7.1.1 自定义DispatcherServlet配置 例如&#xff0c;在本章稍后的内容中&#xff08;7.2节&#xff09;&#xff0c;我们将会看到如何在Spring MVC中处理multipart请求和文件上传。 如果计划使用Servlet 3.0对multipart配置的支持&#xff0c;那么需要使用DispatcherServlet的…

​软考-高级-信息系统项目管理师教程 第四版【第16章-项目采购管理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第16章-项目采购管理-思维导图】 课本里章节里所有蓝色字体的思维导图

内窥镜项目

★ 手持pad内窥镜项目 项目描述&#xff1a;3D电子内窥镜软件项目是一个基于BS&#xff08;浏览器服务器&#xff09;架构的项目&#xff0c;旨在实现对内窥镜设备的远程控制和高级功能操作。该项目允许操作员使用平板电脑手动触摸屏上的按钮、外部按键或脚踏板 来控制内窥镜设…

[移动通讯]【Carrier Aggregation-11】【5G NR Carrier Aggregation (CA) basics 】

前言&#xff1a; 参考&#xff1a; RF Wireless world 里面的 《5G/NR - Carrier Aggregation》 《5G NR Carrier Aggregation (CA) basics | Carrier Aggregation frequency bands》 This page describes 5G NR Carrier Aggregation (CA) basics. It mentions Carrier Aggre…

Redis 的几种集群对比

文章目录 一、对比分析二、优缺点对比三、总结 如果您对Redis的了解不够深入请关注本栏目&#xff0c;本栏目包括Redis安装&#xff0c;Redis配置文件说明&#xff0c;Redis命令和数据类型说明&#xff0c;Redis持久化配置&#xff0c;Redis主从复制和哨兵机制&#xff0c;Redi…

一些常规的报错和解决方法(持续更新)

一些常规的报错和解决方法&#xff1a; 1、vue创建项目后&#xff0c;项目启动时报错You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included bu…

【JavaEE】实现简单博客系统-前端部分

文件目录&#xff1a; 展示&#xff1a; blog_list.html: <!DOCTYPE html> <html lang"cn"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><t…

05-SpringBoot中yaml文件的语法格式,在程序中读取yaml文件中数据的方式,yaml文件中引用数据的方式

yaml文件格式 语法格式 YAML(YAML Aint Markup Language)是一种数据序列化格式 , 具有容易阅读、容易与脚本语言交互、以数据为核心即重数据轻格式的特点 YAML数据常见的文件扩展名有yml格式(主流)和yaml格式两种 YAML文件的语法格式: 属性层级关系使用多行和缩进描述(同层…

第十一章《搞懂算法:聚类是怎么回事》笔记

聚类是机器学习中一种重要的无监督算法&#xff0c;可以将数据点归结为一系列的特定组合。归为一类的数据点具有相同的特性&#xff0c;而不同类别的数据点则具有各不相同的属性。 11.1 聚类算法介绍 人们将物理或抽象对象的集合分成由类似 的对象组成的多个类的过程被称为聚…

使用IDEA让文本对比不在变的困难

文章目录 前言操作1、IDEA与电脑磁盘任意文件的比较2、项目内部的文件比较3、剪切板比较4、IDEA本地历史比较5、IDEA版本历史对比 前言 在日常实际开发当中我们常常会对一些代码或内容进行比对查看是否有差异&#xff0c;这个时候不需要借用第三方比对插件&#xff0c;在IDEA中…

ubuntu 20.04 server安装

ubuntu 20.04 server安装 ubuntu-20.04.6-live-server-amd64.iso 安装 安装ubuntu20.04 TLS系统后&#xff0c;开机卡在“A start job is running for wait for network to be Configured”等待连接两分多钟。 cd /etc/systemd/system/network-online.target.wants/在[Servi…

【UE4】UE编辑器乱码问题

环境&#xff1a;UE4.27、vs2019 如何解决 问题原因&#xff0c;UE的编码默认是UTF-8&#xff0c;VS的默认编码是GBK 通过"高级保存选项" 直接修改VS的 .h头文件 的 编码 为 UTF-8 步骤1. 步骤2. 修改编码后&#xff0c;从新编译&#xff0c;然后就可以解决编辑器…

Linux基础环境开发工具的使用(二):动静态库的理解,make,makefile

Linux基础环境开发工具的使用[二] 一.动静态库的初步理解1.库的作用2.Linux和Windows中库的后缀名3.如何在Linux中看一个的库名字4.Linux中和Windows平台怎样支持开发的?5.动静态库的概念6.动静态库的优缺点与补充7.代码验证 二.make,makefile1.功能2.基本语法1.快速使用2.依赖…

SV-704LW 无线WIFI网络音柱

SV-704LW 无线WIFI网络音柱(工业级) 一、描述 SV-704LW是深圳锐科达电子有限公司的一款壁挂式WIFI无线网络音柱&#xff0c;通过WIFI无线接入到WIFI覆盖的网络中&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;其采用防水设计&#xff0c;功率可以从30W到6…

品牌如何长期占领小红书市场,小红书投放复盘怎么规划?

想要实现产品种草与品牌营销&#xff0c;达人投放成了很多品牌的选择。然而随着达人协助成本的水涨船高&#xff0c;提高达人投放结果&#xff0c;就变得迫在眉睫。今天我们将为大家分享下&#xff0c;品牌如何长期占领小红书市场&#xff0c;小红书投放复盘怎么规划&#xff1…

找不到x3daudio1_7.dll的解决方法,快速修复x3daudio1_7.dll缺失问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到x3daudio1_7.dll”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;这个文件是与音频设备相关的动态链接库文件&#xff0c;如果缺失或损坏&#xff0c;可能会导致软件游戏…

RabbitMQ(高级特性):限流

消费端限流 在rabbitmq中&#xff0c;使用消费端限流必须开启手动签收信息 过MQ可以对请求进行“削峰填谷”&#xff0c;即通过消费端限流的方式限制消息的拉取速度&#xff0c;达到保护消费端的目的。 生产者批量发送消息&#xff1a; Test public void testSendBatch() {…

聊聊 Python 的单元测试框架:unittest!

前言 说到 Python 的单元测试框架&#xff0c;想必接触过 Python 的朋友脑袋里第一个想到的就是 unittest。 的确&#xff0c;作为 Python 的标准库&#xff0c;它很优秀&#xff0c;并被广泛用于各个项目。但你知道吗&#xff1f;其实在 Python 众多项目中&#xff0c;主流的…

【SQL篇】一、Flink动态表与流的关系以及DDL语法

文章目录 1、启动SQL客户端2、SQL客户端常用配置3、动态表和持续查询4、将流转为动态表5、用SQL持续查询6、动态表转为流7、时间属性8、DDL-数据库相关9、DDL-表相关 1、启动SQL客户端 启动Flink&#xff08;基于yarn-session模式为例&#xff09;&#xff1a; /opt/module/f…