Vue3 组件之间的通信

news2025/6/8 2:59:30

组件之间的通信

经过前面几章的阅读,相信开发者已经可以搭建一个基础的 Vue 3 项目了!

但实际业务开发过程中,还会遇到一些组件之间的通信问题,父子组件通信、兄弟组件通信、爷孙组件通信,还有一些全局通信的场景。

TIP

这一章节的内容,Vue 3 对比 Vue 2 的变化都比较大!

这一章就按使用场景来划分对应的章节吧,在什么场景下遇到问题,也方便快速找到对应的处理办法。
父子组件通信
爷孙组件通信
兄弟组件通信
全局组件通信

父子组件通信
父子组件通信是指,B 组件引入到 A 组件里渲染,此时 A 是 B 的父级;B 组件的一些数据需要从 A 组件拿,B 组件有时也要告知 A 组件一些数据变化情况。

他们之间的关系如下, Child.vue 是直接挂载在 Father.vue 下面:

# 父组件
Father.vue
│ # 子组件
└─Child.vue

常用的方法有:
在这里插入图片描述
为了方便阅读,下面的父组件统一叫 Father.vue ,子组件统一叫 Child.vue 。

WARNING

在 Vue 2 ,有的开发者可能喜欢用 $attrs / $listeners 来进行通信,但该方案在 Vue 3 已经移除了,详见 移除 $listeners 。

props / emits
这是 Vue 跨组件通信最常用,也是基础的一个方案,它的通信过程是:

1.父组件 Father.vue 通过 props 向子组件 Child.vue 传值
2.子组件 Child.vue 则可以通过 emits 向父组件 Father.vue 发起事件通知

最常见的场景就是统一在父组件发起 AJAX 请求,拿到数据后,再根据子组件的渲染需要传递不同的 props 给不同的子组件使用。

下发 props
注:这一小节的步骤是在 Father.vue 里操作。

下发的过程是在 Father.vue 里完成的,父组件在向子组件下发 props 之前,需要导入子组件并启用它作为自身的模板,然后在 setup 里处理好数据并 return 给 用。

在 Father.vue 的 script /> 里:

// Father.vue
import { defineComponent } from 'vue'
import Child from '@cp/Child.vue'

interface Member {
  id: number
  name: string
}

export default defineComponent({
  // 需要启用子组件作为模板
  components: {
    Child,
  },

  // 定义一些数据并 `return` 给 `<template />` 用
  setup() {
    const userInfo: Member = {
      id: 1,
      name: 'Petter',
    }

    // 不要忘记 `return` ,否则 `<template />` 拿不到数据
    return {
      userInfo,
    }
  },
})

然后在 Father.vue 的 template /> 这边拿到 return 出来的数据,把要传递的数据通过属性的方式绑定在组件标签上。

<!-- Father.vue -->
<template>
  <Child
    title="用户信息"
    :index="1"
    :uid="userInfo.id"
    :user-name="userInfo.name"
  />
</template>

这样就完成了 props 数据的下发。

在 template /> 绑定属性这里,如果是普通的字符串,比如上面的 title,则直接给属性名赋值就可以。

如果是变量名,或者其他类型如 number 、 boolean 等,比如上面的 index,则需要通过属性动态绑定的方式来添加,使用 v-bind: 或者 : 符号进行绑定。

另外官方文档推荐对 camelCase 风格(小驼峰)命名的 props ,在绑定时使用和 HTML attribute 一样的 kebab-case 风格(短横线),例如使用 user-name 代替 userName 传递,详见官网的 传递 prop 的细节 一节。

接收 props
注:这一小节的步骤是在 Child.vue 里操作。

接收的过程是在 Child.vue 里完成的,在 script /> 部分,子组件通过与 setup 同级的 props 来接收数据。

它可以是一个 string[] 数组,把要接受的变量名放到这个数组里,直接放进来作为数组的 item :

// Child.vue
export default defineComponent({
  props: ['title', 'index', 'userName', 'uid'],
})

但这种情况下,使用者不知道这些属性的使用限制,例如是什么类型的值、是否必传等等。

带有类型限制的 props
注:这一小节的步骤是在 Child.vue 里操作。

和 TypeScript 一样,类型限制可以为程序带来更好的健壮性, Vue 的 props 也支持增加类型限制。

相对于传递一个 string[] 类型的数组,更推荐的方式是把 props 定义为一个对象,以对象形式列出,每个 Property 的名称和值分别是各自的名称和类型,只有合法的类型才允许传入。

TIP

注意,和 TS 的类型定义不同, props 这里的类型,首字母需要大写,也就是 JavaScript 的基本类型。

支持的类型有:
在这里插入图片描述
了解了基本的类型限制用法之后,接下来给 props 加上类型限制:

// Child.vue
export default defineComponent({
  props: {
    title: String,
    index: Number,
    userName: String,
    uid: Number,
  },
})

现在如果传入不正确的类型,程序就会抛出警告信息,告知开发者必须正确传值。

如果需要对某个 Prop 允许多类型,比如这个 uid 字段,可能是数值,也可能是字符串,那么可以在类型这里,使用一个数组,把允许的类型都加进去。

// Child.vue
export default defineComponent({
  props: {
    // 单类型
    title: String,
    index: Number,
    userName: String,

    // 这里使用了多种类型
    uid: [Number, String],
  },
})

可选以及带有默认值的 props
注:这一小节的步骤是在 Child.vue 里操作。

所有 props 默认都是可选的,如果不传递具体的值,则默认值都是 undefined ,可能引起程序运行崩溃, Vue 支持对可选的 props 设置默认值,也是通过对象的形式配置 props 的选项。

其中支持配置的选项有:
在这里插入图片描述
了解了配置选项后,接下来再对 props 进行改造,将其中部分选项设置为可选,并提供默认值:

// Child.vue
export default defineComponent({
  props: {
    // 可选,并提供默认值
    title: {
      type: String,
      required: false,
      default: '默认标题',
    },

    // 默认可选,单类型
    index: Number,

    // 添加一些自定义校验
    userName: {
      type: String,

      // 在这里校验用户名必须至少 3 个字
      validator: (v) => v.length >= 3,
    },

    // 默认可选,但允许多种类型
    uid: [Number, String],
  },
})

使用 props
注:这一小节的步骤是在 Child.vue 里操作。

在 template /> 部分, Vue 3 的使用方法和 Vue 2 是一样的,比如要渲染父组件传入的 props :

<!-- Child.vue -->
<template>
  <p>标题:{{ title }}</p>
  <p>索引:{{ index }}</p>
  <p>用户id:{{ uid }}</p>
  <p>用户名:{{ userName }}</p>
</template>

但是 script /> 部分,变化非常大!

在 Vue 2 里,只需要通过 this.uid 、 this.userName 就可以使用父组件传下来的 Prop ,但是 Vue 3 没有了 this ,所以是通过 setup 的入参进行操作。

// Child.vue
export default defineComponent({
  props: {
    title: String,
    index: Number,
    userName: String,
    uid: Number,
  },

  // 在这里需要添加一个入参
  setup(props) {
    // 该入参包含了当前组件定义的所有 props
    console.log(props)
  },
})

关于 Setup 函数的第一个入参 props :

1.该入参包含了当前组件定义的所有 props (如果父组件 Father.vue 传进来的数据在 Child.vue 里未定义,不仅不会拿到,并且在控制台会有警告信息)。
2.该入参可以随意命名,比如可以写成一个下划线 _ ,通过 _.uid 也可以拿到数据,但是语义化命名是一个良好的编程习惯。
3.该入参具备响应性,父组件修改了传递下来的值,子组件也会同步得到更新,因此请不要直接解构,可以通过 toRef 或 toRefs API 转换为响应式变量

传递非 props 的属性
上一小节最后有一句提示是:
如果父组件 Father.vue 传进来的数据在 Child.vue 里未定义,不仅不会拿到,并且在控制台会有警告信息。

这种情况虽然无法从 props 里拿到对应的数据,但也不意味着不能传递任何未定义的属性数据,在父组件,除了可以给子组件绑定 props ,还可以根据实际需要去绑定一些特殊的属性。

比如给子组件设置 class、id,或者 data-xxx 之类的一些自定义属性,如果子组件 Child.vue 的 template /> 里只有一个根节点,那么这些属性默认会自动继承并渲染在 Node 节点上。

假设当前在子组件 Child.vue 是如下这样只有一个根节点,并且未接收任何 props :

TIP

如果已安装 Vue VSCode Snippets 这个 VSCode 插件,可以在空的 .vue 文件里输入 v3 ,在出现的代码片段菜单里选择 vbase-3-ts 生成一个 Vue 组件的基础代码片段。
<!-- Child.vue -->
<template>
  <div class="child">子组件</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  setup() {
    return {}
  },
})
</script>

<style scoped>
.child {
  width: 100%;
}
</style>

在 Father.vue 里对 Child.vue 传递了多个属性:

<!-- Father.vue -->
<template>
  <Child
    id="child-component"
    class="class-name-from-father"
    :keys="['foo', 'bar']"
    :obj="{ foo: 'bar' }"
    data-hash="b10a8db164e0754105b7a99be72e3fe5"
  />
</template>

回到浏览器,通过 Chrome 的审查元素可以看到子组件 Child.vue 在渲染后,按照 HTML 属性的渲染规则生成了多个属性:

<!-- Child.vue 在浏览器里渲染后的 HTML DOM 结构 -->
<div
  class="child class-name-from-father"
  id="child-component"
  keys="foo,bar"
  obj="[object Object]"
  data-hash="b10a8db164e0754105b7a99be72e3fe5"
  data-v-2dcc19c8=""
  data-v-7eb2bc79=""
>
  子组件
</div>

TIP

其中有两个以 data-v- 开头的属性是 <style /> 标签开启了 Style Scoped 功能自动生成的 Hash 值。

可以在 Child.vue 配置 inheritAttrs 为 false 来屏蔽这些非 props 属性的渲染。

// Child.vue
export default defineComponent({
  inheritAttrs: false,
  setup() {
    // ...
  },
})

关闭了 之后,现在的 DOM 结构如下,只保留了两个由 Style Scoped 生成的 Hash 值:

<!-- Child.vue 在浏览器里渲染后的 HTML DOM 解构 -->
<div class="child" data-v-2dcc19c8="" data-v-7eb2bc79="">子组件</div>

这一类非 props 属性通常称之为 attrs 。

刚接触 Vue 的开发者可能容易混淆这两者,确实是非常接近,都是由父组件传递,由子组件接收,支持传递的数据类型也一样,但为什么一部分是在 props 获取,一部分在 attrs 获取呢?笔者给出一个比较容易记忆的方式,不一定特别准确,但相信可以帮助开发者加深两者的区别理解。

根据它们的缩写,其实是可以知道 Prop 是指 Property ,而 Attr 是指 Attribute ,虽然都是 “属性” ,但 Property 更接近于事物本身的属性,因此需要在组件里声明,而 Attribute 更偏向于赋予的属性,因此用于指代父组件传递的其他未被声明为 Property 的属性。

获取非 props 的属性
注:这一小节的步骤是在 Child.vue 里操作。

在上一小节 传递非 props 的属性 已经在父组件 Father.vue 里向子组件 Child.vue 传递了一些 attrs 自定义属性,在子组件里想要拿到这些属性,使用原生 JavaScript 操作是需要通过 Element.getAttribute() 方法,但 Vue 提供了更简单的操作方式。

在 Child.vue 里,可以通过 setup 的第二个参数 context 里的 attrs 来获取到这些属性,并且父组件传递了什么类型的值,获取到的也是一样的类型,这一点和使用 Element.getAttribute() 完全不同。

// Child.vue
export default defineComponent({
  setup(props, { attrs }) {
    // `attrs` 是个对象,每个 Attribute 都是它的 `key`
    console.log(attrs.id) // child-component
    console.log(attrs.class) // class-name-from-father

    // 传递数组会被保留类型,不会被转换为 `key1,key2` 这样的字符串
    // 这一点与 `Element.getAttribute()` 完全不同
    console.log(attrs.keys) // ['foo', 'bar']

    // 传递对象也可以正常获取
    console.log(attrs.obj) // {foo: 'bar'}

    // 如果传下来的 Attribute 带有短横线,需要通过这种方式获取
    console.log(attrs['data-hash']) // b10a8db164e0754105b7a99be72e3fe5
  },
})

TIP

子组件不论是否设置 inheritAttrs 属性,都可以通过 attrs 拿到父组件传递下来的数据,但是如果要使用 Element.getAttribute() 则只有当 inheritAttrs 为 true 的时候才可以,因为此时在 DOM 上才会渲染这些属性。

与 Vue 2 的 template /> 只能有一个根节点不同, Vue 3 允许多个根节点,多个根节点的情况下,无法直接继承这些 attrs 属性(在 inheritAttrs: true 的情况也下无法默认继承),需要在子组件 Child.vue 里通过 v-bind 绑定到要继承在节点上。

可以通过 Vue 实例属性 $attrs 或者从 setup 函数里把 attrs return 出来使用

<!-- Child.vue -->
<template>
  <!-- 默认不会继承属性 -->
  <div class="child">不会继承</div>

  <!-- 绑定后可继承, `$attrs` 是一个 Vue 提供的实例属性 -->
  <div class="child" v-bind="$attrs">使用 $attrs 继承</div>

  <!-- 绑定后可继承, `attrs` 是从 `setup``return` 出来的变量 -->
  <div class="child" v-bind="attrs">使用 attrs 继承</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  setup(props, { attrs }) {

    return {
      attrs,
    }
  },
})
</script>

绑定 emits
注:这一小节的步骤是在 Father.vue 里操作。

如果父组件 Father.vue 需要获取子组件 Child.vue 的数据更新情况,可以由子组件通过 emits 进行通知,下面这个更新用户年龄的例子可以学习如何给子组件绑定 emit 事件。

事件的逻辑是由父组件决定的,因此需要在父组件 Father.vue 的 script /> 里先声明数据变量和一个更新函数,并且这个更新函数通常会有一个入参作为数据的新值接收。

在本例子里,父组件声明了一个 updateAge 方法,它接受一个入参 newAge ,代表新的年龄数据,这个入参的值将由子组件 Child.vue 在触发 emits 时传入。

因为还需要在 template /> 部分绑定给子组件,所以请记得 return 出来。

// Father.vue
import { defineComponent, reactive } from 'vue'
import Child from '@cp/Child.vue'

interface Member {
  id: number
  name: string
  age: number
}

export default defineComponent({
  components: {
    Child,
  },
  setup() {
    const userInfo: Member = reactive({
      id: 1,
      name: 'Petter',
      age: 0,
    })

    /**
     * 声明一个更新年龄的方法
     * @param newAge - 新的年龄,由子组件触发 emits 时传递
     */
    function updateAge(newAge: number) {
      userInfo.age = newAge
    }

    return {
      userInfo,
      updateAge,
    }
  },
})

再看 Father.vue 的 template /> 部分,和 Click 事件使用 @click 一样,自定义的 emits 事件也是通过 v-on 或者是 @ 来绑定:

<!-- Father.vue -->
<template>
  <Child @update-age="updateAge" />
</template>

和 props 一样,官方文档也推荐将 camelCase 风格(小驼峰)命名的函数,在绑定时使用 kebab-case 风格(短横线),例如使用 update-age 代替 updateAge 传递。

接收并调用 emits
注:这一小节的步骤是在 Child.vue 里操作。

和 props 一样,可以指定是一个数组,把要接收的 emit 事件名称写进去:

// Child.vue
export default defineComponent({
  emits: ['update-age'],
})

和 props 不同,通常情况下 emits 这样配置就足够使用了。

接下来如果子组件需要更新数据并通知父组件,可以使用 setup 第二个参数 context 里的 emit 方法触发:

// Child.vue
export default defineComponent({
  emits: ['update-age'],
  setup(props, { emit }) {
    // 通知父组件将年龄设置为 `2`
    emit('update-age', 2)
  },
})

emit 方法最少要传递一个参数:事件名称。

事件名称是指父组件 Father.vue 绑定事件时 @update-age=“updateAge” 里的 update-age ,如果改成 @hello=“updateAge” ,那么事件名称就需要使用 hello ,一般情况下事件名称和更新函数的名称会保持一致,方便维护。

对于需要更新数据的情况, emit 还支持传递更多的参数,对应更新函数里的入参,所以可以看到上面例子里的 emit(‘update-age’, 2) 有第二个参数,传递了一个 2 的数值,就是作为父组件 updateAge 的入参 newAge 传递。

如果需要通信的数据很多,建议第二个入参使用一个对象来管理数据,例如父组件调整为:

// Father.vue
function updateInfo({ name, age }: Member) {
  // 当 `name` 变化时更新 `name` 的值
  if (name && name !== userInfo.name) {
    userInfo.name = name
  }

  // 当 `age` 变化并且新值在正确的范围内时,更新 `age` 的值
  if (age > 0 && age !== userInfo.age) {
    userInfo.age = age
  }
}

子组件在传递新数据时,就应该使用对象的形式传递:

// Child.vue
emit('update-info', {
  name: 'Tom',
  age: 18,
})

这对于更新表单等数据量较多的场景非常好用。

接收 emits 时做一些校验

注:这一小节的步骤是在 Child.vue 里操作。

和 props 一样,子组件在接收 emits 时也可以对这些事件做一些验证,这个时候就需要将 emits 配置为对象,然后把事件名称作为 key , value 则对应为一个用来校验的方法。

还是用回上文那个更新年龄的方法,如果需要增加一个条件:当达到成年人的年龄时才会更新父组件的数据,那么就可以将 emits 调整为:

// Child.vue
export default defineComponent({
  emits: {
    // 需要校验
    'update-age': (age: number) => {
      // 写一些条件拦截,返回 `false` 表示验证不通过
      if (age < 18) {
        console.log('未成年人不允许参与')
        return false
      }

      // 通过则返回 `true`
      return true
    },

    // 一些无需校验的,设置为 `null` 即可
    'update-name': null,
  },
})

接下来如果提交 emit(‘update-age’, 2) ,因为不满足验证条件,浏览器控制台将会出现一段 [Vue warn]: Invalid event arguments: event validation failed for event “update-age”. 这样的警告信息。

v-model / emits
相对于 props / emits 这一对通信方案,使用 v-model 的方式更为简单:

1.在 Father.vue ,通过 v-model 向 Child.vue 传值

2.Child.vue 通过自身设定的 emits 向 Father.vue 通知数据更新

v-model 的用法和 props 非常相似,但是很多操作上更为简化,但操作简单带来的 “副作用” ,就是功能上也没有 props 那么多。

绑定 v-model
注:这一小节的步骤是在 Father.vue 里操作

和下发 props 的方式类似,都是在子组件上绑定 Father.vue 定义好的数据,这是绑定一个数据的例子:

<!-- Father.vue -->
<template>
  <Child v-model:username="userInfo.name" />
</template>

和 Vue 2 不同, Vue 3 可以直接绑定 v-model ,而无需在子组件指定 model 选项 ,并且 Vue 3 的 v-model 需要使用英文冒号 : 指定要绑定的属性名,同时也支持绑定多个 v-model 。

如果要绑定多个数据,写多个 v-model 即可:

<!-- Father.vue -->
<template>
  <Child
    v-model:uid="userInfo.id"
    v-model:username="userInfo.name"
    v-model:age="userInfo.age"
  />
</template>

看到这里应该能明白了,一个 v-model 其实就是一个 prop ,它支持的数据类型和 prop 是一样的,所以子组件在接收数据的时候,完全按照 props 去定义就可以了。

点击回顾:接收 props ,了解在 Child.vue 如何接收 props,以及相关的 props 类型限制等部分内容。

配置 emits
注:这一小节的步骤是在 Child.vue 里操作。

虽然 v-model 的配置和 props 相似,但是为什么出这么两个相似的东西?自然是为了简化一些开发上的操作。

使用 props / emits ,如果要更新父组件的数据,还需要在父组件声明一个更新函数并绑定事件给子组件,才能够更新。

而使用 v-model / emits ,无需在父组件声明更新函数,只需要在子组件 Child.vue 里通过 update: 前缀加上 v-model 的属性名这样的格式,即可直接定义一个更新事件。

// Child.vue
export default defineComponent({
  props: {
    uid: Number,
    username: String,
    age: Number,
  },
  // 注意这里的 `update:` 前缀
  emits: ['update:uid', 'update:username', 'update:age'],
})

这里的 update 后面的属性名,支持驼峰写法,这一部分和 Vue 2 的使用是相同的。

在配置 emits 时,也可以对数据更新做一些校验,配置方式和讲解 props / emits 时 接收 emits 时做一些校验 这一小节的操作是一样的。

在 Child.vue 配置好 emits 之后,就可以在 setup 里直接操作数据的更新了:

// Child.vue
export default defineComponent({
  setup(props, { emit }) {
    // 2s 后更新用户名
    setTimeout(() => {
      emit('update:username', 'Tom')
    }, 2000)
  },
})

子组件通过调用 emit(‘update:xxx’) 即可让父组件更新对应的数据。

ref / emits
在学习 响应式 API 之 ref 的时候,已讲解过 ref 是可以用在 DOM 元素与子组件 上面,所以也可以使用 ref 配合 emits 完成父子组件的通信。

父组件操作子组件
注:这一小节的步骤是在 Father.vue 里操作。

父组件可以给子组件绑定 ref 属性,然后通过 Ref 变量操作子组件的数据或者调用子组件里面的方法。

先在 template /> 处给子组件标签绑定 ref 属性:

<!-- Father.vue -->
<template>
  <Child ref="child" />
</template>

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

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

相关文章

【GPLT 二阶题目集】L2-043 龙龙送外卖

参考地址&#xff1a;AcWing 4474. 龙龙送外卖&#xff08;杂题选讲&#xff09; 作者&#xff1a;yxc 感谢y总&#xff01; 龙龙是“饱了呀”外卖软件的注册骑手&#xff0c;负责送帕特小区的外卖。帕特小区的构造非常特别&#xff0c;都是双向道路且没有构成环 —— 你可以…

Spring Cloud Alibaba Sentinel 控制台

简介 Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的入口&#xff0c;它为用户提供了机器自发现、簇点链路自发现、监控、规则配置等功能。在 Sentinel 控制台上&#xff0c;我们可以配置规则并实时查看流量控制效果。 下载 有以下两种方式获取Sentinel控制台 下…

进阶技术:Linux Arm32是如何调用C Main的

前言&#xff1a; Linux x64通过qemu的rdinit方式调用的C Main&#xff0c;实际上是通过load_elf_binary(加载和解析elf)和start_thread(设置Ip和sp)&#xff0c;用缺页异常来调用。关于这点可以看这篇文章&#xff1a;点击查看。那么Arm32里面是如何调用C Main的呢&#xff1f…

Android 进阶——Framework 核心之Binder 相关预备理论(一)

文章大纲引言一、进程的内存空间和进程隔离二、Linux 系统内存的用户空间和内核空间1、用户空间&#xff08;User Space&#xff09;2、内核空间&#xff08;Kernel Space&#xff09;三、Linux IPC 原理1、内核态和用户态2、IPC 步骤四、内核模块和驱动五、Binder1、Binder IP…

优思学院|從《狂飙》高启强爱看的《孙子兵法》到六西格玛项目管理

近期最受人瞩目的&#xff0c;无疑是电视剧《狂飙》中出类拔萃的反派高启强。而在剧中&#xff0c;指引高启强走向顶峰的&#xff0c;正是那部著名的军事经典——《孙子兵法》。 在剧中&#xff0c;高启强在一次村庄改造项目上遇到了困难&#xff0c;但他仍保持冷静&#xff0…

QT开发安卓程序初识

Qt | Qt For Android、Qt5.14.2安卓开发环境搭建详细步骤 测试结果如下&#xff1a;

AcWing 840. 模拟散列表

题目描述 餐前小菜&#xff1a; 在讨论本题目之前先看一个简单的问题&#xff1a;给出 NNN 个正整数 (a1,a2,...,an)(a_1,a_2,...,a_n)(a1​,a2​,...,an​)&#xff0c;再给出 MMM 个正整数 (x1,x2,...,xm)(x_1,x_2,...,x_m)(x1​,x2​,...,xm​)&#xff0c;问这 MMM 个数中…

冷知识|鹤顶红还能用来修长城?

大家好&#xff0c;我是建模助手。 在上篇浅浅地蹭了波热点之后&#xff0c;我灵机一动&#xff0c;倒不如也搞一搞建筑方面的冷知识&#xff1f;冷热搭配&#xff0c;事半功倍... 问问大家&#xff0c;如果谈起古建筑&#xff0c;关键词都有什么&#xff1f;是庄严、震撼、壮…

DHCP实验及配置

DHCP实验配置基于接口拓扑图配置基于全局拓扑图配置基于接口 拓扑图 配置 [Huawei]dhcp enable//在全局下使能DHCP服务 [Huawei]interface GigabitEthernet0/0/0//进入接口 [Huawei-GigabitEthernet0/0/0] ip address 192.168.1.1 255.255.255.0 //配置接口地址 [Huawei-Giga…

什么是QoS?QoS是如何工作的?QoS的实验配置如何进行?

QoS&#xff08;Quality of Service&#xff09;是服务质量的简称。对于网络业务来说&#xff0c;服务质量包括哪些方面呢&#xff1f; 从传统意义上来讲&#xff0c;无非就是传输的带宽、传送的时延、数据的丢包率等&#xff0c;而提高服务质量无非也就是保证传输的带宽&…

人工智能:分享五个目前最火的ChatGPT开源项目

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️荣誉&#xff1a; CSDN博客专家、数据库优质创作者&#x1f3c6;&…

Nacos简介(一)

目录 一、概览 二、注册中心基本概念 1) 什么是注册中心&#xff1f; 2) 如果没有注册中心&#xff1f;会怎样 3) 注册中心主要有三种角色&#xff1a; 4) 服务注册中心的作用 5&#xff09;CAP 理论 6&#xff09;CP和AP的选择 三、什么是 Nacos&#xff1f; 四、Nac…

C++——继承那些事儿你真的知道吗?

目录1.继承的概念及定义1.1继承的概念1.2 继承定义1.2.1定义格式1.2.2继承关系和访问限定符1.2.3继承基类成员访问方式的变化2.父类和子类对象赋值转换3.继承中的作用域4.派生类的默认成员函数5.继承与友元6. 继承与静态成员7.复杂的菱形继承及菱形虚拟继承如何解决数据冗余和二…

Spring 5(黑马)

文章目录传统JavaWeb开发的困惑IoC、DI和Aop思想提出Spring框架的诞生Spring 框架概述Spring 框架历史Spring Framework技术栈图示BeanFactory 快速入门DI 入门案例ApplicationContext快速入门BeanFactory 和 ApplicationContext的关系BeanFactory 的继承体系ApplicationContex…

全志H616——安装SQlite库并使用常用的数据库操作指令

在官网下载安装包&#xff1a;SQLite下载页面、https://www.sqlite.org/2022/sqlite-autoconf-3400100.tar.gz&#xff08;安装包&#xff09;下载到MobaXterm_Personal中解压&#xff1a;tar xvf sqlite-autoconf-3400100.tar.gz设置下载路径&#xff1a;./configure --help:.…

滴滴一面:order by 调优10倍,思路是啥?

背景说明&#xff1a; Mysql调优&#xff0c;是大家日常常见的调优工作。 所以&#xff0c;Mysql调优是一个非常、非常核心的面试知识点。 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;其相关面试题是一个非常、非常高频的交流话题。 近段时间&#xff0c;有小伙伴面…

计算机视觉 吴恩达 week 10 卷积

文章目录一、边缘检测二、填充 padding1、valid convolution2、same convolution三、卷积步长 strided convolution四、三维卷积五、池化层 pooling六、 为什么要使用卷积神经网络一、边缘检测 可以通过卷积操作来进行 原图像 n✖n 卷积核 f✖f 则输出的图像为 n-f1 二、填充…

【软考】系统集成项目管理工程师(二十)项目风险管理

一、项目风险管理概述1. 风险概念2. 风险分类3. 风险成本二、项目风险管理子过程1. 规划风险管理2. 识别风险3. 实施定性风险分析4. 实施定量风险分析5. 规划风险应对6. 控制风险三、项目风险管理流程梳理一、项目风险管理概述 1. 风险概念 风险是一种不确定事件或条件,一旦…

java赫夫曼编码

1.基本介绍 赫夫曼编码也翻译为 哈夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式, 属于一种程序算法赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。赫夫曼编码广泛地用于数据文件压缩。其压缩率通常在 20%&#xff5e;90%之间赫夫曼…

[Android]网络框架之Retrofit(kotlin)

目录 Retrofit简介 Retrofit基本使用 Retrofit的注解 Retrofit的转换器 文件的上传与下载 Retrofit简介 Retrofit是一款由Square公司开发的网络库&#xff0c;但是它和OkHttp的定位完全不同。 OkHttp侧重的是底层通信的实现&#xff0c;而Retrofit侧重的是上层接口的封装…