当前位置: 首页 > news >正文

Web Components学习(2)-语法

一、Web Components 对 Vue 的影响

尤雨溪在创建 Vue 的时候大量参考了 Web Components 的语法,下面写个简单示例。

首先写个 Vue 组件 my-span.vue:

<!-- my-span.vue -->
<template><span>my-span</span>
</template><script>
export default {}
</script><style>
span {color: purple;
}
</style>

这是很标准的 Vue 组件,不过非常遗憾的是 HTML 文件并不能有效的利用这个 vue 文件,如果想让它能够正确运行,还需要下载 node、webpack、vue-loader 将其打包,而且它只能在 Vue 的项目中使用,也就是必须依赖 Vue 的安装包。如果在 React、Angular 甚至 jQuery 项目中,这个组件就不能用了。

但是以前只需要将它稍稍修改一下,它就会变成 Web Components 文件,能够直接在浏览器中运行。

只需要修改 <script> 中的 JS 代码和文件后缀:

<!-- my-span.html -->
<template><span>my-span</span>
</template><script>
// 获取 DOM 元素
const dom = document.currentScript.ownerDocument.querySelector('template').content// 有点像 React 定义组件的写法
class MySpan extends HTMLElement {constructor() {super()this.attachShadow({ mode: 'open' }).appendChild(dom)}
}// 注册组件
customElements.define('my-span', MySpan)
</script><style>
span {color: purple;
}
</style>

使用 HTML Imports 在 HTML 页面中引入组件:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title><!-- HTML Imports --><link rel="import" href="my-span.html">
</head>
<body><my-span></my-span>
</body>
</html>

但是现在 HTML Imports 已废弃(被 ES Modules 的代替),所以不能使用这种方式了。

如果还想要以独立模块的方式引入,那么就要通过 JS 生成 HTML 和 CSS:

// my-span.js
class MySpan extends HTMLElement {constructor() {super()this.render()}// 生成 HTML 和 CSSrender() {const shadow = this.attachShadow({ mode: 'open' })const dom = document.createElement('span')const style = document.createElement('style')dom.textContent = 'my-span'style.textContent = `span {color: purple;}`shadow.appendChild(style)shadow.appendChild(dom)}
}// 注册组件
customElements.define('my-span', MySpan)
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title><!-- HTML Imports(已废弃) --><!-- <link rel="import" href="my-span.html"> --><!-- ES Modules --><script type="module" src="my-span.js"></script>
</head>
<body><my-span></my-span>
</body>
</html>

注意:使用 ES Modules 和 HTML Imports 一样,都要开启一个 Web 服务,直接打开 HTML 文件,会以文件协议(file://)的方式打开,控制台会报跨域错误。可以使用 vscode 的 Live Server 插件打开 HTML。或者不使用 ES Modules:<script src="my-span.js"></script>

也可以提前在 HTML 页面中通过 <template> 原生标签写好 DOM 结构,然后在组件中通过 DOM API 获取模板内容,不过这样并没有将组件作为独立的模块分离出来。

如果想使用插槽,只需要将 <slot /> 添加进去:

const dom = document.createElement('span')
const style = document.createElement('style')
// dom.textContent = 'my-span'
dom.innerHTML = '<slot>默认内容</slot>'
style.textContent = `span {color: purple;}
`

使用上也和 Vue 一样:

<!-- 默认内容 -->
<my-span></my-span>
<!-- 自定义内容 -->
<my-span>自定义内容</my-span>

如果想使用具名插槽(多个插槽):

const dom = document.createElement('span')
const style = document.createElement('style')
// dom.textContent = 'my-span'
dom.innerHTML = `<slot>默认内容</slot><slot name="content">默认内容</slot>
`
style.textContent = `span {color: purple;}
`

使用:

<my-span><h1>默认插槽</h1><h2 slot="content">另一个插槽</h2>
</my-span>

Vue 新语法已经建议使用 v-slot,而 Web Components 还是 slot

二、HTML Imports

Web Components 的历史
Web Components 不是一门单一的技术,而是四门技术的组合,这四门技术分别是:

  • HTML Imports
  • HTML templates
  • Custom Elements
  • Shadow DOM

HTML Imports

HTML Imports 就是上面示例中的 用来引入另一个 HTML 文件。

可惜 HTML Imports 已经被废弃,如果想正常使用 HTML Imports 代码查看效果,可以安装低版本浏览器,例如 Chrome 79:

在这里插入图片描述
通过上面的示例可以看到 HTML Imports 很好用,为什么会被废弃?这就要讲讲 Web Components 的前世今生了。

很多人都认为 Google 是一个比 IE 还“遵纪守法”的好公民,因为它一直遵守 W3C、ECMA 的标准,才可以得以干掉 IE 成为浏览器市场的占有率之王。

其实 Google 可不老实,它经常会倒逼标准的形成。比方说 Google 自己实现了一个 CSS 属性,那时候 W3C 并没有发布标准,于是它就在自己自创的属性前加个前缀 -webkit-,这代表只是它自己浏览器的实验性属性,并没有破坏标准私自发布属性。

可是开发者觉得这个属性真的很好用,可以实现很酷炫的效果,其他浏览器的厂商有的是觉得这个属性确实很不错,而有的是感觉到了压力,总而言之,所有浏览器厂商最终都实现了这个属性,为了表示自己也没有破坏标准私自发布属性,大家都默默地在这个属性前面加上自己浏览器内核的前缀,像 -moz--ms--o-

虽然这个属性没有在 W3C 等机构成为标准,但它已经成为了**“事实标准”**,世界各地的开发者们也都已经用这个属性实现出来成千上万个网站了,最终也不得不把它标为标准。于是 Google 最终自己研究出来的属性就这样成为了标准。大家再也不用写那么烦人的前缀了。Web Components 也正是基于这样的一种情况下诞生的。

话说在 2011 年的时候 Google 就推出了 Web Components 的概念,当时前端还没有**“模块化”的概念,甚至都没有“前端”**的概念,这个时期 Google 就已经敏锐的察觉到前端需要组件化,但最开始他们也只是提出了这个概念,并没有开发出真正能用的前端组件化。

2015 年 Web Components 终于能用了,所以网上开始有人介绍 Web Components,这也是为什么网上大部分 Web Components 文章都是 2015 - 2016 写的(内容还包括 HTML Imports)。

那么为什么这么多年过去了,Web Components 还没有火起来呢?

因为 Google 的做法引起了其他浏览器厂商的不满,凭什么这么重要的新功能就你一家说了算,平时你实现的 CSS3 属性啥的,我们睁一只眼闭一只眼也就算了,可 Web Components 是非常重大的一项功能,API 长什么样子都是你自己定,我们不同意。于是 Web Components 的第一版,也就是 V0,就只有 Google 自己实现了。

Google 也意识到,虽然自己目前市场占有率全球称霸,但只要其它浏览器不支持还是不会有人用,毕竟大家都要考虑兼容性的问题,不可能只考虑用 Google 内核的用户上网才能够看到效果,其它浏览器就不管。

所以 Google 决定,和其它主流浏览器厂商一起讨论一下,在讨论中大家就产生了激烈的分歧,比如苹果系统的浏览器 Safari 觉得 Shadow DOM 应该始终保持封闭以保证独立性,而 Google 则认为要始终保持开放,让用户能够访问到,不然 Web Components 组件库在用户的眼中始终是一个无法窥视内部构造的黑盒;还有火狐浏览器觉得马上要出 ES6 了,HTML Imports 不用实现,先看看 ES6 的模块化怎么样,感觉它也能代替 HTML Imports 的功能。

于是根据各个浏览器厂商的不满,又修订了第二个版本:V1,这正是目前使用的版本。就在各大浏览器厂商不断扯皮的过程中,三大框架崛起了:Angular、React、Vue,它们都有组件化的功能,于是其它浏览器厂商实现 Web Components 的动力就有点不足了,本来实现起来就挺复杂的,现在更不想实现了。

但是几年过后,大家发现浏览器真的需要一个原生的组件化技术,开发者们也一直都在询问到底为什么就是不实现 Web Components。

基于种种压力之下,Safari 在 2017 年实现了 Web Components,当然只实现了一部分,因为他们至今都不是很认同 Google 的 is 属性(类似 Vue 的 is 属性),所以他们就是不实现,反正 Web Components 还没有成为标准(2017 年),这也不算不遵守规范。

而火狐则是在 2018 年实现的 Web Components。

微软的 Edge 浏览器现在改用 Google 的内核了,IE 就不要提了。

Opera 也早就改用 Google 内核了。

至此所有浏览器都实现了 Web Components,不过它终究还是来的太晚了点,三大框架早已瓜分了市场,形成了三足鼎立的局面。但之后随着时间的推移,三大框架有可能会用 Web Components 去实现自己底层的组件化系统。

而 Vue CLI 早就实现了能将 Vue 组件编译成 Web Components 的功能。

而且一些组件库为了能够跨框架运行,也是采用了 Web Components 来实现,比如 Taro 3 为了能够让写不同框架的的人都能用上组件,特意采用了 Web Components 来实现的基础组件。

既然 HTML Imports 已经废弃,这里也不再学习它的具体用法。但可以介绍一下它的下一代技术 HTML Modules。

下面是一个无法运行的示例:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><script type="module">import A from './component.html'</script>
</body>
</html>
<!-- component.html -->
<template></template><script type="module"></script>

目前还没有任何浏览器实现了这一提案,所以上例代码无法演示,而且这种写法目前来说争议非常大,因为在<script>标签里引入了一个 HTML 文件,之所以要这么做,是因为 <template> 通常就是用来引入到 JS 文件里使用的。

下面介绍 Web Components 中最重要的一项技术,同时也是所有浏览器都没有提出反对意见,一致通过的一项技术 —— Custom Elements(自定义元素)。

Shadow DOM 和 HTML templates( and slots) 目前主流浏览器也同样支持,通常都会应用于 Custom Elements,前者是用于封装独立于主文档的 DOM,后者类似 Vue 的 Slot,本文不作详解。

Custom Elements 自定义元素

MDN:使用 custom elements

基础使用
window 全局对象上有一个 customElements 提供自定义元素支持,它包含四个 API:

  • define:注册/定义自定义元素
  • get:获取自定义元素的构造函数
  • whenDefined:
  • upgrade:
  • define 示例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Custom Elements</title></head><body><!-- 使用元素 --><long-time-no-see></long-time-no-see><!-- 不能写成自闭和标签,浏览器会当作起始标签包裹后面的全部内容 --><!-- <long-time-no-see /> --><script>// 注册组件(自定义元素)window.customElements.define(// 参数1:元素名,必须包含一个短横线,以区分原生元素'long-time-no-see',// 参数2:用于定义元素行为的类(类似 React 中的类组件),必须继承自 HTMLElementclass extends HTMLElement {constructor() {super()// custome elements 类中的 this 指向组件本身console.log(this)this.innerHTML = '<h1>好久不见</h1>'this.onclick = () => alert('你还好吗')}})// 多次注册相同名称的组件会报错:// the name "long-time-no-see" has already been used with this registry// window.customElements.define('long-time-no-see', class extends HTMLElement {})// 获取自定义元素的构造函数console.log(customElements.get('long-time-no-see'))// 如果获取的是一个并没有被定义的元素,则返回 undefined// 使用场景1:用于判断组件是否已被注册过// 使用场景2:扩展第三方组件console.log(customElements.get('long-time-no-see1'))</script></body>
</html>

get 示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Custom Elements</title></head><body><!-- 扩展第三方组件 --><my-bubbles click>我扩展的 bubbles</my-bubbles><script type="module">import { FcBubbles } from 'https://unpkg.com/fancy-components'// 注册组件new FcBubbles()// 获取第三方组件的构造函数,用于继承扩展const FcBubblesConstructor = customElements.get('fc-bubbles')customElements.define('my-bubbles',class extends FcBubblesConstructor {constructor() {super()this.onclick = () => console.log('自定义点击事件')}})</script></body>
</html>

whenDefined 示例
通常都会将

当渲染引擎读取到自定义元素的时候,并不知道它是什么元素(此时注册脚本还没执行),一般来说当渲染引擎碰到一个不认识的元素的时候,会认为这是一个无效的元素。

不过自定义元素的命名规则要求必须包含短横杠 -,是为了和原生元素区分开,所有当渲染引擎看到一个不认识的元素,但是名称中带有横杠连字符,会将它认为是一个未定义的自定义元素,不会当作一个无效元素。当执行到注册自定义元素的代码时,就会将之前未定义的元素标记为定义的元素。

定义的元素对应的伪类选择器就是 :defined,未定义的元素对应的伪类选择器就是 :not(:defined)

通过这个伪类选择器,可以在定义元素之前的空白时间内,设置自定义元素的加载样式。

whenDefine 是元素定义后触发的回调,通常用于异步注册组件的时候:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Custom Elements</title><style>:not(:defined) {width: 120px;height: 60px;background: gray linear-gradient(-60deg, transparent, transparent 20%, white 40%, transparent 60%) 0 / 300%;border-radius: 15px;animation: loading 2s infinite;display: grid;place-items: center;}@keyframes loading {to {background-position: 300% 0;}}</style></head><body><long-time-no-see>Loading</long-time-no-see><script>// 模拟 JS 代码执行延迟setTimeout(() => {customElements.define('long-time-no-see',class extends HTMLElement {})}, 3000)// 返回一个 PromisecustomElements.whenDefined('long-time-no-see').then(() => {document.querySelector('long-time-no-see').innerHTML = '好久不见'}).catch(err => console.log(err))</script></body>
</html>

upgrade 示例
upgrade 是升级的意思,如果在定义元素之前先使用 JS 创建了元素,则元素实例并不是继承的定义元素行为的类,可以使用 upgrade 将其升级为期望的样子:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Custom Elements</title></head><body><script>// 先使用 JS 创建自定义元素const el = document.createElement('vue-react')// 再注册自定义元素class VueReact extends HTMLElement {}customElements.define('vue-react', VueReact)// 返回 falseconsole.log(el instanceof VueReact)// 升级元素customElements.upgrade(el)// 返回 trueconsole.log(el instanceof VueReact)</script></body>
</html>

在这里插入图片描述

生命周期
我们经常会在组件的初始阶段设置监听器,在组件的挂载阶段获取 DOM 元素,在组件的更新阶段发送一些 ajax 请求,在组件的卸载阶段做一些清理操作(例如移除定时器)。

Web Components 的生命周期比 Vue 和 React 的都要少。

下面通过 Vue 的生命周期来对比 Web Components 的生命周期:
在这里插入图片描述
connectedCallback vs mounted
Vue 和 React 都是靠一个根元素(Root)来实现的,默认 Vue 里是一个 id 为 app 的元素,React 中是一个 id 为 root 的根元素:

<div id="app"></div>

一开始 DOM 都是空的,是靠 JavaScript 动态生成的 DOM,然后再往里填充:

const component = document.createElement('h1')

它需要挂载到 HTML 页面上才能显示:

const root = document.getElementById('app')
root.append(component)

所以这个过程叫挂载,而对应的生命周期命名为 mounted。

而自定义元素组件通常是先在 HTML 中编写组件,浏览器会先解析到它:

<life-cycle></life-cycle>

然后浏览器继续解析到定义它的 JS 代码时,就会将其与 JS 定义的元素(构造函数中的 this)进行连接:

customElements.define('life-cycle', class extends HTMLElement {})

这个连接的过程和 Vue、React 挂载的过程有很大的区别,所以它叫 connectedCallback

adoptedCallback 示例
adopt 是收养的意思,DOM API document.adoptNode可以剪切文档(包括另一个文档)中的节点,可以通过它将其它文档上的节点剪切到当前文档中使用,这个过程可以成为“收养(adopt)”,例如:

<!-- iframe.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>iframe</title>
</head>
<body><h1>我来自 iframe</h1>
</body>
</html>
<!-- index.html -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /></head><body><iframe src="./iframe.html"></iframe><script>const iframe = document.querySelector('iframe')iframe.onload = () => {const dom = iframe.contentDocument.querySelector('h1')// 剪切元素const adoptDom = document.adoptNode(dom)// 添加到当前文档document.body.append(adoptDom)}</script></body>
</html>

注意:要开启一个 web 服务访问页面,否则获取不到 iframe 的内容。并且要访问 iframe 的内容还要符合同源要求。

而 Web Components 的 adoptedCallback 生命周期回调指的是元素被移动(剪切)到新的文档时被调用,正符合这个场景:

<!-- iframe.html -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>iframe</title></head><body><life-cycle>我来自 iframe</life-cycle><script>customElements.define('life-cycle',class extends HTMLElement {constructor() {super()// 相当于 Vue3 的 setupconsole.log('constructor')}connectedCallback() {// 相当于 Vue 的 mountedconsole.log('connected')}disconnectedCallback() {// 相当于 Vue 的 unmountedconsole.log('disconnected')}adoptedCallback() {console.log('adopted')}})</script></body>
</html>
<!-- index.html -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /></head><body><iframe src="./iframe.html"></iframe><script>const iframe = document.querySelector('iframe')iframe.onload = () => {const dom = iframe.contentDocument.querySelector('life-cycle')// 剪切元素const adoptDom = document.adoptNode(dom)// 添加到当前文档document.body.append(adoptDom)}</script></body>
</html>

该示例可以查看不同生命周期函数触发的时机。

相关文章:

Web Components学习(2)-语法

一、Web Components 对 Vue 的影响 尤雨溪在创建 Vue 的时候大量参考了 Web Components 的语法&#xff0c;下面写个简单示例。 首先写个 Vue 组件 my-span.vue&#xff1a; <!-- my-span.vue --> <template><span>my-span</span> </template>…...

Lesson 9.2 随机森林回归器的参数

文章目录一、弱分类器的结构1. 分枝标准与特征重要性2. 调节树结构来控制过拟合二、弱分类器的数量三、弱分类器训练的数据1. 样本的随机抽样2. 特征的随机抽样3. 随机抽样的模式四、弱分类器的其他参数在开始学习之前&#xff0c;先导入我们需要的库。 import numpy as np im…...

Kubernetes Secret简介

Secret概述 前面文章中学习ConfigMap的时候&#xff0c;我们说ConfigMap这个资源对象是Kubernetes当中非常重要的一个对象&#xff0c;一般情况下ConfigMap是用来存储一些非安全的配置信息&#xff0c;如果涉及到一些安全相关的数据的话用ConfigMap就非常不妥了&#xff0c;因…...

Redis 哨兵(Sentinel)

文章目录1.概述2. 没有哨兵下主从效果3.搭建多哨兵3.1 新建目录3.2 复制redis3.3 复制配置文件3.4 修改配置文件3.5 启动主从3.6 启动三个哨兵3.7 查看日志3.8 测试宕机1.概述 在redis主从默认是只有主具备写的能力&#xff0c;而从只能读。如果主宕机&#xff0c;整个节点不具…...

精读笔记 - How to backdoor Federated Learning

文章目录 精读笔记 - How to backdoor Federated Learning1. 基本信息2. 系统概要3. 攻击模型3.1 问题形式化定义3.1.1 前提假设3.1.2 攻击目标3.2 创新点3.2.1 Semantic Backdoor3.2.2 攻击方法4. 实验验证4.1 图像分类4.2 实验操作4.2.1 超参数设置4.2.2 衡量标准4.3 结果分析…...

即时通讯系列-N-客户端如何在推拉结合的模式下保证消息的可靠性展示

结论先行 原则&#xff1a; server拉取的消息一定是连续的原则&#xff1a; 端侧记录的消息的连续段有两个作用&#xff1a; 1. 记录消息的连续性&#xff0c; 即起始中间没有断层&#xff0c; 2. 消息连续&#xff0c; 同时意味着消息是最新的&#xff0c;消息不是过期的。同…...

关于js数据类型的理解

目录标题一、js数据类型分为 基本数据类型和引用数据类型二、区别&#xff1a;传值和传址三、深浅拷贝传值四、数据类型的判断一、js数据类型分为 基本数据类型和引用数据类型 1、基本数据类型 Number、String、Boolean、Null、undefined、BigInt、Symbol 2、引用数据类型 像对…...

大一上计算机期末考试考点

RGB颜色模型也称为相加混色模型 采样频率大于或等于原始声音信号最高频率的两倍即可还原出原始信号. 声音数字化过程中&#xff0c;采样是把时间上连续的模拟信号在时间轴上离散化的过程。 量化的主要工作就是将幅度上连续取值的每一个样本转换为离散值表示。 图像数字化过…...

微搭问搭001-如何清空表单的数据

韩老师&#xff0c;我点关闭按钮后&#xff0c;弹窗从新打开&#xff0c;里面的数据还在&#xff0c;这个可以从新打开清除不&#xff1f; 点关闭的时候清掉 就是清楚不掉也&#xff1f;咋清掉 清掉表单内容有属性可以做到&#xff1f; $page.widgets.id**.value “” 就可以实…...

Windows7,10使用:Vagrant+VirtualBox 安装 centos7

一、Vagrant&#xff0c;VirtualBox 是什么二、版本说明1、win7下建议安装版本2、win10下建议安装版本三、Windows7下安装1、安装Vagrant2、安装VirtualBox3、打开VirtualBox&#xff0c;配置虚拟机默认安装地址四、windows7下载.box文件&#xff0c;安装centos 71、下载一个.b…...

基于JavaEE开发博客系统项目开发与设计(附源码)

文章目录1.项目介绍2.项目模块3.项目效果1.项目介绍 这是一个基于JavaEE开发的一个博客系统。实现了博客的基本功能&#xff0c;前台页面可以进行文章浏览&#xff0c;关键词搜索&#xff0c;登录注册&#xff1b;登陆后支持对文章进行感谢、评论&#xff1b;然后还可以对评论…...

Android Framework——zygote 启动 SystemServer

概述 在Android系统中&#xff0c;所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育&#xff08;fork&#xff09;出来的&#xff0c;这也许就是为什么要把它称为Zygote&#xff08;受精卵&#xff09;的原因吧。由于Zygote进程在Android系统中有着如此重…...

在ubuntu上搭建SSH和FTP和NFS和TFTP

一、SSH服务搭建使用如下命令安装 SSH 服务&#xff1b;ssh 的配置文件为/etc/ssh/sshd_config&#xff0c;使用默认配置即可。sudo apt-get install openssh-server开启 SSH 服务以后我们就可以在 Windwos 下使用终端软件登陆到 Ubuntu&#xff0c;比如使用 Mobaxterm。二、FT…...

ThinkPHP 6.1 模板篇之文件加载

本文主要讲述模板中如何使用包含文件、引入css/js文件及路径优化。 包含文件 使用{include}标签来加载公用重复的文件&#xff0c;比如头部、尾部和导航部分 包含用法 1.创建公用文件 在模版 view 目录创建一个 common公共目录&#xff0c;分别创建 header、footer 和 nav …...

操作系统内核与安全分析课程笔记【1】链表、汇编与makefile

文章目录链表循环双向链表哈希链表其他链表汇编内联汇编扩展内联汇编makefile链表 链表是linux内核中关键的数据结构。在第二次课中&#xff0c;重点介绍了循环双向链表和哈希链表。这两种链表都在传统的双向链表的基础之上进行了针对效率的优化。(ps&#xff1a;这部分可以通…...

华为OD机试题 - 九宫格按键输入(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:九宫格按键输入题目输入输出示例一输入输出说明示例二输入输出说…...

PMSM控制_foc 控制环路

整个系统的控制过程有以下部分&#xff0c;以无感FOC&#xff0c;双电阻电流采样&#xff0c;控制周期为 10KHz 为例&#xff1a; 1、在每隔一个 PWM 周期采样一次两相电流 2、进行 FOC 的计算 &#xff08;1&#xff09;clarke 变换&#xff0c;将电流变换至静止坐标系下的 Ia…...

Linux 练习七 (IPC 共享内存)

文章目录System V 共享内存机制&#xff1a;shmget shmat shmdt shmctl案例一&#xff1a;有亲缘关系的进程通信案例二&#xff1a;非亲缘关系的进程通信内存写端write1.c内存读端read1.c案例三&#xff1a;不同程序之间的进程通信程序一&#xff0c;写者shmwr.c程序二&#xf…...

【数据库原理复习】ch4 完整性约束 SQL定义

这里写目录标题基本概念实体完整性参照完整性违规处理用户自定义完整性约束条件定义完整性约束命名字句基本概念 完整性约束主要包括 实体完整性参照完整性用户自定义完整性 实体完整性 关系模型中实体完整性通常在建表时候添加primary key完成 # primary key定义 create …...

【2023年的就业形势依旧严峻】

2023年口罩放开的第一年&#xff0c;也是第一个招聘会&#xff0c;挤满了求职者和用人单位&#xff0c;大多数都是想着重新开始&#xff0c;抓住金三银四的好时机&#xff0c;找到心仪的工作和符合岗位要求的人才&#xff0c;一起整装出发。我们理想的状态是&#xff0c;经济已…...

Linux下LED灯驱动模板详解

一、地址映射我们先了解MMU&#xff0c;全称是Memory Manage Unit。在老版本的Linux中要求处理器必须有MMU&#xff0c;但是现在Linux内核已经支持五MMU。MMU主要完成的功能如下&#xff1a;1、完成虚拟空间到物理空间的映射2、内存保护&#xff0c;设置存储器的访问权限&#…...

【C++】你不得不爱的——继承

凡是面向对象的语言&#xff0c;都有三大特性&#xff0c;继承&#xff0c;封装和多态&#xff0c;但并不是只有这三个特性&#xff0c;是因为者三个特性是最重要的特性&#xff0c;那今天我们一起来看继承&#xff01; 目录 1.继承的概念及定义 1.概念 2.继承的定义 2.基类…...

数据库系统概论

文章目录前言基础篇&#xff1a;1-5章第 1 章 绪论1.1 数据库系统概述1.2 数据模型1.3 数据库系统的结构1.4 数据库系统的组成1.5 小结第 2 章 关系数据库1.关系模型1.1 关系数据结构1.2 关系完整性约束实体完整性、参照完整性、用户定义完整性2.关系代数8种关系代数运算符并 ∪…...

32位处理器AM6528BACDXEA、AM6548BACDXEAF基于Arm Cortex-A53内核【工业4.0嵌入式产品应用】

AM6528BACDXEA、AM6548BACDXEAF 处理器是专为满足工业4.0嵌入式产品对处理性能的复杂需求而设计的Arm应用处理器。AM654x和AM652x器件将四个或两个Arm Cortex-A53内核与一个双Arm Cortex-R5F MCU子系统结合在一起。这些包含的功能旨在帮助客户实现终端产品的功能安全目标。它还…...

多图片怎么转换成PDF?这招教你轻松转换

多图片怎么转换成PDF&#xff1f;我们经常会传输图片文件给同事或者朋友&#xff0c;但是多张图片的传输比较麻烦&#xff0c;有的时候传输比较慢&#xff0c;而且也不便于查看&#xff0c;所以我们就可以将需要传输的多张图片转换成一个PDF文件&#xff0c;这样查看文件时就可…...

kali双网卡

先单独开启一个网卡&#xff0c;配置/etc/network/interfaces 修改为如下配置 This file describes the network interfaces available on your system and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* The loopb…...

【wed前端初级课程】第一章 什么是HTML

什么是WEB前端&#xff1f; 简单来说就是网页&#xff0c;只是这个网页它是由多种技术参与制作的&#xff0c;用来向用户展示的页面。 HTML(超文本标签语言)&#xff1a;它决定了网页的结构。 CSS&#xff1a;网页的装饰器。 JavaScript&#xff1a;JavaScrip最初是因为校验…...

sd卡格式化后数据恢复怎么操作

有时候我们需要清空SD卡数据文件&#xff0c;有时候则是因为需要修复SD卡所以需要格式化&#xff0c;但是却被提示无法格式化SD卡。这种情况往往是由于平时SD卡使用时的一些不良习惯或是SD卡中病毒&#xff0c;病毒在运行SD卡中的软件所造成的。那么sd卡格式化后数据恢复怎么操…...

论文阅读笔记|大规模多标签文本分类

多标签文本分类&#xff08;Extreme Multi Label Classification, MLTC&#xff09;是自然语言处理领域中一个十分重要的任务&#xff0c;其旨在从一个给定的标签集合中选取出与文本相关的若干个标签。MLTC可以广泛应用于网页标注&#xff0c;话题识别和情感分析等场景。大规模…...

国际化翻译navigator.language与语种对照表

代码(navigator.language) 语种 字段名 "zh-CN", 中文 Chinese "zh-SG" 马新简体 Chinese_SG "zh-TW","zh-HK", 繁体中文 Chinese_TW "en", "en-US"&#xff08;美国&#xff09;, "en-EG"…...

Matlab进阶绘图第6期—雷达图/蜘蛛图/星图

雷达图&#xff08;Radar Chart&#xff09;&#xff0c;又称星图、蜘蛛图、蜘蛛网图、网络图、Kiviat图等&#xff0c;是一种以从同一点开始的轴上表示的三个以上变量的二维图表的形式&#xff0c;来显示多变量数据的图形方法。 雷达图可以直观地对多维数据集目标对象的性能、…...

Javascript的ES6 class写法和ES5闭包写法性能对比

看到很多闭包写法的函数, 一直怀疑它对性能是否有影响. 还有就是备受推崇的React Hooks函数式写法中出现大量的闭包和临时函数, 我很担心这样会影响性能. 于是, 做了一个实验来做对比. 这个实验很简单, 用md5计算一百万次. 计算过程将结果再放回参数, 这样避免结果没被引用被…...

探秘MySQL——全面了解索引、索引优化规则

文章目录0.什么是索引1.常用索引分类逻辑维度底层数据结构维度物理维度&#xff08;InnoDB&#xff09;2.为什么底层是B树平衡二叉查找树红黑树B树&#xff08;多叉&#xff09;B树&#xff08;多叉&#xff09;3.MySQL索引优化SQL性能分析之explainQ.MySQL如何查看查询是否用到…...

战斗力最强排行榜:10-30人团队任务管理工具

工欲善其事&#xff0c;必先利其器。在高效的任务执行过程中&#xff0c;选择灵活轻便的项目管理工具来提升工作效率、适应快速多变的发展诉求&#xff0c;对团队来说&#xff0c;至关重要。但是如果团队不大&#xff0c;企业对这块的预算又有限&#xff0c;大型的团队任务管理…...

2023-03-09干活小计

强化学习&#xff1a; 强化学习用智能体&#xff08;agent&#xff09;这个概念来表示做决策的机器。 感知、决策和奖励 感知。智能体在…...

基数排序算法

目录&#xff1a;什么是基数排序&#xff1f;基本原理核心思想实现逻辑代码实现复杂度分析总结什么是基数排序&#xff1f; 基数排序&#xff1a;基数排序&#xff08;Radix sort&#xff09;是一种非比较型整数排序算法&#xff0c; 基本思想主要是通过关键字间的比较和移动记…...

项目实战典型案例24——xxljob控制台不打印日志排查

xxljob控制台不打印日志排查一&#xff1a;背景介绍问题截图问题解读二&#xff1a;思路&方案三&#xff1a;过程四&#xff1a;总结一&#xff1a;背景介绍 本篇博客是对xxljob控制台不打印日志排查进行的总结和进行的改进。 目的是将经历转变为自己的经验。通过博客的方…...

旋转框目标检测mmrotate v1.0.0rc1 之RTMDet训练DOTA的官方问题解析整理(四)

关于rotated_rtmdet_l-coco_pretrain-3x-dota_ms.py配置文件的batchsize和学习率设置问题&#xff1a;回答&#xff1a;如何在mmrotate中绘制特征图问题&#xff1a;回答&#xff1a;你好AllieLan&#xff0c;您可以尝试使用https://github.com/open-mmlab/mmyolo/blob/main/de…...

4个顶级的华为/小米/OPPO/Vivo手机屏幕解锁工具软件

有好几次用户发现自己被锁定在他们的华为/小米/OPPO/Vivo设备之外&#xff0c;我们知道这可能是一种非常可怕的体验。在这种情况下&#xff0c;找到安卓手机解锁软件&#xff0c;重新获得手机中重要数据和文件的访问权限。看看这篇文章&#xff0c;因为我们将与您分享什么是解锁…...

华为OD机试题 - 和最大子矩阵(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:和最大子矩阵题目输入输出示例一输入输出说明Code思路版权说明华…...

企业电子招标采购系统源码之项目说明和开发类型

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…...

Python高频面试题——装饰器(带大家理解装饰器的本质)

装饰器概念装饰器本质上是一个python函数&#xff0c;它可以让其他函数在不需要做任何代码变动的前提下增加额外功能&#xff0c;装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景&#xff0c;比如&#xff1a;插入日志、性能测试、事务处理、缓存、权限验证等场景…...

全方位解读智能中控屏发展趋势!亚马逊Alexa语音+Matter能力成必备

随着智能家居行业逐步从碎片化的智能单品阶段&#xff0c;迈向体验更完整的全屋互联阶段&#xff0c;智能中控屏作为智能家居最佳的入口之一&#xff0c;在年轻人青睐全屋智能装修的风潮下&#xff0c;市场潜力彻底被引爆。 一、为什么是智能中控屏&#xff1f; 在智能音箱增…...

JAVA练习74-括号生成

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 3月10日练习内容 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目-…...

Java ORM开发 更全面的应用场景

1. 一个web系统, 想支持多种数据库, 如同时要用mysql, oracle 需要动态切换数据源? 2. 读写分离, 但读库与写库是不同的类型, 如分别是: mysql, oracle 3. 智能化自动过滤null和空字符串&#xff0c;不再需要写判断非空的代码。 4.动态/任意组合查询条件,不需要提前准备da…...

SpringBoot【基础篇】---- 基础配置

SpringBoot【基础篇】---- 基础配置1. 属性配置2. 配置文件分类3. yaml 文件4. yaml 数据读取1. 读取单一数据2. 读取全部数据3. 读取对象数据yaml 文件中的数据引用1. 属性配置 SpringBoot 通过配置文件 application.properties 就可以修改默认的配置&#xff0c;那咱们就先找…...

手机磁吸背夹散热器制冷快速方案

手机散热器是什么&#xff1f;手机散热器分为几种类型&#xff1f;手机散热的方式都有哪些&#xff1f; 因为经常玩游戏&#xff0c;手机发热得厉害&#xff0c;都可以煎鸡蛋了&#xff0c;心想着要买个东西给手机散散热&#xff0c;没想到还真的有手机散热器。 不知道手机散…...

青岛OJ(QingdaoU/OnlineJudge)部署如何直连数据库批量修改

1.postgres数据库QingdaoU/OnlineJudge用的数据库是postgreSQL&#xff0c;一个关系型数据库。默认端口是5432&#xff0c;我们下载一个navcat 15以上的版本&#xff0c;用来连数据库。2.修改docker-compose.yml文件修改docker-compose.yml&#xff0c;手动添加一个端口&#x…...

渗透测试——信息收集(详细)

信息收集&#xff1a;前言&#xff1a;信息收集是渗透测试除了授权之外的第一步&#xff0c;也是关键的一步&#xff0c;尽量多的收集目标的信息会给后续的渗透事半功倍。收集信息的思路有很多&#xff0c;例如&#xff1a;页面信息收集、域名信息收集、敏感信息收集、子域名收…...

什么是谐波

什么是谐波 目录 1. 问题的提出 2. “谐”字在中英文中的原意 2.1 “谐”字在汉语中的原义 2.2 “谐”字对应的英语词的原义 3.“harmonics(谐波)”概念是谁引入物理学中的&#xff1f; 4.“harmonics(谐波)”的数学解释 1. 问题的提出 “谐波”这个术语用于各种学科&am…...