Web Components学习(2)-语法

news2024/11/26 0:27:48

一、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 和 CSS
  render() {
    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 中的类组件),必须继承自 HTMLElement
        class 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)

      // 返回一个 Promise
      customElements
        .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)

      // 返回 false
      console.log(el instanceof VueReact)

      // 升级元素
      customElements.upgrade(el)

      // 返回 true
      console.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 的 setup
            console.log('constructor')
          }
          connectedCallback() {
            // 相当于 Vue 的 mounted
            console.log('connected')
          }
          disconnectedCallback() {
            // 相当于 Vue 的 unmounted
            console.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>


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

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

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

相关文章

Spring——spring整合JUnit

JUnit定义: Junit测试是程序员测试&#xff0c;即所谓 白盒测试 &#xff0c;因为程序员知道被测试的软件如何&#xff08;How&#xff09;完成功能和完成什么样&#xff08;What&#xff09;的功能。 Junit是一套框架&#xff0c;继承TestCase类&#xff0c;就可以用Junit进行…

基于Selenium+Python的web自动化测试框架(附框架源码+项目实战)

目录 一、什么是Selenium&#xff1f; 二、自动化测试框架 三、自动化框架的设计和实现 四、需要改进的模块 五、总结 总结感谢每一个认真阅读我文章的人&#xff01;&#xff01;&#xff01; 重点&#xff1a;配套学习资料和视频教学 一、什么是Selenium&#xff1f; …

SpringBoot bean 加载顺序如何查看(源码解读)

背景 SpringBoot bean 加载顺序如何查看&#xff0c;想看加载了哪些bean&#xff0c; 这些bean的加载顺序是什么&#xff1f; 实际加载顺序不受控制&#xff0c;但会有一些大的原则&#xff1a; 1、按照字母顺序加载&#xff08;同一文件夹下按照字母数序&#xff1b;不同文件…

界面开发(4)--- PyQt5实现打开图像及视频播放功能

PyQt5创建打开图像及播放视频页面 上篇文章主要介绍了如何实现登录界面的账号密码注册及登录功能&#xff0c;还简单介绍了有关数据库的连接方法。这篇文章我们介绍一下如何在设计的页面中打开本地的图像&#xff0c;以及实现视频播放功能。 实现打开图像功能 为了便于记录实…

CobaltStrike攻击payload(有效载荷)介绍

HTA文档Office宏payload生成器有效载荷生成器windows可执行程序windows可执行程序windows stageless生成所有有效载荷HTA文档该模块为HTML Application attack&#xff08;HTML应用攻击&#xff09;。简单来说&#xff0c;就是这个包生成一个运行有效负载的HTML应用程序该模块下…

TCP UPD详解

文章目录TCP UDP协议1. 概述2. 端口号 复用 分用3. TCP3.1 TCP首部格式3.2 建立连接-三次握手3.3 释放连接-四次挥手3.4 TCP流量控制3.5 TCP拥塞控制3.6 TCP可靠传输的实现3.7 TCP超时重传4. UDP5.TCP与UDP的区别TCP UDP协议 1. 概述 TCP、UDP协议是TCP/IP体系结构传输层中的…

Flink 定时加载数据源

一、简介 flink 自定义实时数据源使用流处理比较简单&#xff0c;比如 Kafka、MQ 等&#xff0c;如果使用 MySQL、redis 批处理也比较简单 如果需要定时加载数据作为 flink 数据源使用流处理&#xff0c;比如定时从 mysql 或者 redis 获取一批数据&#xff0c;传入 flink 做处…

三、HTTP协议之三

文章目录一、HTTPS协议概述二、 HTTPS使用成本三、从HTTP到HTTPS四、HTTP协议的瓶颈五、双工通信的websocket六、HTTP2.0一、HTTPS协议概述 二、 HTTPS使用成本 HTTPS对性能的影响 https之所有安全是因为使用TLS(SSL)来加密传输. 三、从HTTP到HTTPS 了解个大概 第一步&#x…

react:二、jsx语法规则

目录 1.传输数据的xml和json格式举例 2.jsx语法规则 3.js语句跟js表达式的区别 4.jsx的小练习 1.传输数据的xml和json格式举例 2.jsx语法规则 1.定义虚拟DOM时&#xff0c;不要写引号。 2.标签中混入JS表达式时要用{}。 3.样式的类名指定不要用class&#xff0c;要用cla…

第十一章 寡头垄断市场中的企业决策

寡头垄断市场的定义、条件 寡头垄断市场&#xff1a;少数几家企业控制了某一行业的市场&#xff0c;供给该行业生产的大部分产品 寡头垄断市场应具备的条件&#xff1a; 一个行业或市场中&#xff0c;只有少数几家企业企业之间存在着相互制约、相互依存的关系新企业进入行业比…

golang大杀器GMP模型

golang 大杀器——GMP模型 文章目录golang 大杀器——GMP模型1. 发展过程2. GMP模型设计思想2.1 GMP模型2.2 调度器的设计策略2.2.1 复用线程2.2.2 利用并行2.2.3 抢占策略2.2.4 全局G队列2.3 go func()经历了那些过程2.4 调度器的生命周期2.5 可视化的CMP编程2.5.1 trace方式2…

【LeetCode】33. 搜索旋转排序数组、1290. 二进制链表转整数

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 33. 搜索旋转排序数组 1290. 二进制链表转整数 33. 搜索旋转排序数组 33. 搜索旋转排序…

JavaEE简单示例——Bean的实例化

简单介绍&#xff1a; 在我们之前使用某个对象&#xff0c;那么就要创建这个类的对象&#xff0c;创建对象的过程就叫做实例化。对于Spring来说&#xff0c;实例化Bean的方式有三种&#xff0c;分别是构造方法实例化&#xff0c;静态方法实例化&#xff0c;实例工厂实例化。我…

哪款手推式洗地机好用?2023洗地机推荐

虽然现在市面上的洗地机层出不穷&#xff0c;但是无论洗地机怎么变&#xff0c;关于洗地机的选择看准吸力、除菌、续航、清洁力这几点就够了。因此&#xff0c;一款好用的洗地机必须要拥有良好的清洁力和续航时间&#xff0c;最好还拥有除菌等细节功能。那么下面就让我们一起来…

【Linux】文件系统详解

&#x1f60a;&#x1f60a;作者简介&#x1f60a;&#x1f60a; &#xff1a; 大家好&#xff0c;我是南瓜籽&#xff0c;一个在校大二学生&#xff0c;我将会持续分享C/C相关知识。 &#x1f389;&#x1f389;个人主页&#x1f389;&#x1f389; &#xff1a; 南瓜籽的主页…

Unity脚本复习

1.在Project面板中显示和创建的每一个脚本其实都是一个类&#xff0c;当我们把脚本挂载到Hierarchy层级中的游戏物体时&#xff0c;其实我们就实现了将脚本类实例化为一个脚本组件&#xff08;对象&#xff09;的过程 2.在游戏运行时&#xff0c;场景加载&#xff0c;游戏对象…

云边端协同时序数据库的挑战与解决方案

现今&#xff0c;时序数据库在经济金融、环境监控、医疗生物等多个领域有着极为广泛的需求。其中&#xff0c;在环境监控等领域&#xff0c;时序数据库主要部署在云边端架构中。但如何实现云边端协同是目前TSDB所面临的巨大挑战。由于云、边和端的计算、存储资源状况和对数据管…

【LeetCode】剑指 Offer(21)

目录 题目&#xff1a;剑指 Offer 39. 数组中出现次数超过一半的数字 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;剑指 Offer 40. 最小的k个数 -…

论文阅读和分析:A Tree-Structured Decoder for Image-to-Markup Generation

目录1.主要内容&#xff1a;2.树解码器3、损失函数4、结论&#xff1a;参考&#xff1a;1.主要内容&#xff1a; &#xff08;1、提出创新的树结构解码器来表示树、输出树、优化基于注意力的编解码框架&#xff1b; &#xff08;2、设计一个问题说明特别是在复杂结构时字符解…

AidLux AI 应用案例悬赏征集活动正式启动!

ChatGPT爆火之后&#xff0c;AI领域的人才需求迎来了疯狂增长&#xff0c;AI学习也一跃成为业界大热门。 但AI囊括知识广、学习周期长&#xff0c;要克服理论、实战等多重阻碍并不容易。 而持续降低AI学习门槛是我们一直在做的事情。 为此&#xff0c;我们举办了多期AidLux …