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

vue3相关知识点

title: vue_1
date: 2025-01-28 12:00:00
tags:- 前端
categories:- 前端

vue3

Webpack ~ vite

vue3是基于vite创建的

vite 更快一点

一些准备工作

准备后如图所示

image-20250127163451471

插件

image-20250127163615341

image-20250127163622050

image-20250127163640162

Main.ts

// 引入createApp用于创建应用
import {createApp} from 'vue'
// 引入App根组件
import App from './App.vue'createApp(App).mount('#app')

App 是根组件,createApp是盆

npm run dev

APP.vue

<template><div class="app"><h1>你好啊!</h1></div>
</template><script lang="ts">export default {name:'App' //组件名}
</script><style>.app {background-color: #ddd;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}
</style>

简单效果实现

<template><div class="person"><h2>姓名:{% raw %}{{name}}{% endraw %}</h2><h2>年龄:{% raw %}{{age}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button></div>
</template><script lang="ts">export default {name:'Person',data(){return {name:'张三',age:18,tel:'13888888888'}},methods:{// 修改姓名changeName(){this.name = 'zhang-san'},// 修改年龄changeAge(){this.age += 1},// 展示联系方式showTel(){alert(this.tel)}}}
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
</style>

这个代码分别是cue组件的三个主要部分,分别对应的模版,脚本和样式

模版部分:也就是trmplate

模版

模版是vue组件的视图部分,定义了组件的html结构

在vue中。模版部分是通过高{% raw %}{ {}}{% endraw %}语法实现数据绑定的,{% raw %}{ {name}}{% endraw %} 会绑定到 data 中的 name 数据。

其中的@click 指令绑定点击事件,点击按钮时执行相应的方法,chageName,changeAge,changeTel

<template><div class="person"><h2>姓名:{% raw %}{{name}}{% endraw %}</h2><h2>年龄:{% raw %}{{age}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button></div>
</template>

脚本部分

脚本定义了vue组件的逻辑部分

  • data :组件的状态,即组件中使用的数据

  • Methods:定义组件的方法,这些方法可以在模版中调用来响应用户事件

  • name : 组件的名字,这里是'Person',在vue开发工具中查看到这个组件

    <script lang="ts">export default {name:'Person',data(){return {name:'张三',age:18,tel:'13888888888'}},methods:{// 修改姓名changeName(){this.name = 'zhang-san'},// 修改年龄changeAge(){this.age += 1},// 展示联系方式showTel(){alert(this.tel)}}}
    </script>

这段代码是一个 Vue 组件 的脚本部分,使用的是 TypeScript 语法。它定义了组件的 数据方法组件的名称

export default {name: 'Person',  这里就是组件的名称data() { ... },methods: { ... }
}

export default 是一个 ES6 模块语法,它表示该文件导出的内容是一个对象,并且该对象是默认导出的。这使得 Vue 在加载组件时可以导入这个对象并使用它来渲染组件

样式部分

<style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
</style>

scoped 属性确保这些样式只作用于当前组件,不会影响到其他组件。这是因为 Vue 会为每个组件自动加上独特的属性选择器(如 .person 只作用于当前组件的 .person 元素)。

app.vue

<template><div class="app"><h1>你好啊!</h1><Person/></div>
</template><script lang="ts">import Person from './components/Person.vue'export default {name:'App', //组件名components:{Person} //注册组件}
</script><style>.app {background-color: #ddd;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}
</style>

Export default{}

export default {name: 'App',components: { Person }
}

export default 语句使得这个对象成为当前模块的默认导出。这意味着在其他地方使用 import 时,就可以导入这个对象。该对象定义了一个 Vue 组件,组件的名字是 App(通过 name: 'App' 设置)。App 是这个 Vue 组件的名称,它通常是根组件或父组件的名称。

• name 属性指定了当前组件的名字。在 Vue 开发工具中,App 组件将显示为 App,它通常是 Vue 应用的根组件。

• App 组件是父组件,而 Person 组件是它的子组件。

• components 是一个 Vue 组件选项,表示当前组件所使用的子组件。

• 这里通过 components: { Person } 注册了 Person 组件,意味着在 App 组件的模板中可以使用 <Person 标签来引用 Person 组件。

• 由于我们已经通过 import Person from './components/Person.vue' 导入了 Person 组件,所以在 components 中注册它时,只需要直接写 Person 就可以了。

【OptionsAPI 与 CompositionAPI】

Options API 的弊端

Options类型的 API,数据、方法、计算属性等,是分散在:datamethodscomputed中的,若想新增或者修改一个需求,就需要分别修改:datamethodscomputed,不便于维护和复用。

Composition API 的优势

可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。

<template><div class="person"><h2>姓名:{% raw %}{{name}}{% endraw %}</h2><h2>年龄:{% raw %}{{age}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button></div>
</template><script lang="ts">export default {name:'Person',beforeCreate(){console.log('beforeCreate')},setup(){console.log(this) //setup中的this是undefined,Vue3在弱化this了// 数据,原来是写在data中的,此时的name、age、tel都不是响应式的数据let name = '张三'let age = 18let tel = '13888888888'// 方法function changeName() {name = 'zhang-san' //注意:这样修改name,页面是没有变化的console.log(name) //name确实改了,但name不是响应式的}function changeAge() {age += 1 //注意:这样修改age,页面是没有变化的console.log(age) //age确实改了,但age不是响应式的}function showTel() {alert(tel)}// 将数据、方法交出去,模板中才可以使用return {name,age,tel,changeName,changeAge,showTel}}}
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
</style>

这段代码展示了一个vue3组件的setup()函数的使用,并且展示了一些vue3中的特性

Setup与compositionAPI

  • 组件名称

    export default {name: 'Person',beforeCreate() {console.log('beforeCreate')},

beforeCreate() 是一个 生命周期钩子,它会在 Vue 实例被创建之前调用。这是 Vue 2 和 Vue 3 中都存在的生命周期钩子,但是在 Vue 3 的 Composition API 中,生命周期钩子的使用方式发生了变化,通常会使用 onBeforeMount 等新的钩子函数(在 setup() 函数中)。

  • setup函数

    setup() {console.log(this) // setup中的this是undefined,Vue3在弱化this了

setup() 函数是 Vue 3 引入的 Composition API 的一部分,目的是简化组件的状态和行为的管理。

• 在 setup() 中,this 是 undefined,这与 Vue 2 中的 this(指向当前组件实例)不同。Vue 3 通过 Composition API 进行了优化,弱化了对 this 的依赖,增强了对组合逻辑的关注。此时,你应该通过返回的对象来访问数据和方法,而不是通过 this。

  • 定义数据

    let name = '张三'
    let age = 18
    let tel = '13888888888'

  • 定义方法

    function changeName() {name = 'zhang-san' // 注意:这样修改name,页面是没有变化的console.log(name) // name确实改了,但name不是响应式的
    }
    function changeAge() {age += 1 // 注意:这样修改age,页面是没有变化的console.log(age) // age确实改了,但age不是响应式的
    }
    function showTel() {alert(tel)
    }

    changeName()、changeAge() 和 showTel() 是组件的方法。修改 name 和 age 时,你会发现页面没有发生变化。这是因为 name 和 age 是普通的 JavaScript 变量,而不是响应式数据

    如果你希望这些数据能够自动反映到模板中,应该使用 Vue 3 的响应式 API(如 ref() 或 reactive())。

  • 返回数据与方法

    return { name, age, tel, changeName, changeAge, showTel }

setup与optionAPI&xompositionAPI

  • 模版部分

    <template><div class="person"><h2>姓名:{% raw %}{{name}}{% endraw %}</h2><h2>年龄:{% raw %}{{age}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button><hr><h2>测试1:{% raw %}{{a}}{% endraw %}</h2><h2>测试2:{% raw %}{{c}}{% endraw %}</h2><h2>测试3:{% raw %}{{d}}{% endraw %}</h2><button @click="b">测试</button></div>
    </template>

• name、age:显示 data 或 setup 中的数据。

• a、c、d:展示的是通过 data() 中的数据。

• 还有一些按钮和方法,如 changeName、changeAge 和 showTel。

  • 脚本部分

    beforeCreate(){console.log('beforeCreate')
    }
    

    image-20250127172908590

记清楚这个模版

  • data

    data(){return {a: 100,c: this.name,  // 这里的 `this.name` 会在 `data` 被调用时是 `undefined`,因为 `name` 在 Vue 3 的 `setup()` 中还没有定义。d: 900,age: 90}
    }
  • methods

    methods:{b(){console.log('b')}
    }

    定义了一个方法b,他会在点击按钮时输出b

  • setup

    setup(){let name = '张三'let age = 18let tel = '13888888888'function changeName() {name = 'zhang-san'console.log(name)}function changeAge() {age += 1console.log(age)}function showTel() {alert(tel)}return {name, age, tel, changeName, changeAge, showTel}
    }

    在setup()中,你定义了name, age,tel,他们是普通的javascript 变量,因此他们不是响应式的。修改的时候页面不会刷新

    相比较下,我更偏向于上一个写法

    setup语法糖

    <template><div class="person"><h2>姓名:{% raw %}{{name}}{% endraw %}</h2><h2>年龄:{% raw %}{{age}}{% endraw %}</h2><h2>地址:{% raw %}{{address}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button></div>
    </template><script lang="ts" setup name="Person">// 数据,原来是写在data中的,此时的name、age、tel都不是响应式的数据let name = '张三'let age = 18let tel = '13888888888'let address = '北京昌平区宏福苑·宏福科技园'// 方法function changeName() {name = 'zhang-san' //注意:这样修改name,页面是没有变化的console.log(name) //name确实改了,但name不是响应式的}function changeAge() {age += 1 //注意:这样修改age,页面是没有变化的console.log(age) //age确实改了,但age不是响应式的}function showTel() {alert(tel)}
    </script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
    </style>

重点是分析脚本

<script lang="ts" setup name="Person">// 数据,原来是写在data中的,此时的name、age、tel都不是响应式的数据let name = '张三'let age = 18let tel = '13888888888'let address = '北京昌平区宏福苑·宏福科技园'// 方法function changeName() {name = 'zhang-san' //注意:这样修改name,页面是没有变化的console.log(name) //name确实改了,但name不是响应式的}function changeAge() {age += 1 //注意:这样修改age,页面是没有变化的console.log(age) //age确实改了,但age不是响应式的}function showTel() {alert(tel)}
</script>
<script lang="ts" setup name="Person">// 数据,原来是写在data中的,此时的name、age、tel都不是响应式的数据

这里发生了改变

1. <script setup

• setup 是 Vue 3 的 Composition API 的新语法。它简化了组件的声明,并且没有 export default,所有的变量和方法都自动暴露给模板。

• name="Person" 是组件的名称,但是在 <script setup> 中并不需要显式定义,可以直接通过文件名推导。

2. 定义的变量:

• let name = '张三',let age = 18,let tel = '13888888888',let address = '北京昌平区宏福苑·宏福科技园':这些变量是普通的 JavaScript 变量,它们 不是响应式的。如果你修改这些变量,视图不会自动更新。

3. 修改数据的函数:

• changeName 和 changeAge 中直接修改了 name 和 age,但是由于没有使用 Vue 的响应式 API,页面不会随着这些变量的变化而自动重新渲染。

• 这是一个问题,因为 Vue 3 中的响应式系统(通过 ref 或 reactive)才能让数据变化时自动更新视图。

ref创建

哪一个是响应式的,就改变哪一个

<template><div class="person"><h2>姓名:{% raw %}{{name}}{% endraw %}</h2><h2>年龄:{% raw %}{{age}}{% endraw %}</h2><h2>地址:{% raw %}{{address}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button></div>
</template><script lang="ts" setup name="Person">import {ref} from 'vue'// 数据,原来是写在data中的,此时的name、age、tel都不是响应式的数据let name = ref('张三')let age = ref(18)let tel = '13888888888'let address = '北京昌平区宏福苑·宏福科技园'// 方法function changeName() {name.value = 'zhang-san' // JS中操作ref对象时候需要.valueconsole.log(name.value) }function changeAge() {age.value += 1 console.log(age.value) // JS中操作ref对象时候需要.value}function showTel() {alert(tel)}
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
</style>

这段代码已经解决了你之前提到的 响应式数据 问题,通过使用 ref 将 name 和 age 变成了响应式变量,确保它们的变化能够自动更新到视图中。让我们来逐部分解释这个代码:

ref()用于创建单一响应式数据,而reactive()用于创建对象的响应式数据

import { ref } from 'vue';<script lang="ts" setup name="Person">// 使用 ref() 创建响应式数据let name = ref('张三');let age = ref(18);let tel = ref('13888888888');let address = ref('北京昌平区宏福苑·宏福科技园');// 方法function changeName() {name.value = 'zhang-san'; // 修改时需要通过 `.value` 访问和修改 ref 数据console.log(name.value);}function changeAge() {age.value += 1;console.log(age.value);}function showTel() {alert(tel.value);}
</script>

Reactive-对象类型

<template><div class="person"><h2>汽车信息:一辆{% raw %}{{car.brand}}{% endraw %}车,价值{% raw %}{{car.price}}{% endraw %}万</h2><button @click="changePrice">修改汽车的价格</button><br><h2>游戏列表:</h2><ul><li v-for="g in games" :key="g.id">{% raw %}{{g.name}}{% endraw %}</li></ul><button @click="changeFirstGame">修改第一个游戏的名字</button><hr><h2>测试:{% raw %}{{obj.a.b.c}}{% endraw %}</h2><button @click="changeObj">测试</button></div>
</template><script lang="ts" setup name="Person">import { reactive } from 'vue'// 定义数据类型type Car = {brand: string;price: number;}type Game = {id: string;name: string;}type Obj = {a: {b: {c: number;}}}// 响应式数据let car = reactive<Car>({ brand: '奔驰', price: 100 })let games = reactive<Game[]>([{ id: 'aysdytfsatr01', name: '王者荣耀' },{ id: 'aysdytfsatr02', name: '原神' },{ id: 'aysdytfsatr03', name: '三国志' }])let obj = reactive<Obj>({a: {b: {c: 666}}})// 方法function changePrice() {car.price += 10console.log(car.price)}function changeFirstGame() {games[0].name = '流星蝴蝶剑'}function changeObj() {obj.a.b.c = 999}
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

何时使用 reactive:

1. 对象和数组的响应式数据

• reactive 主要用于对象和数组类型的响应式处理。因为它会深度递归地将对象的每一个属性都变成响应式的。

• 如果你想让一个复杂的对象(例如包含嵌套对象或数组的对象)自动反应数据变化并更新视图时,就应该使用 reactive。

2. 对象需要嵌套响应式

• 如果你有多层嵌套的数据结构,并且想要使所有的嵌套属性都成为响应式的,reactive 是非常合适的。比如,一个对象内部有数组,数组内部又有对象等。

3. 非原始数据类型

• reactive 适用于对象和数组,但不适用于原始类型(例如:number、string、boolean)。如果你只需要处理一个原始数据类型,可以使用 ref。

4. 复杂的数据结构

• 当你有一个比较复杂的对象,且其中可能包含许多不同类型的属性,reactive 能够方便地使这些属性变得响应式,避免手动为每个属性都使用 ref 或者其他方法来设置响应式。

<template><div class="person"><h2>姓名:{% raw %}{{ person.name }}{% endraw %}</h2><h2>年龄:{% raw %}{{ person.age }}{% endraw %}</h2><h2>地址:{% raw %}{{ person.address }}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="showTel">查看联系方式</button></div>
</template><script lang="ts" setup name="Person">import { reactive } from 'vue'// 使用 reactive 来定义响应式对象const person = reactive({name: '张三',age: 18,tel: '13888888888',address: '北京昌平区宏福苑·宏福科技园'})// 修改姓名function changeName() {person.name = 'zhang-san'console.log(person.name) }// 修改年龄function changeAge() {person.age += 1 console.log(person.age) }// 展示联系方式function showTel() {alert(person.tel)}
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
</style>

image-20250127210920434

<template><div class="person"><h2>汽车信息:一辆{% raw %}{{car.brand}}{% endraw %}车,价值{% raw %}{{car.price}}{% endraw %}万</h2><button @click="changeBrand">修改汽车的品牌</button><button @click="changePrice">修改汽车的价格</button><button @click="changeCar">修改汽车</button><hr><h2>当前求和为:{% raw %}{{sum}}{% endraw %}</h2><button @click="changeSum">点我sum+1</button></div>
</template><script lang="ts" setup name="Person">import {ref,reactive} from 'vue'// 数据let car = reactive({brand:'奔驰',price:100})let sum = ref(0)// 方法function changeBrand(){car.brand = '宝马'}function changePrice(){car.price += 10}function changeCar(){// car = {brand:'奥拓',price:1} //这么写页面不更新的// car = reactive({brand:'奥拓',price:1}) //这么写页面不更新的// 下面这个写法页面可以更新Object.assign(car,{brand:'奥拓',price:1})}function changeSum(){// sum = ref(9) //这么写页面不更新的sum.value += 1}</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>
  // 修改汽车(对象赋值的问题)function changeCar() {// 通过 Object.assign 保持响应式Object.assign(car, { brand: '奥拓', price: 1 })}

这里是重点

Torefs && toref

image-20250127213249475

image-20250127213325812

类似于解构

<template><div class="person"><h2>姓名:{% raw %}{{person.name}}{% endraw %}</h2><h2>年龄:{% raw %}{{person.age}}{% endraw %},{% raw %}{{nl}}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button></div>
</template><script lang="ts" setup name="Person">import {reactive,toRefs,toRef} from 'vue'// 数据let person = reactive({name:'张三',age:18})// 使用toRefs从person这个响应式对象中,解构出name、age,且name和age依然是响应式的// name和age的值是ref类型,其value值指向的是person.name和person.agelet {name,age} = toRefs(person)let nl = toRef(person,'age')console.log(nl.value)// 方法function changeName(){name.value += '~'console.log(name.value,person.name)}function changeAge(){age.value += 1}</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

1. reactive 和 toRefs 的使用:

• reactive:用于创建响应式对象。你使用 reactive 来创建 person 对象,该对象包含 name 和 age。

• toRefs:将 reactive 对象的属性解构出来,变成单独的响应式 ref。你通过 toRefs(person) 将 person 对象中的 name 和 age 分别解构为 ref 类型的响应式数据。这样,name 和 age 的每个属性都保持响应式。**

• toRef:用来将对象的特定属性转换为 ref。你通过 toRef(person, 'age') 将 person 对象的 age 属性变成一个 ref 类型。

2. changeName 和 changeAge 方法:

• changeName:修改 name 的值,通过 name.value 更新。由于 name 是通过 toRefs 解构出来的,它依然是响应式的,因此当修改 name.value 时,视图会自动更新。

• changeAge:同样修改 age 的值,age 也是一个 ref 类型,通过 age.value 来更新

computed计算属性

<template><div class="person">姓:<input type="text" v-model="firstName"> <br>名:<input type="text" v-model="lastName"> <br><button @click="changeFullName">将全名改为li-si</button> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br></div>
</template><script lang="ts" setup name="Person">import {ref,computed} from 'vue'let firstName = ref('zhang')let lastName = ref('san')// fullName是一个计算属性,且是只读的/* let fullName = computed(()=>{console.log(1)return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' + lastName.value}) */// fullName是一个计算属性,可读可写let fullName = computed({// 当fullName被读取时,get调用get(){return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' + lastName.value},// 当fullName被修改时,set调用,且会收到修改的值set(val){const [str1,str2] = val.split('-')firstName.value = str1lastName.value = str2}})function changeFullName(){fullName.value = 'li-si'}
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

在这里面有一个计算属性,她的作用是基于已有的响应式数据计算新的值,计算属性的返回值会自动缓存,只有当它依赖的数据发生变化时,才会重新计算。

计算属性是只读的,也可以是可读可导的

现在展开对代码进行讲解

  • 模版部分

    <template><div class="person">姓:<input type="text" v-model="firstName"> <br>名:<input type="text" v-model="lastName"> <br><button @click="changeFullName">将全名改为li-si</button> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br>全名:<span>{% raw %}{{fullName}}{% endraw %}</span> <br></div>
    </template>

    其中那么多全名是为了对齐进行测试

  • 脚本部分

    <script lang="ts" setup name="Person">import {ref,computed} from 'vue'let firstName = ref('zhang')let lastName = ref('san')// fullName是一个计算属性,且是可读可写的let fullName = computed({// 当fullName被读取时,get调用get(){return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' + lastName.value},// 当fullName被修改时,set调用,且会收到修改的值set(val){const [str1,str2] = val.split('-')firstName.value = str1lastName.value = str2}})function changeFullName(){fullName.value = 'li-si'}
    </script>

只读
  // fullName是一个计算属性,且是只读的/* let fullName = computed(()=>{console.log(1)return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' + lastName.value}) */
可读可写
// fullName是一个计算属性,可读可写let fullName = computed({// 当fullName被读取时,get调用get(){return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' + lastName.value},// 当fullName被修改时,set调用,且会收到修改的值set(val){const [str1,str2] = val.split('-')firstName.value = str1lastName.value = str2}})

2. computed

• computed 是 Vue 3 中的 计算属性,它会根据其他响应式数据的变化动态计算一个值,并且当相关数据改变时,计算属性会自动更新。

• fullName 是一个 可读可写的计算属性,通过 get 和 set 方法来控制:

• get():当 fullName 被读取时,它会拼接 firstName 和 lastName,并且确保 firstName 的首字母大写。

• set(val):当 fullName 被修改时,set 会接收到新的值,并将其拆分为 firstName 和 lastName,更新这两个响应式变量。

3. changeFullName 方法:

• 当点击按钮时,会调用 changeFullName 方法,并设置 fullName 的值为 'li-si'。由于 fullName 是计算属性,这会触发 set 方法,从而更新 firstName 和 lastName 的值为 'li' 和 'si'。

watch监视

image-20250127215508527

情况一

<template><div class="person"><h1>情况一:监视【ref】定义的【基本类型】数据</h1><h2>当前求和为:{% raw %}{{sum}}{% endraw %}</h2><button @click="changeSum">点我sum+1</button></div>
</template><script lang="ts" setup name="Person">import {ref,watch} from 'vue'// 数据let sum = ref(0)// 方法function changeSum(){sum.value += 1}// 监视,情况一:监视【ref】定义的【基本类型】数据const stopWatch = watch(sum,(newValue,oldValue)=>{console.log('sum变化了',newValue,oldValue)if(newValue >= 10){stopWatch()}})
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>
<script lang="ts" setup name="Person">import { ref, watch } from 'vue'// 数据let sum = ref(0)// 方法function changeSum() {sum.value += 1}// 监视,情况一:监视【ref】定义的【基本类型】数据const stopWatch = watch(sum, (newValue, oldValue) => {console.log('sum变化了', newValue, oldValue)if (newValue >= 10) {stopWatch() // 停止监听}})
</script>

watch的基本语法

watch(source, callback, options)

source:要监视的数据源(可以是一个响应式对象、ref 等)。

callback:数据变化时调用的回调函数,它会接收到新值和旧值。

options:可选参数,允许你配置 watch 的行为。

在你的例子中,watch 监视了 sum 的变化,每当 sum 发生变化时,回调函数就会执行,打印出新旧值。如果新值大于或等于 10,就停止监视。

<template><div class="person"><h1>情况二:监视【ref】定义的【对象类型】数据</h1><h2>姓名:{% raw %}{{ person.name }}{% endraw %}</h2><h2>年龄:{% raw %}{{ person.age }}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="changePerson">修改整个人</button></div>
</template><script lang="ts" setup name="Person">import {ref,watch} from 'vue'// 数据let person = ref({name:'张三',age:18})// 方法function changeName(){person.value.name += '~'}function changeAge(){person.value.age += 1}function changePerson(){person.value = {name:'李四',age:90}}/* 监视,情况一:监视【ref】定义的【对象类型】数据,监视的是对象的地址值,若想监视对象内部属性的变化,需要手动开启深度监视watch的第一个参数是:被监视的数据watch的第二个参数是:监视的回调watch的第三个参数是:配置对象(deep、immediate等等.....) */watch(person,(newValue,oldValue)=>{console.log('person变化了',newValue,oldValue)},{deep:true})</script>
<style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

2. watch 监视对象变化:

• watch 是 Vue 3 提供的 API,用来监听响应式数据(如 ref 或 reactive)的变化。当监视的数据变化时,watch 的回调函数会被触发。

你在代码中通过 watch(person, ...) 来监听 person 对象的变化。watch 会接收到两个参数:

• newValue:person 变化后的新值。

• oldValue:person 变化前的旧值。

• deep: true:由于 watch 默认只监视对象的引用变化,如果你需要监视对象内部属性的变化(即对象内部的数据变化),需要设置 { deep: true },这样 Vue 会递归地监视对象内部的每个属性变化。

• 深度监视:

• deep 是 watch 的一个选项,它使得 Vue 能够监听 对象属性的变化。当对象的嵌套属性发生变化时,watch 的回调也会被触发。

• 如果没有开启深度监视,那么只有对象的引用变化(如直接替换整个对象)才会触发回调。如果只是修改对象的某个属性,默认不会触发回调。

3. person.value = { name: '李四', age: 90 }:

• 在 changePerson 方法中,直接给 person 赋值一个新的对象,这会改变 person 的引用,从而触发 watch 监听的回调。

情况3

<template><div class="person"><h1>情况三:监视【reactive】定义的【对象类型】数据</h1><h2>姓名:{% raw %}{{ person.name }}{% endraw %}</h2><h2>年龄:{% raw %}{{ person.age }}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="changePerson">修改整个人</button><hr><h2>测试:{% raw %}{{obj.a.b.c}}{% endraw %}</h2><button @click="test">修改obj.a.b.c</button></div>
</template><script lang="ts" setup name="Person">import {reactive,watch} from 'vue'// 数据let person = reactive({name:'张三',age:18})let obj = reactive({a:{b:{c:666}}})// 方法function changeName(){person.name += '~'}function changeAge(){person.age += 1}function changePerson(){Object.assign(person,{name:'李四',age:80})}function test(){obj.a.b.c = 888}// 监视,情况三:监视【reactive】定义的【对象类型】数据,且默认是开启深度监视的watch(person,(newValue,oldValue)=>{console.log('person变化了',newValue,oldValue)})watch(obj,(newValue,oldValue)=>{console.log('Obj变化了',newValue,oldValue)})</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

情况四

<template><div class="person"><h1>情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性</h1><h2>姓名:{% raw %}{{ person.name }}{% endraw %}</h2><h2>年龄:{% raw %}{{ person.age }}{% endraw %}</h2><h2>汽车:{% raw %}{{ person.car.c1 }}{% endraw %}、{% raw %}{{ person.car.c2 }}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="changeC1">修改第一台车</button><button @click="changeC2">修改第二台车</button><button @click="changeCar">修改整个车</button></div>
</template><script lang="ts" setup name="Person">import {reactive,watch} from 'vue'// 数据let person = reactive({name:'张三',age:18,car:{c1:'奔驰',c2:'宝马'}})// 方法function changeName(){person.name += '~'}function changeAge(){person.age += 1}function changeC1(){person.car.c1 = '奥迪'}function changeC2(){person.car.c2 = '大众'}function changeCar(){person.car = {c1:'雅迪',c2:'爱玛'}}// 监视,情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式/* watch(()=> person.name,(newValue,oldValue)=>{console.log('person.name变化了',newValue,oldValue)}) */// 监视,情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数watch(()=>person.car,(newValue,oldValue)=>{console.log('person.car变化了',newValue,oldValue)},{deep:true})</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>
watch(() => person.car, (newValue, oldValue) => {console.log('person.car变化了', newValue, oldValue)
}, { deep: true })

• deep: true:由于 person.car 是一个对象,默认情况下,watch 只会监听对象的引用变化。如果你想监听对象内部的嵌套属性(如 c1 和 c2)的变化,需要设置 { deep: true },这会开启深度监视。

• 在 深度监视 下,watch 不仅会监视 person.car 的引用变化,还会监视 person.car.c1 和 person.car.c2 的变化。

这是对象类型的写法

情况5-监视多个事件

<template><div class="person"><h1>情况五:监视上述的多个数据</h1><h2>姓名:{% raw %}{{ person.name }}{% endraw %}</h2><h2>年龄:{% raw %}{{ person.age }}{% endraw %}</h2><h2>汽车:{% raw %}{{ person.car.c1 }}{% endraw %}、{% raw %}{{ person.car.c2 }}{% endraw %}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="changeC1">修改第一台车</button><button @click="changeC2">修改第二台车</button><button @click="changeCar">修改整个车</button></div>
</template><script lang="ts" setup name="Person">import {reactive,watch} from 'vue'// 数据let person = reactive({name:'张三',age:18,car:{c1:'奔驰',c2:'宝马'}})// 方法function changeName(){person.name += '~'}function changeAge(){person.age += 1}function changeC1(){person.car.c1 = '奥迪'}function changeC2(){person.car.c2 = '大众'}function changeCar(){person.car = {c1:'雅迪',c2:'爱玛'}}// 监视,情况五:监视上述的多个数据watch([()=>person.name,person.car],(newValue,oldValue)=>{console.log('person.car变化了',newValue,oldValue)},{deep:true})</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>
  // 监视,情况五:监视上述的多个数据watch([()=>person.name,person.car],(newValue,oldValue)=>{console.log('person.car变化了',newValue,oldValue)},{deep:true})

就是加了个中括号

watch- effect

<template><div class="person"><h2>需求:当水温达到60度,或水位达到80cm时,给服务器发请求</h2><h2>当前水温:{% raw %}{{temp}}{% endraw %}℃</h2><h2>当前水位:{% raw %}{{height}}{% endraw %}cm</h2><button @click="changeTemp">水温+10</button><button @click="changeHeight">水位+10</button></div>
</template><script lang="ts" setup name="Person">import {ref,watch,watchEffect} from 'vue'// 数据let temp = ref(10)let height = ref(0)// 方法function changeTemp(){temp.value += 10}function changeHeight(){height.value += 10}// 监视 -- watch实现/* watch([temp,height],(value)=>{// 从value中获取最新的水温(newTemp)、最新的水位(newHeight)let [newTemp,newHeight] = value// 逻辑if(newTemp >= 60 || newHeight >= 80){console.log('给服务器发请求')}}) */// 监视 -- watchEffect实现watchEffect(()=>{if(temp.value >= 60 || height.value >= 80){console.log('给服务器发请求')}})</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

详细讲解:

watch 的用法:

• watch 是 Vue 3 中的一个 API,用于监视一个或多个响应式数据。当监视的数据发生变化时,watch 会触发回调函数,并将最新的值传递给回调函数。

• watch([temp, height], (value) => {...}):

• temp 和 height 是你监视的两个数据源。

• 当这两个数据发生变化时,watch 会调用回调函数 (value)。

• value 是一个数组,包含了 temp 和 height 的新值。注意:这两个值的顺序与传入 watch 时的顺序一致,value[0] 是 temp 的新值,value[1] 是 height 的新值。

回调函数:

• value:

• value 是一个数组,包含了所有被监视的数据的新值。在这个例子中,value 是 [newTemp, newHeight]。

• 通过解构赋值 let [newTemp, newHeight] = value,可以直接获取 temp 和 height 的新值。

条件判断:

• 如果 newTemp(水温)大于等于 60,或者 newHeight(水位)大于等于 80,就执行 console.log('给服务器发请求')。

• 这段逻辑可以用于监测水温或水位达到某个阈值时,触发某些操作(例如,发送请求给服务器)。

标签属性

<template><div class="person"><h1>中国</h1><h2 ref="title2">北京</h2><h3>尚硅谷</h3><button @click="showLog">点我输出h2这个元素</button></div>
</template><script lang="ts" setup name="Person">import {ref,defineExpose} from 'vue'// 创建一个title2,用于存储ref标记的内容let title2 = ref()let a = ref(0)let b = ref(1)let c = ref(2)function showLog(){console.log(title2.value)}defineExpose({a,b,c})
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

TS

index.ts

// 定义一个接口,用于限制person对象的具体属性
export interface PersonInter {id:string,name:string,age:number
}// 一个自定义类型
// export type Persons = Array<PersonInter>
export type Persons = PersonInter[]

interface 定义接口

export interface PersonInter {id: string,name: string,age: number
}

interface :接口用于定义对象的结构与约束

在这里:PersonInter是一个接口,约束了一个person对象必须具有的属性

• id:类型为 string,表示唯一标识符。

• name:类型为 string,表示人员的姓名。

• age:类型为 number,表示人员的年龄。

• type:类型别名可以用来给复杂的类型(如数组、联合类型等)取一个简短的名字。

• Persons:类型别名定义为一个 PersonInter 对象数组(即 PersonInter[]),表示一个由多个 person 对象组成的列表。

<script lang="ts" setup name="Person">import {type PersonInter,type Persons} from '@/types'// let person:PersonInter = {id:'asyud7asfd01',name:'张三',age:60}let personList:Persons = [{id:'asyud7asfd01',name:'张三',age:60},{id:'asyud7asfd02',name:'李四',age:18},{id:'asyud7asfd03',name:'王五',age:5}]</script>

• import { type ... }:

• type 是 TypeScript 的关键字,用来导入类型信息。它能明确表明这是一个类型导入,而不是普通值。

• 从 @/types 文件中导入了两个类型:PersonInter 和 Persons。

• @/types:

• 表示一个类型定义文件的路径。一般情况下,这个文件夹是项目中专门用来存放全局类型定义的。

• 在这个 types 文件中,定义了以下内容(假设内容如下):

• let personList: Persons:

• 通过 :Persons 明确指定了 personList 的类型是 Persons。

• Persons 的定义是 PersonInter[],即一个数组,数组的每个元素都必须符合 PersonInter 接口的结构。

• personList 的用途:

• personList 是一个数组,其中存储了多个 person 对象。

• 每个对象必须具有 id(字符串)、name(字符串)和 age(数字)属性,否则 TypeScript 会抛出类型错误。

数据校验示例

• 如果你尝试添加一个不符合 PersonInter 结构的对象,比如:

let personList: Persons = [{ id: 'asyud7asfd04', name: '赵六' } // 缺少 age 属性
]

image-20250128002108189

image-20250128002115128

props的使用

<template><div class="person"><ul><li v-for="p in list" :key="p.id">{% raw %}{{p.name}}{% endraw %} -- {% raw %}{{p.age}}{% endraw %}</li></ul></div>
</template><script lang="ts" setup name="Person">import {withDefaults} from 'vue'import {type Persons} from '@/types'// 只接收list// defineProps(['list'])// 接收list + 限制类型// defineProps<{list:Persons}>()//  接收list + 限制类型 + 限制必要性 + 指定默认值withDefaults(defineProps<{list?:Persons}>(),{list:()=> [{id:'ausydgyu01',name:'康师傅·王麻子·特仑苏',age:19}]})// 接收list,同时将props保存起来/* let x = defineProps(['list'])console.log(x.list) */</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
</style>

拆分代码:

  • 模版部分

    <template><div class="person"><ul><li v-for="p in list" :key="p.id">{% raw %}{{p.name}}{% endraw %} -- {% raw %}{{p.age}}{% endraw %}</li></ul></div>
    </template>

这里面含有v-for循环,那么这个是什么?

  • 遍历list数据(通过props传递到组件中)

  • 每个p是list数组中的一项

  • :key="p.id" 为每个列表项绑定唯一的 key,提高渲染性能。

• {% raw %}{ {p.name}}{% endraw %} 和 {% raw %}{ {p.age}}{% endraw %} 动态展示每个对象的 name 和 age 属性。

  • 脚本部分

    • 导入工具与类型

      import { withDefaults } from 'vue'
      import { type Persons } from '@/types'

      • withDefaults:

      • 用于为 defineProps 定义的 props 设置默认值。它接收两个参数:

      • defineProps 的返回值(包含 props 的类型约束)。

      • 一个对象,用来指定每个 prop 的默认值。

    • 那么对应的index.ts

      // 定义一个接口,用于限制person对象的具体属性
      export interface PersonInter {id:string,name:string,age:number,
      }// 一个自定义类型
      // export type Persons = Array<PersonInter>
      export type Persons = PersonInter[]

相关文章:

vue3相关知识点

title: vue_1 date: 2025-01-28 12:00:00 tags:- 前端 categories:- 前端vue3 Webpack ~ vite vue3是基于vite创建的 vite 更快一点 一些准备工作 准备后如图所示 插件 Main.ts // 引入createApp用于创建应用 import {createApp} from vue // 引入App根组件 import App f…...

【2025美赛D题】为更美好的城市绘制路线图建模|建模过程+完整代码论文全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的美赛O奖、国赛国一的数学建模团队&#xff0c;我们将为你带来本次数学建模竞赛的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解析&#xff0c…...

games101-(5/6)

光栅化 投影完成之后&#xff0c;视图区域被确定在从[-1,1]的单位矩阵中&#xff0c;下一步就是光栅化 长宽比&#xff1a;ratio 垂直的可视角度&#xff1a;fild-of-view 可以看到的y 轴的范围&#xff0c;角度越小 越接近正交投影 屏幕坐标系 、 将多边形转化成像素 显示…...

UE5.3 C++ CDO的初步理解

一.UObject UObject是所有对象的基类&#xff0c;往上还有UObjectBaseUtility。 注释&#xff1a;所有虚幻引擎对象的基类。对象的类型由基于 UClass 类来定义。 这为创建和使用UObject的对象提供了 函数&#xff0c;并且提供了应在子类中重写的虚函数。 /** * The base cla…...

前端——js高级25.1.27

复习&#xff1a;对象 问题一&#xff1a; 多个数据的封装提 一个对象对应现实中的一个事物 问题二&#xff1a; 统一管理多个数据 问题三&#xff1a; 属性&#xff1a;组成&#xff1a;属性名属性值 &#xff08;属性名为字符串&#xff0c;属性值任意&#xff09; 方…...

Python 魔术方法

1. 什么是魔术方法 在 Python 中&#xff0c;魔术方法&#xff08;Magic Methods&#xff09;&#xff0c;又叫 特殊方法 或 双下方法&#xff0c;是以两个下划线&#xff08;__&#xff09;开头和结尾的方法。 这些方法为 Python 提供了对类和对象的特殊操作功能&#xff0c…...

websocket webworker教程及应用

WebSocket 和 Web Workers 是两种不同的 Web 技术&#xff0c;分别用于实现实时通信和后台线程处理。以下是它们的简要教程&#xff1a; WebSocket 教程 1. 什么是 WebSocket&#xff1f; WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许服务器主动向客户端推…...

qwen2.5-vl:阿里开源超强多模态大模型(包含使用方法、微调方法介绍)

1.简介 在 Qwen2-VL 发布后的五个月里&#xff0c;众多开发者基于该视觉语言模型开发了新的模型&#xff0c;并向 Qwen 团队提供了极具价值的反馈。在此期间&#xff0c;Qwen 团队始终致力于打造更具实用性的视觉语言模型。今天&#xff0c;Qwen 家族的最新成员——Qwen2.5-VL…...

PaddleSeg 从配置文件和模型 URL 自动化运行预测任务

git clone https://github.com/PaddlePaddle/PaddleSeg.git# 在ipynb里面运行 cd PaddleSegimport sys sys.path.append(/home/aistudio/work/PaddleSeg)import os# 配置文件夹路径 folder_path "/home/aistudio/work/PaddleSeg/configs"# 遍历文件夹&#xff0c;寻…...

Java实战项目-基于 springboot 的校园选课小程序(附源码,部署,文档)

Java 基于 springboot 的校园选课小程序 博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战*✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&…...

网络工程师 (7)进程管理

一、进程相关的概念 &#xff08;一&#xff09;定义 进程&#xff08;Process&#xff09;是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;也是操作系统结构的基础。进程是程序的一次执行实例&#xff0c;具有动…...

大屏 UI 设计风格的未来趋势

在科技飞速革新的时代&#xff0c;大屏设备的应用领域不断拓展&#xff0c;从城市的智能交通指挥中心&#xff0c;到商场的互动广告大屏&#xff0c;再到家庭的超大尺寸智能电视&#xff0c;大屏已然成为信息展示与交互的关键载体。大屏 UI 设计风格也随之不断演变&#xff0c;…...

Kmesh v1.0 正式发布

2025 年 1 月 23 日&#xff0c;Kmesh 团队正式发布了 Kmesh v1.0235。Kmesh 作为一款开源的服务网格解决方案&#xff0c;v1.0 版本在网络流量管理领域引入了多项重磅特性2。具体如下134&#xff1a; IPsec 加密通信&#xff1a;引入 IPsec 加密协议&#xff0c;将节点间流量加…...

低代码系统-产品架构案例介绍、轻流(九)

轻流低代码产品定位为零代码产品&#xff0c;试图通过搭建来降低企业成本&#xff0c;提升业务上线效率。 依旧是从下至上&#xff0c;从左至右的顺序 名词概述运维层底层系统运维层&#xff0c;例如上线、部署等基础服务体系内置的系统能力&#xff0c;发消息、组织和权限是必…...

深入理解动态规划(dp)--(提前要对dfs有了解)

前言&#xff1a;对于动态规划&#xff1a;该算法思维是在dfs基础上演化发展来的&#xff0c;所以我不想讲的是看到一个题怎样直接用动态规划来解决&#xff0c;而是说先用dfs搜索&#xff0c;一步步优化&#xff0c;这个过程叫做动态规划。&#xff08;该文章教你怎样一步步的…...

C++传送锚点的内存寻址:内存管理

文章目录 1.C/C内存分布回顾2.C内存管理2.1 内存申请2.2 operator new与operator delete函数2.3 定位new表达式 3.关于内存管理的常见知识点3.1 malloc/free和new/delete的区别3.2 内存泄漏 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 继C语…...

webAPI -DOM 相关知识点总结(非常细)

title: WebAPI语法 date: 2025-01-28 12:00:00 tags:- 前端 categories:- 前端WEB API 了解DOM的结构并掌握其基本的操作&#xff0c;体验 DOM 在开发中的作用 API简介 就是使用js来操作html和浏览器 什么是DOM? 就是一个文档对象模型&#xff0c;是用来呈现预计于任意htm…...

Deepseek的RL算法GRPO解读

在本文中&#xff0c;我们将深入探讨Deepseek采用的策略优化方法GRPO&#xff0c;并顺带介绍一些强化学习&#xff08;Reinforcement Learning, RL&#xff09;的基础知识&#xff0c;包括PPO等关键概念。 策略函数&#xff08;policy&#xff09; 在强化学习中&#xff0c; a…...

设计模式的艺术-策略模式

行为型模式的名称、定义、学习难度和使用频率如下表所示&#xff1a; 1.如何理解策略模式 在策略模式中&#xff0c;可以定义一些独立的类来封装不同的算法&#xff0c;每个类封装一种具体的算法。在这里&#xff0c;每个封装算法的类都可以称之为一种策略&#xff08;Strategy…...

MyBatis 写法

MyBatis 高效使用技巧 常见 MyBatis 使用技巧&#xff0c;这些技巧有助于简化数据库操作&#xff0c;提高开发效率&#xff0c;并增强系统的性能。 1. 动态 SQL 动态 SQL 让开发者能够依据参数灵活地构建 SQL 语句&#xff0c;避免了手动拼接字符串带来的复杂性和错误风险。…...

Git图形化工具【lazygit】

简要介绍一下偶然发现的Git图形化工具——「lazygit」 概述 Lazygit 是一个用 Go 语言编写的 Git 命令行界面&#xff08;TUI&#xff09;工具&#xff0c;它让 Git 操作变得更加直观和高效。 Github地址&#xff1a;https://github.com/jesseduffield/lazygit 主要特点 主要…...

K8s运维管理平台 - xkube体验:功能较多

目录 简介Lic安装1、需要手动安装MySQL&#xff0c;**建库**2、启动命令3、[ERROR] GetNodeMetric Fail:the server is currently unable to handle the request (get nodes.metrics.k8s.io qfusion-1) 使用总结优点优化 补充1&#xff1a;layui、layuimini和beego的详细介绍1.…...

5.3.1 软件设计的基本任务

文章目录 软件设计解决的问题概要设计基本任务详细设计基本任务 软件设计解决的问题 需求分析解决“做什么”的问题&#xff0c;软件设计解决“如何做”的问题。软件设计分为概要设计、详细设计两块。概要设计是设计软件和数据的总体框架&#xff0c;比详细设计的颗粒度更大。详…...

Go学习:字符、字符串需注意的点

Go语言与C/C语言编程有很多相似之处&#xff0c;但是Go语言中在声明一个字符时&#xff0c;数据类型与其他语言声明一个字符数据时有一点不同之处。通常&#xff0c;字符的数据类型为 char&#xff0c;例如 &#xff1a;声明一个字符 (字符名称为 ch) 的语句格式为 char ch&am…...

LabVIEW无线齿轮监测系统

本案例介绍了基于LabVIEW的无线齿轮监测系统设计。该系统利用LabVIEW编程语言和改进的天牛须算法优化支持向量机&#xff0c;实现了无线齿轮故障监测。通过LabVIEW软件和相关硬件&#xff0c;可以实现对齿轮箱振动信号的采集、传输和故障识别&#xff0c;集远程采集、数据库存储…...

基于SpringBoot的租房管理系统(含论文)

基于SpringBoot的租房管理系统是一个集订单管理、房源信息管理、屋主申诉处理、用户反馈等多项功能于一体的系统。该系统通过SpringBoot框架开发&#xff0c;拥有完善的管理员后台、屋主管理模块、用户功能模块等&#xff0c;适用于房地产租赁平台或中介公司进行日常管理与运营…...

剑指 Offer II 008. 和大于等于 target 的最短子数组

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20008.%20%E5%92%8C%E5%A4%A7%E4%BA%8E%E7%AD%89%E4%BA%8E%20target%20%E7%9A%84%E6%9C%80%E7%9F%AD%E5%AD%90%E6%95%B0%E7%BB%84/README.md 剑指 Offer II 008.…...

【微服务与分布式实践】探索 Eureka

服务注册中心 心跳检测机制&#xff1a;剔除失效服务自我保护机制 统计心跳失败的比例在15分钟之内是否低于85%&#xff0c;如果出现低于的情况&#xff0c;Eureka Server会将当前的实例注册信息保护起来&#xff0c;让这些实例不会过期。当节点在短时间内丢失过多的心跳时&am…...

关于opencv环境搭建问题:由于找不到opencv_worldXXX.dll,无法执行代码,重新安装程序可能会解决此问题

方法一&#xff1a;利用复制黏贴方法 打开opencv文件夹目录找到\opencv\build\x64\vc15\bin 复制该目录下所有文件&#xff0c;找到C:\Windows\System32文件夹&#xff08;注意一定是C盘&#xff09;黏贴至该文件夹重新打开VS。 方法二&#xff1a;直接配置环境 打开opencv文…...

重构字符串(767)

767. 重构字符串 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:string reorganizeString(string s){string res;//因为1 < s.length < 500 &#xff0c; uint64_t 类型足够uint16_t n s.size();if (n 0) {return res;}unordere…...

【MQ】如何保证消息队列的高性能?

零拷贝 Kafka 使用到了 mmap 和 sendfile 的方式来实现零拷贝。分别对应 Java 的 MappedByteBuffer 和 FileChannel.transferTo 顺序写磁盘 Kafka 采用顺序写文件的方式来提高磁盘写入性能。顺序写文件&#xff0c;基本减少了磁盘寻道和旋转的次数完成一次磁盘 IO&#xff0…...

通义灵码插件保姆级教学-IDEA(安装及使用)

一、JetBrains IDEA 中安装指南 官方下载指南&#xff1a;通义灵码安装教程-阿里云 步骤 1&#xff1a;准备工作 操作系统&#xff1a;Windows 7 及以上、macOS、Linux&#xff1b; 下载并安装兼容的 JetBrains IDEs 2020.3 及以上版本&#xff0c;通义灵码与以下 IDE 兼容&…...

babylon.js-3:了解STL网格模型

网格模型上色 本篇文章主要介绍如何在 BabylonJS 中实现STL网格模型上色。 文章目录 网格模型上色运用场景概要延申正文加载器库的支持认识 OBJ 和 STL 文件GUI 色板选择器网格模型异步加载加载动画网格模型上色官方即将弃用 ImportMesh 而推荐使用 ImportMeshAsync 说明OBJ …...

面向对象设计(大三上)--往年试卷题+答案

目录 1. UML以及相关概念 1.1 动态图&静态图 1.2 交互图 1.3 序列图 1.4 类图以及关联关系 1.4.1类图 1.4.2 关系类型 (1) 用例图中的包含、扩展关系(include & extend) (2) 类图中的聚合、组合关系(aggragation & composition) 1.5 图对象以及职责划…...

Java基础知识总结(二十四)--Collections

它的出现给集合操作提供了更多的功能。这个类不需要创建对象&#xff0c;内部提供的都是静态方法。 静态方法&#xff1a; Collections.sort(list);//list集合进行元素的自然顺序排序。 Collections.sort(list,new ComparatorByLen());//按指定的比较器方法排序。 class Co…...

大语言模型的API接口如何操作

选择大语言模型 根据自身需求和应用场景选择合适的大语言模型&#xff0c;如 OpenAI 的 GPT 系列、百度的文心一言、智谱的 GLM 等。需要考虑模型的性能、功能特点、适用领域、成本等因素。 获取 API 密钥和凭证 注册账号&#xff1a;访问所选大语言模型的官方平台或相关开发…...

【漫话机器学习系列】067.希腊字母(greek letters)-写法、名称、读法和常见用途

希腊字母&#xff08;Greek Letters&#xff09; 希腊字母在数学、科学、工程学和编程中广泛使用&#xff0c;常用于表示变量、常量、参数、角度等。以下是希腊字母的完整列表及其常见用途。 大写与小写希腊字母表 大写小写名称&#xff08;英文&#xff09;名称&#xff08;…...

Kotlin判空辅助工具

1&#xff09;?.操作符 //执行逻辑 if (person ! null) {person.doSomething() } //表达式 person?.doSomething() 2&#xff09;?:操作符 //执行逻辑 val c if (a ! null) {a } else {b } //表达式 val c a ?: b 3&#xff09;!!表达式 var message: String? &qu…...

【Python-办公自动化】实现自动化输出json数据类型的分析报告和正逆转换

分析报告 import json from pprint import pprint, PrettyPrinterdef analyze_energy_data(file_path):"""能源数据分析与结构查看函数参数:file_path (str): JSON文件路径功能:1. 加载并解析JSON数据2. 显示数据结构概览3. 交互式结构探索"""…...

深入理解指针(2)

数组名的理解 什么是数组名&#xff1f;在计算机编程中&#xff0c;数组名是用于标识一个数组的名称。那应当如何来理解数组名呢&#xff1f;事实上&#xff0c;在数组中数组名就是数组首元素的地址。 示例1&#xff1a; #include<stdio.h> int main() {int arr[10] …...

SOME/IP--协议英文原文讲解3

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 Note: Thi…...

计算机网络之计算机网络主要性能

一、速率与带宽 速率&#xff1a; 定义&#xff1a;数据的传送速率&#xff0c;也称数据率或比特率&#xff0c;表示单位时间内传输的比特数。 单位&#xff1a;比特/秒&#xff08;bit/s&#xff09;&#xff0c;常用单位有千比特/秒&#xff08;kb/s&#xff09;、兆比特/秒…...

家居 EDI:Haverty‘s EDI 需求分析

Havertys 成立于 1885 年&#xff0c;是一家历史悠久的美国家具零售商。公司致力于为客户提供高品质的家具和家居饰品&#xff0c;其产品线涵盖客厅、卧室、餐厅及办公家具等多个领域。 电子数据交换&#xff08;EDI&#xff09;是一种通过标准化电子格式在商业伙伴之间进行数据…...

JavaScript - Web APIs(上)

Web API 介绍 严格意义上讲&#xff0c;我们在 JavaScript 阶段学习的知识绝大部分属于 ECMAScript 的知识体系&#xff0c;ECMAScript 简称 ES 它提供了一套语言标准规范&#xff0c;如变量、数据类型、表达式、语句、函数等语法规则都是由 ECMAScript 规定的。浏览器将 ECM…...

【漫话机器学习系列】068.网格搜索(GridSearch)

网格搜索&#xff08;Grid Search&#xff09; 网格搜索&#xff08;Grid Search&#xff09;是一种用于优化机器学习模型超参数的技术。它通过系统地遍历给定的参数组合&#xff0c;找出使模型性能达到最优的参数配置。 网格搜索的核心思想 定义参数网格 创建一个包含超参数值…...

MySQL 的索引类型【图文并茂】

基本分类 文本生成MindMap:https://app.pollyoyo.com/planttext <style> mindmapDiagram {node {BackgroundColor yellow}:depth(0) {BackGroundColor SkyBlue}:depth(1) {BackGroundColor lightGreen} } </style> * MySQL 索引** 数据结构角度 *** B树索引*** 哈…...

OSCP:发送钓鱼电子邮件执行客户端攻击

概述 在渗透测试领域&#xff0c;钓鱼攻击是一种有效的客户端攻击手段&#xff0c;尤其在目标用户缺乏安全意识或系统存在未修复漏洞时&#xff0c;成功率较高。针对Windows平台&#xff0c;滥用Windows库文件&#xff08;.Library-ms&#xff09;是一种技术性较强但易于实施的…...

Oracle 普通用户连接hang住处理方法

一、现象说明 $ sqlplus / as sysdbaSQL*Plus: Release 19.0.0.0.0 - Production on Wed Dec 18 16:49:19 2024 Version 19.11.0.0.0Copyright (c) 1982, 2020, Oracle. All rights reserved.Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Pro…...

C++ ——— 学习并使用 priority_queue 类

目录 何为 priority_queue 类 学习并使用 priority_queue 类 实例化一个 priority_queue 类对象 插入数据 遍历堆&#xff08;默认是大堆&#xff09; 通过改变实例化的模板参数修改为小堆 何为 priority_queue 类 priority_queue 类为 优先级队列&#xff0c;其本质就是…...

JVM--类加载器

概念 类加载器&#xff1a;只参与加载过程中的字节码获取并加载到内存中的部分&#xff1b;java虚拟机提供给应用程序去实现获取类和接口字节码数据的一种技术&#xff0c;也就是说java虚拟机是允许程序员写代码去获取字节码信息 类加载是加载的第一步&#xff0c;主要有以下三…...