Vue3学习记录(二)--- 组合式API之计算属性和侦听器

news2024/10/7 9:17:14

一、计算属性

1、简介

​ 计算属性computed(),用于根据依赖的响应式变量的变化,进行自动的计算,并返回计算后的结果。当依赖的响应式变量发生变化时,computed()会自动进行重新计算,并返回最新的计算结果。如果依赖的响应式变量没有发生变化,则computed()会将计算的结果进行缓存,后续再调用时,将会返回缓存的计算结果,而不会重新计算。

2、使用
基础用法:

computed() 方法期望接收一个 getter 函数,返回值为一个只读的响应式 ref 对象,然后使用let/const/var声明一个变量,作为计算属性的名称,接收的返回的 ref。与使用 ref() 声明的响应式变量类似,在JS中需要通过 计算属性名.value 访问计算结果,在组件的<template>模板中使用,可以直接使用计算属性名,因为此时会自动解包,获取其value属性。

<script setup>
// 引入要使用的相关API
import { ref, computed, onMounted } from 'vue';

// 声明一个响应式变量
const list = ref([1,2,3]);

// 使用computed计算属性 
const hasData = computed(() => {
  // 内部依赖响应式变量 list
  return list.value.length > 0;
});

// 在mounted生命周期中修改响应式变量的值 观察computed的变化
onMounted(() => {
  // 初始化时输出computed的值
  console.log('computed',hasData.value); // true
  // 2秒后清空list数组 观察computed的变化
  setTimeout(() => {
    list.value = [];
    console.log('computed',hasData.value); // false
  }, 2000);
})
</script>

<template>
  <div>
    <h1>computed计算属性</h1>
    <!-- 在模板中使用计算属性 无需使用value -->
    <h2>computed: {{hasData}}</h2>
    <!-- 观察其变化 初始为true 两秒后变为false  -->
  </div>
</template>
可写的计算属性:

​ 默认情况下,声明的计算属性是只读的,不可修改。但我们可以通过同时给计算属性设置gettersetter方法来创建一个可读写的计算属性。虽然说是可写的计算属性,但实际上原理是在setter方法中通过修改计算属性依赖的响应式变量的值,从而达到修改计算属性值的效果:

<script setup>
// 引入要使用的相关API
import { ref, computed, onMounted } from 'vue';

// 声明一个响应式变量
const list = ref([1,2,3]);

// 设置一个可读写的计算属性
const listString = computed({
  // getter方法 用于获取计算属性的值
  get() {
    // 依赖于响应式变量list
    return list.value.join(',');
  },
  // setter方法 用于设置计算属性的值
  set(val) {
    // 实际是通过修改依赖的响应式变量list的值 从而实现修改计算属性的值
    list.value = val.split(',');
  }
});

// 在mounted生命周期中操作计算属性
onMounted(() => {
  // 初始输出computed的值
  console.log('computed',listString.value);
  // 2秒后修改listString的值 观察computed和依赖的响应式变量的变化
  setTimeout(() => {
    listString.value = '4,5,6';
    console.log('computed',listString.value);
    console.log('list',list.value);
  }, 2000);
})
</script>

<template>
  <div>
    <h1>computed计算属性</h1>
    <!-- 在模板中使用计算属性 观察其变化 -->
    <h2>computed: {{listString}}</h2>
    <!-- 在模板中使用响应式变量 观察其变化 -->
    <h2>ref变量: {{list}}</h2>
  </div>
</template>

页面效果:

在这里插入图片描述

计算属性调试:

​ 在开发环境中,可以向computed()传入第二个参数,参数值为一个包含了onTrackonTrigger两个函数的对象。其中onTrack 将在计算属性初次被调用时触发。onTrigger 将在计算属性的值发生变化,也就是所依赖的响应式变量的值发生变更时触发。

<script setup>
// 引入要使用的相关API
import { ref, computed, onMounted } from 'vue';

// 声明一个响应式变量
const count = ref(0);

// 声明一个计算属性 并开启调试模式
const double = computed(() => count.value * 2, {
  onTrack(e) {
    // 计算属性初次被访问时 在访问之前触发
    console.log('computed onTrack---',e);
  },
  onTrigger(e) {
    // 计算属性的结果发生变化时触发 在修改计算属性依赖的响应式变量的值之后触发
    console.log('computed onTrigger---',e);
  }
});

// 点击事件
const clickFunc = () => {
  count.value++;
  console.log('computed', double.value);
}

// 在mounted生命周期中操作计算属性
onMounted(() => {
  // 初次访问计算属性的值 触发onTrack
  console.log('computed', double.value);
  // 修改计算属性依赖的响应式变量的值 触发onTrigger
  count.value = 2;
})
</script>

<template>
  <div>
    <h1>computed计算属性</h1>
    <!-- 在模板中使用计算属性 观察其变化 -->
    <h2 @click="clickFunc">computed: {{double}}</h2>
  </div>
</template>

页面效果:

在这里插入图片描述

点击h2元素之后:

在这里插入图片描述

注意:计算属性的 onTrackonTrigger 选项仅会在开发模式下工作。

3、其他
getter方法不应该有副作用:

​ 计算属性的getter方法只能用于根据依赖的响应式变量计算并返回计算的结果。一定不能在getter方法中进行修改其他变量的值、操作DOM以及发起异步请求等会产生副作用的操作,这违背了计算属性的设计初衷。

​ 在计算属性getter方法中使用 reverse()sort() 等会影响原有数据的方法时务必小心。由于这些方法将改变原始数组的值,因此在调用这些方法之前要深拷贝一个原始数据的副本,然后对副本进行操作,并返回操作后的结果。

计算属性依赖的变量必须为响应式变量:

​ 计算属性依赖的变量必须是响应式的变量,可以是refreactive声明的响应式变量,也可以是shallowRefshallowReactive声明的浅层响应式变量。但如果是浅层响应式变量,则只有修改可以被监听到的属性时,才会触发计算属性的重新计算,计算属性的值层会更新。

​ 通过let/const/var声明的普通JS变量不能作为计算属性依赖的变量。

二、侦听器(监听器)

1、简介

​ 侦听器watch()用于实现监听一个响应式变量的变化,侦听器接收三个参数,其第一个参数表示所侦听的响应式变量,第二个参数表示响应式变量变化之后触发的回调函数,第三个参数是一个可选的选项,用来进行一些侦听器配置。在响应式变量发生变化时,触发回调函数,然后在回调函数中根据变量的状态变化,执行对应的操作,与计算属性不同的是,侦听器可以在回调函数中产生副作用,如:修改其他变量的值、操作DOM、发起异步请求等等。

​ 在侦听器的回调函数中可以接收三个参数:新值、旧值,以及一个可选参数:用于注册清理副作用的清理函数。第三个参数清理函数会在下一次侦听器的回调函数被触发之前执行,用来清除上一次回调函数未执行结束的副作用,如未执行结束的异步请求等。

watch()函数的返回值是一个用来停止该侦听器的函数。

2、使用
基础用法:
// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 声明一个响应式变量
const count = ref(0);

// watch监听响应式变量的变化
watch(count, (newVal, oldVal) => {
  // 响应式变量初始化时,不会触发watch的回调函数
  // 只有当响应式变量的值发生变化时,会触发watch的回调函数 newval是变化后的值 oldval是变化前的值
  console.log('watch--', newVal, oldVal); // 10 0
  // 根据变量值的具体变化 进行后续操作
});

// 在mounted生命周期中修改响应式变量的值 观察watch的变化
onMounted(() => {
  // 2秒后修改响应式变量的值 观察watch的变化
  setTimeout(() => {
    count.value = 10;
  }, 2000);
});
可侦听的数据类型:

watch()的第一个参数所监听的数据源可以是多种形式:一个响应式变量(ref、reactive等)、一个getter函数、由多个数据源组成的数组。

​ 如果监听的数据源是一个响应式变量,当变量变动时,回调函数就会被触发,且参数中包含监听变量的新值和旧值。

​ 如果监听的数据源是一个getter函数,这个getter函数类似于计算属性,依赖于某些响应式变量进行计算,并返回计算的结果,当getter函数所依赖的变量发生变动时,回调函数就会被触发,且回调函数的参数中包含getter函数的新返回值和就返回值。

​ 如果监听的数据源是一个由多个数据源构成的数组,数组中可以同时包含响应式变量、getter函数,当数组中任意一个数据源发生变动时,都会触发回调函数,且回调函数的参数中以以两个数组的形式返回所有监听数据源的新值和旧值,新值数组和旧值数组中元素的顺序与监听数组中元素的顺序一一对应。

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 声明两个响应式变量
const count = ref(0);
const str = ref('hello');

// watch监听一个响应式变量的变化 第一个参数为监听的数据源 第二个参数为回调函数
watch(count, (newVal, oldVal) => {
  // 响应式变量初始化时,不会触发watch的回调函数
  // 只有当响应式变量的值发生变化时,会触发watch的回调函数 newval是变化后的值 oldval是变化前的值
  console.log('watch监听一个响应式变量--', newVal, oldVal);
});

// watch监听一个getter函数  第一个参数为监听的数据源 第二个参数为回调函数
watch(() => count.value + str.value, (newVal, oldVal) => {
  // 响应式变量初始化时,不会触发watch的回调函数
  // 只有当getter函数中依赖的任意一个响应式变量的值发生变化时,都会触发watch的回调函数
  console.log('watch监听一个getter函数--', newVal, oldVal);
});

// watch同时监听多个数据源的变化 用数组的形式  第一个参数为监听的数据源 第二个参数为回调函数
watch([count, str,() => count.value + str.value], ([newVal1, newVal2,newVal3], [oldVal1, oldVal2, oldVal3]) => {
  // 响应式变量初始化时,不会触发watch的回调函数
  // 当任意一个数据源的值发生变化时,会触发watch的回调函数 newval是变化后的值 oldval是变化前的值
  console.log('watch监听多个数据源--', newVal1, newVal2, newVal3, oldVal1, oldVal2, oldVal3);
});

// 在mounted生命周期中修改响应式变量的值 观察watch的变化
onMounted(() => {
  // 2秒后修改响应式变量的值 观察watch的变化
  setTimeout(() => {
    count.value = 10;
  }, 2000);
});

控制台输出:

在这里插入图片描述

​ 如果想要监听响应式对象的某一个简单属性(非嵌套对象、数组属性等),而非整个响应式对象,不能直接以对象.属性名的形式作为监听的数据源,因为这样watch() 得到的数据源参数只是一个 number,而非响应式的数据源。因此我们需要借助getter函数,以函数返回值的形式返回该属性,最后将getter函数设置为监听的数据源。

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 声明一个响应式对象
const obj = ref({ count: 0,name: '张三' });

// watch监听一个响应式对象的某条属性的变化
watch(() => obj.value.count, (newVal, oldVal) => {
  // 响应式变量初始化时,不会触发watch的回调函数
  // 只有当响应式变量的指定属性值发生变化时,才会触发watch的回调函数
  console.log('watch监听一个响应式对象的某条属性的变化--', newVal, oldVal);
});

// 在mounted生命周期中修改响应式对象的属性值 观察watch的变化
onMounted(() => {
  // 1秒后修改响应式变量的其他属性的值 观察watch的变化
  setTimeout(() => {
    // 非监听的指定属性 不会触发watch的回调函数
    obj.value.name = '李四';
  }, 1000);
  // 2秒后修改响应式变量的指定属性的值 观察watch的变化
  setTimeout(() => {
    // 监听的指定属性 会触发watch的回调函数
    obj.value.count = 2;
  }, 2000);
});
深度侦听器

​ 如果我们使用watch()监听的数据源为一个响应式对象,则侦听器内部会隐式的创建一个深层侦听器。响应式对象中任意属性的发生变动,都会触发回调函数,即使是响应式对象内部嵌套对象的属性值,也会被监听到。watch()回调函数的参数表示的是响应式对象的新值和旧值,但由于我们监听的是一个响应式对象,因此新值和旧值在此时是相等的,指向所监听的那个响应式对象。

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 用ref声明一个响应式对象
const obj = ref({ count: 0,name: '张三',info: { age: 18 } });

// watch监听一个响应式对象的变化
watch(obj.value, (newVal, oldVal) => {
  // 响应式对象初始化时,不会触发watch的回调函数
  // 响应式对象的任意属性值发生变化时,都会触发watch的回调函数
  console.log('watch监听一个响应式对象的变化--', newVal, oldVal);
  // newVal和oldVal是同一个对象
  console.log(newVal === oldVal);
  // newVal、oldVal和响应式对象的值是同一个对象
  console.log(newVal === obj.value);
});

// 在mounted生命周期中修改响应式对象的属性值 观察watch的变化
onMounted(() => {
  // 1秒后修改响应式对象的根属性的值 观察watch的变化
  setTimeout(() => {
    obj.value.name = '王五';
  }, 1000);
  // 2秒后修改响应式对象的嵌套对象的属性值 观察watch的变化
  setTimeout(() => {
    obj.value.info.age = 20;
  }, 2000);

控制台输出:

在这里插入图片描述

​ 如果我们仅仅只是想要监听的数据源为响应式对象中某个嵌套对象属性,那我们需要借助getter函数,以函数返回值的形式返回该属性。但仅仅这样,只会在嵌套对象属性整个被替换时,才会触发回调函数。想要深度监听嵌套对象属性的变动,我们还需要给watch()函数增加第三个参数,参数为一个配置对象,对象中包含deep: true属性,表示将监听的数据源进行深层监听。在回调函数中可以获取到被监听的嵌套对象的新值和旧值,除非监听的嵌套对象整个被替换,否则新值和旧值在此时是相等的,指向所监听的那个嵌套对象。

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 用ref声明一个响应式对象
const obj = ref({ count: 0,name: '张三',info: { age: 18 } });

// watch监听一个响应式对象内部某个嵌套对象的属性变化
watch(() => obj.value.info, (newVal, oldVal) => {
  // 响应式对象初始化时,不会触发watch的回调函数
  // 响应式对象的任意属性值发生变化时,都会触发watch的回调函数
  console.log('watch监听一个响应式对象内部某个嵌套对象的属性变化--', newVal, oldVal);
  // 除非监听的嵌套对象整个被替换 否则newVal和oldVal是同一个对象
  console.log(newVal === oldVal); 
  // newVal、oldVal和响应式对象的值是同一个对象
  console.log(newVal === obj.value.info);
},{
  // deep选项为true时,表示深度监听,包括嵌套对象的属性变化
  deep: true
});

// 在mounted生命周期中修改响应式变量的值 观察watch的变化
onMounted(() => {
  // 2秒后修改响应式对象中嵌套对象的属性值 观察watch的变化
  setTimeout(() => {
    obj.value.info.age = 22;
  }, 2000);
});

注意: 深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,性能开销很大。因此请谨慎使用。

监听数据源初始化

watch()侦听器默认在数据源初始化时不触发回调函数,只有在数据源变化时才会触发回调函数。如果我们想要在数据源初始化后,立即触发一次回调函数,可以通过给watch()函数的三个参数,设置immediate: true属性,表示将数据源的初始化动作加入到监听范围内,此时回调函数的参数中新值为数据源初始化后的值,旧值为undefined

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 声明两个响应式变量
const count = ref(0);

// watch监听一个响应式变量的变化 包括初始化时
watch(count, (newVal, oldVal) => {
  // 响应式变量的值发生变化时,会触发watch的回调函数
  console.log('watch监听一个响应式变量--', newVal, oldVal); // 0 undefined
},{
  // immediate选项为true时,表示初始化时也触发watch的回调函数
  immediate: true
});
一次性侦听器:

watch()侦听器默认每次数据源的变化时都会触发回调函数。如果我们想让侦听器只运行一次,可以通过给watch()函数的三个参数,设置once: true属性(v3.4版本新增),表示侦听器将在回调函数首次执行后自动停止,不再监听数据源的后续变动。

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 声明两个响应式变量
const count = ref(0);

// watch监听一个响应式变量的变化 但回调函数只执行一次
watch(count, (newVal, oldVal) => {
  // 响应式变量的值发生变化时,会触发watch的回调函数
  console.log('watch监听一个响应式变量--', newVal, oldVal);
},{
  // once选项为true时,表示只执行一次回调函数
  once: true
});

// 在mounted生命周期中修改响应式变量的值 观察watch的变化
onMounted(() => {
  // 1秒后修改响应式变量的值 触发watch的回调函数
  setTimeout(() => {
    count.value = 5;
  }, 1000);
  // 2秒后再次修改响应式变量的值 不触发watch的回调函数
  setTimeout(() => {
    count.value = 10;
  }, 2000);
});
回调函数的执行时机:

​ 如果我们使用watch()监听了一个响应式变量,并且在单文件组件的模板中使用了它,那么该变量在修改时,可能会同时触发Vue 组件更新和侦听器回调函数。默认情况下,侦听器的回调函数会在组件更新之前执行,如果此时在回调函数中访问页面的DOM,访问的是组件更新前的DOM。如果想要访问组件更新后的DOM,可以通过给watch()函数的三个参数,设置flush: 'post'属性,表示回调函数在组件更新之后执行,此时访问页面的DOM,将是最新状态的DOM。

// 引入要使用的相关API
import { ref, watch, onMounted } from 'vue';

// 声明两个响应式变量
const count = ref(0);

// watch监听一个响应式变量的变化 回调函数在组件更新前执行
watch(count, (newVal, oldVal) => { 
  // 在此处获取页面的DOM元素 获取的是组件更新前的DOM元素
  console.log('组件更新前---',document.querySelector('h3').innerText); // 0
});

// watch监听一个响应式变量的变化 但回调函数在组件更新后执行
watch(count, (newVal, oldVal) => { 
  // 在此处获取页面的DOM元素 获取的是组件更新后的DOM元素
  console.log('组件更新后--',document.querySelector('h3').innerText); // 10
},{
  // flush选项为post时,表示在组件更新后执行回调函数
  flush: 'post'
});

// 在mounted生命周期中修改响应式变量的值 观察watch的变化
onMounted(() => {
  // 2秒后再次修改响应式变量的值
  setTimeout(() => {
    count.value = 10;
  }, 2000);
});

flush属性的可选值有三个:

  • pre(默认值):回调函数会在数据源变化之后,组件更新渲染之前立即执行。
  • post:回调函数会在数据源变化之后,组件更新渲染之后执行。
  • sync:回调函数会在数据变化时立即被同步调用。该设置要谨慎使用,因为如果有多个属性同时更新,这将导致一些性能和数据一致性的问题。
副作用清除:

​ 清理函数会在下一次侦听器的回调函数被触发之前执行,用来清除上一次回调函数未执行结束的副作用,如未执行结束的异步请求等。

watchEffect(async (newVal, oldVal, onCleanup) => {
  console.log()
  const { response, cancel } = doAsyncWork(id.value)
  // `cancel`取消逻辑 会在 `id` 更改时调用
  // 以便取消之前
  // 未完成的请求
  onCleanup(cancel)
  data.value = await response
})
侦听器调试:

​ 和计算属性类似,侦听器的第三个参数也支持 onTrackonTrigger 的调试选项。

// watch侦听器调试
watch(count, (newVal, oldVal) => { 
  console.log('watch监听一个响应式变量--', newVal, oldVal);
}, {
  onTrack(e) {
    console.log('onTrack---', e);
  },
  onTrigger(e) {
    console.log('onTrigger---', e);
  }
});

注意:侦听器的 onTrackonTrigger 选项仅会在开发模式下工作。

停止侦听器:

​ 正常情况下用同步语句创建的侦听器,会自动绑定到当前组件实例上,并且会在当前组件卸载时自动停止。但如果用异步回调创建一个侦听器,那么它不会绑定到当前组件上,你必须手动停止它,以防内存泄漏。所以尽量不要在异步回调中创建侦听器。

​ 正常创建的侦听器,也可以被手动停止,但基本不需要这么做。

watch()函数会返回一个对应的停止函数,如果想要手动停止一个侦听器,直接调用该侦听器返回的停止函数即可。

// watch监听一个响应式变量的变化 并接收侦听器结束函数
const unWatch = watch(count, (newVal, oldVal) => { 
  console.log('watch监听一个响应式变量--', newVal, oldVal);
});

// 在mounted生命周期中修改响应式变量的值 观察watch的变化
onMounted(() => {
  // 1秒后修改响应式变量的值 watch会监听到
  setTimeout(() => {
    count.value = 5;
  }, 1000);
  // 2秒后 调用对应的停止函数  手动停止侦听器
  setTimeout(() => {
    unWatch();
  }, 2000);
  // 3秒后 再次修改响应式变量的值 watch已经被停止 不会监听到
  setTimeout(() => {
    count.value = 10;
  }, 3000);
});
3、其他
watchEffect():

watchEffect()watch()侦听器的一种简写形式,无需指定监听的数据源,该函数会自动跟踪回调函数中使用的响应式依赖。而且该函数无需指定immediate: true,也会在响应式依赖初始化时执行。每当响应式依赖发生变化时,都会自动执行回调函数。

watchEffect()函数的第一个参数就是要触发的回调函数,第二个参数是一个可选参数对象,用来配置侦听器的flush属性。该函数的返回值同watch()一样,是一个用来停止该侦听器的函数。

watchEffect()函数的第一个参数的回调函数中可以接收一个用于注册清理副作用的清理函数。清理函数会在下一次回调函数被触发之前执行,用来清除上一次回调函数未执行结束的副作用,如未执行结束的异步请求等。

// 引入要使用的相关API
import { ref, watch, watchEffect, onMounted } from 'vue';

// 声明一个响应式变量
const count = ref(0);

// watchEffect监听一个响应式变量
watchEffect(() => {
  console.log('watchEffect监听一个响应式变量--', count.value);
})
// 等同于
// watch监听一个响应式变量
watch(count, (newVal, oldVal) => {
  console.log('watch监听一个响应式变量--', newVal, oldVal);
},{
  immediate: true 
});

watch 只监听明确指定的数据源,仅在数据源确实改变时才会触发回调,能更加精确地控制回调函数的触发时机。watchEffect,则会在回调函数发生期间追踪依赖的数据源,自动追踪回调函数中访问到的响应式属性,但其响应性依赖关系会不那么明确。可以根据具体的业务场景选择合适的API。

watchPostEffect():

watchPostEffect()watchEffect() 使用 flush: 'post' 选项时的简写别名。

// watchPostEffect监听一个响应式变量
watchPostEffect(() => {
  console.log('watchEffect监听一个响应式变量--', count.value);
})

// 等同于

// watchEffect监听一个响应式变量
watchEffect(() => {
  console.log('watchEffect监听一个响应式变量--', count.value);
}, {
  flush: 'post'
})
watchSyncEffect():

watchSyncEffect()watchEffect() 使用 flush: 'sync' 选项时的简写别名。

// watchSyncEffect监听一个响应式变量
watchSyncEffect(() => {
  console.log('watchEffect监听一个响应式变量--', count.value);
})

// 等同于

// watchEffect监听一个响应式变量
watchEffect(() => {
  console.log('watchEffect监听一个响应式变量--', count.value);
}, {
  flush: 'sync'
})

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

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

相关文章

Open CASCADE学习|球面上曲线长度计算

球和球面是数学和物理学中非常重要的概念&#xff0c;它们在许多领域都有广泛的应用。 球面是指所有与固定点等距离的点的集合&#xff0c;这个固定点被称为球心&#xff0c;而这个等距离的长度就是球的半径。球面是一个二维曲面&#xff0c;它是三维空间中点与距离之间关系的…

大数据平台-可视化面板介绍-Echarts

应对现在数据可视化的趋势&#xff0c;越来越多企业需要在很多场景(营销数据&#xff0c;生产数据&#xff0c;用户数据)下使用&#xff0c;可视化图表来展示体现数据&#xff0c;让数据更加直观&#xff0c;数据特点更加突出。 目录 01-使用技术 02- 案例适配方案 03-基础…

在IDEA中使用git(教程)

目录 第一章、快速了解git和idea1.1&#xff09;git安装使用教程1.2&#xff09;idea安装使用教程 第二章、在IDEA中使用git2.1&#xff09;安装插件和git设置2.2&#xff09;基础操作2.2.1&#xff09;使用IDEA初始化本地仓库&#xff0c;2.2.2&#xff09;关联本地仓库和远程…

XGB-1:XGBoost安装及快速上手

XGBoost是“Extreme Gradient Boosting”的缩写&#xff0c;是一种高效的机器学习算法&#xff0c;用于分类、回归和排序问题。它由陈天奇&#xff08;Tianqi Chen&#xff09;在2014年首次提出&#xff0c;并迅速在数据科学竞赛和工业界获得广泛应用。XGBoost基于梯度提升框架…

人工智能基础-Numpy的arg运算-Fancy Indexing-比较

索引 获取最小值最大值索引 np.argmin(x) np.argmax(x)排序和使用索引 np.sort(x)Fancy Indexing 索引 二维数组的应用 numpy.array 的比较 比较结果和Fancy Indexing

爱、自由与创造——教育改革的三大基石

爱、自由与创造——教育改革的三大基石 Love, Freedom, and Creativity: The Three Pillars of Educational Reform 在当今社会快速发展的背景下&#xff0c;创造性思维的重要性日益凸显。然而&#xff0c;我们必须认识到&#xff0c;创造性并非凭空产生&#xff0c;而是深深植…

Android Studio非UI线程修改控件——定时器软件

目录 一、UI界面设计 1、UI样式 2、XML代码 二、功能编写 1、定义 2、实现方法 3、功能实现 一、UI界面设计 1、UI样式 2、XML代码 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android…

Methodot低代码实战教程(一)——熟悉可视化Echart组件

一、产品介绍&#xff1a; Methodot是行云创新旗下一款面向研发使用的一站式云原生开发及应用托管平台&#xff0c;产品内有大量开箱即用的服务和开发工具&#xff0c;例如&#xff1a; 支持开发团队进行微服务架构设计&#xff08;例如一个袜子商店管理系统&#xff09;&…

【开源】SpringBoot框架开发农村物流配送系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…

高频高动态范围信号采集的理想选择

在无线通讯、雷达/声纳、图形成像等领域&#xff0c;高频和高动态范围的信号采集是关键。PCIe8532B/8531B&#xff0c;作为一款专为这类应用而设计的4通道12/14位20MS/s采样数字化仪&#xff0c;无疑成为了工程师们的理想选择。 卓越的性能参数 这款数字化仪具备4通道单端模拟…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TimePicker组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之TimePicker组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 编辑 二、TimePicker组件 TextClock组件通过文本将当前系统时间显示在设备上。…

基于SpringBoot Vue学生成绩管理系统

大家好✌&#xff01;我是Dwzun。很高兴你能来阅读我&#xff0c;我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结&#xff0c;还为大家分享优质的实战项目&#xff0c;本人在Java项目开发领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#x…

日志记录——单片机可执行文件合并

一&#xff1a;需求场景 现在有一片单片机&#xff0c;执行程序包括自定义boot和应用程序app, 在将打包好的固件给到生产是有以下问题&#xff0c;由于要通过jlink烧录boot&#xff0c;然后上电启动boot&#xff0c;通过boot烧录初始化程序&#xff0c;过程过于复杂&#xff0…

IT业务的卓越服务

要想实现卓越服务&#xff0c;就必须对当前的服务成熟度进行全面分析。然而&#xff0c;这种评估可能会令人望而生畏&#xff0c;尤其是在现有评估框架不明确的情况下。这些方法要么考虑实践的成熟度&#xff0c;要么考虑技术的成熟度&#xff0c;为团队提供了狭隘的视野。 为…

移动机器人激光SLAM导航(三):Hector SLAM 篇

参考引用 Hector_Mapping ROS-Wiki从零开始搭二维激光SLAM机器人工匠阿杰wpr_simulation 移动机器人激光SLAM导航&#xff08;文章链接汇总&#xff09; 1. 基于滤波器的 SLAM 问题 1.1 什么是 SLAM 什么是SLAM SLAM 就是为了构建地图用的&#xff0c;这个地图可以保存下来&…

【python接口自动化】- DDT数据驱动测试

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

第一讲:入门python

第一讲&#xff1a;入门python1.安装Python1.下载2.安装3.运行4.代码 2.安装VS code 第一讲&#xff1a;入门python 本讲任务&#xff1a; 安装python安装VS code Python初学者通常首次面临的主要问题是需要在计算机上安装Python和一个适用的代码编辑器&#xff08;比如VSco…

龙芯--自主架构先驱者

&#x1f6d1; 这是ren_dong的第23篇原创 1、概述 自主可控最高的 MIPS 架构 CPU 龙芯是我国最早研制的高性能通用处理器系列&#xff0c;拥有 MIPS 指令的永久授权&#xff0c;并拓展出了自己的指令集loong ISA。龙芯采用自主 Loong ISA 指令系统&#xff0c;兼容 MIPS 指令&a…

OpenCV学习记录——形态学处理

文章目录 前言一、腐蚀和膨胀二、高级形态学运算三、具体应用代码 前言 形态学是图像处理中最常用的技术之一&#xff0c;它主要用于从图像中提取有意义的形状信息&#xff0c;例如边界和连通区域&#xff0c;以便后续的识别工作能够捕捉到目标对象最重要的形状特征。此外&…

为什么飞凌嵌入式的FET527N-C核心板更值得期待?

在高度数字化的智能时代&#xff0c;嵌入式系统在各个领域都发挥着重要作用&#xff0c;因此在项目的选型与开发中选择与需求更为匹配的核心板主控至关重要。飞凌嵌入式最新发布的FET527N-C核心板是一款值得特别关注的产品&#xff0c;具有许多令人瞩目的优势。下面小编将从四个…