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

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…...

Lustre v6 语法 - 时序表达式

概述 Lustre v6 语法中&#xff0c;与时序表达式有关的运算&#xff0c;包括 ->(followed by), pre(previous), fby, current, when, merge。其中&#xff0c;除 merge 运算是 Lustre v6 中新引入的外&#xff0c;其余在 Lustre Core 语法中已有定义。 与时序表达式有关的…...

vs2013 使用 eigen 库编译时报 C2059 错的解决方法

&#xff08;个人感觉&#xff09;vs2013 就不能使用版本大于等于 3.4 的 eigen&#xff0c;使用 3.3.9 就可以了&#xff0c;再不行就用 3.3.8 另一个博主也遇到过用 vs2013 的时候不能编译 3.4 的 eigen 的问题&#xff0c;不过我用的是 win11&#xff0c;所以感觉跟操作系统…...

Kafka 消费端反复 Rebalance: `Attempt to heartbeat failed since group is rebalancing`

文章目录 Kafka 消费端反复 Rebalance: Attempt to heartbeat failed since group is rebalancing1. Rebalance 过程概述2. 错误原因分析2.1 消费者组频繁加入或退出2.1.1 消费者故障导致频繁重启2.1.2. 消费者加入和退出导致的 Rebalance2.1.3 消费者心跳超时导致的 Rebalance…...

【第九天】零基础入门刷题Python-算法篇-数据结构与算法的介绍-六种常见的图论算法(持续更新)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Python数据结构与算法的详细介绍1.Python中的常用的图论算法2. 图论算法3.详细的图论算法1&#xff09;深度优先搜索&#xff08;DFS&#xff09;2&#xf…...

微服务网关鉴权之sa-token

目录 前言 项目描述 使用技术 项目结构 要点 实现 前期准备 依赖准备 统一依赖版本 模块依赖 配置文件准备 登录准备 网关配置token解析拦截器 网关集成sa-token 配置sa-token接口鉴权 配置satoken权限、角色获取 通用模块配置用户拦截器 api模块配置feign…...

shell脚本批量修改文件名之方法(The Method of Batch Modifying File Names in Shell Scripts)

shell脚本批量修改文件名方法 我们可以使用Shell脚本来实现这个功能。Shell脚本是一种用于自动化任务的编程语言&#xff0c;它可以在Unix/Linux操作系统上运行。在这个脚本中&#xff0c;我们将使用一个for循环来遍历目标目录下的所有文件&#xff0c;并使用mv命令将每个文件…...

华为小米vivo向上,苹果荣耀OPPO向下

日前&#xff0c;Counterpoint发布的手机销量月度报告显示&#xff0c;中国智能手机销量在2024年第四季度同比下降3.2%&#xff0c;成为2024年唯一出现同比下滑的季度。而对于各大智能手机品牌来说&#xff0c;他们的市场份额和格局也在悄然发生变化。 华为逆势向上 在2024年第…...

国产编辑器EverEdit - 输出窗口

1 输出窗口 1.1 应用场景 输出窗口可以显示用户执行某些操作的结果&#xff0c;主要包括&#xff1a; 查找类&#xff1a;查找全部&#xff0c;筛选等待操作&#xff0c;可以把查找结果打印到输出窗口中&#xff1b; 程序类&#xff1a;在执行外部程序时(如&#xff1a;命令窗…...

获取snmp oid的小方法1(随手记)

snmpwalk遍历设备的mib # snmpwalk -v <SNMP version> -c <community-id> <IP> . snmpwalk -v 2c -c test 192.168.100.201 .根据获取的值&#xff0c;找到某一个想要的值的oid # SNMPv2-MIB::sysName.0 STRING: test1 [rootzabbix01 fonts]# snmpwalk -v…...

DeepSeek模型:开启人工智能的新篇章

DeepSeek模型&#xff1a;开启人工智能的新篇章 在当今快速发展的技术浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;已经成为了推动社会进步和创新的核心力量之一。而DeepSeek模型&#xff0c;作为AI领域的一颗璀璨明珠&#xff0c;正以其强大的功能和灵活的用法&…...

望获实时Linux系统:2024回顾与2025展望

2024年回顾 功能安全认证 2024年4月&#xff0c;望获操作系统V2获ISO26262:2018功能安全产品认证&#xff08;ASIL B等级&#xff09;&#xff0c;达到国际功能安全标准。 EtherCAT实时性增强 2024年5月&#xff0c;发布通信实时增强组件&#xff0c;EtherCAT总线通信抖…...

2025_1_29 C语言学习中关于指针

1. 指针 指针就是存储的变量的地址&#xff0c;指针变量就是指针的变量。 1.1 空指针 当定义一个指针没有明确指向内容时&#xff0c;就可以将他设置为空指针 int* p NULL;这样对空指针的操作就会使程序崩溃而不会导致出现未定义行为&#xff0c;因为程序崩溃是宏观的&…...

SQL注入漏洞之高阶手法 宽字节注入以及编码解释 以及堆叠注入原理说明

目录 宽字节注入 编码区分 原理 函数 转译符号解释 注意 绕过方式详解 堆叠【Stack】注入攻击 注入语句 宽字节注入 在说宽字节注入之前 我们需要知道编码相关的知识点&#xff0c;这个有助于搞定什么是宽字节注入 分清楚是ascii码是什么宽字节注入代码里面加入了adds…...

doris:JSON

JSON 数据类型&#xff0c;用二进制格式高效存储 JSON 数据&#xff0c;通过 JSON 函数访问其内部字段。 默认支持 1048576 字节&#xff08;1 MB&#xff09;&#xff0c;可调大到 2147483643 字节&#xff08;2 GB&#xff09;&#xff0c;可通过 BE 配置string_type_length…...

ADC 精度 第一部分:精度与分辨率是否不同?

在与使用模数转换器&#xff08;ADC&#xff09;的系统设计师交谈时&#xff0c;我经常听到的一个最常见问题是&#xff1a; “你们的16位ADC也是16位准确的吗&#xff1f;” 这个问题的答案在于对分辨率和精度这两个概念的基本理解存在差异。尽管这是两个完全不同的概念&…...

生成模型:扩散模型(DDPM, DDIM, 条件生成)

扩散模型的理论较为复杂&#xff0c;论文公式与开源代码都难以理解。现有的教程大多侧重推导公式。为此&#xff0c;本文通过精简代码&#xff08;约300行&#xff09;&#xff0c;更多以代码运行角度讲解扩散模型。 本代码包括扩散模型的主流技术复现&#xff1a; 1.DDPM (De…...

人格分裂(交互问答)-小白想懂Elasticsearch

通过交互式追问了解一个中间件 ? 啥是Elasticsearch ! 分布式搜索和分析引擎 ? 为啥是分布式搜索&#xff0c;单体难道用不了吗 ? 实际上是说这个东西可以分布式部署 ! 单机可用但扩展性差&#xff0c;分布式通过分片、副本和负载均衡实现海量数据存储与高并发处理 ? 提…...

【hot100】刷题记录(7)-除自身数组以外的乘积

题目描述&#xff1a; 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#x…...

鸢尾花书01---基本介绍和Jupyterlab的上手

文章目录 1.致谢和推荐2.py和.ipynb区别3.Jupyterlab的上手3.1入口3.2页面展示3.3相关键介绍3.4代码的运行3.5重命名3.6latex和markdown说明 1.致谢和推荐 这个系列是关于一套书籍&#xff0c;结合了python和数学&#xff0c;机器学习等等相关的理论&#xff0c;总结的7本书籍…...

可扩展架构:如何打造一个善变的柔性系统?

系统的构成:模块 + 关系 我们天天和系统打交道,但你有没想过系统到底是什么?在我看来,系统内部是有明确结构 的,它可以简化表达为: 系统 = 模块 + 关系 在这里,模块是系统的基本组成部分,它泛指子系统、应用、服务或功能模块。关系指模块 之间的依赖关系,简单…...

C++并发:C++内存模型和原子操作

C11引入了新的线程感知内存模型。内存模型精确定义了基础构建单元应当如何被运转。 1 内存模型基础 内存模型牵涉两个方面&#xff1a;基本结构和并发。 基本结构关系到整个程序在内存中的布局。 1.1 对象和内存区域 C的数据包括&#xff1a; 内建基本类型&#xff1a;int&…...

实验作业管理系统的设计与实现

标题:实验作业管理系统的设计与实现 内容:1.摘要 本系统旨在解决当前实验作业管理中存在的问题&#xff0c;提高管理效率和质量。通过对现有系统的调研和分析&#xff0c;我们确定了系统的功能需求和性能要求&#xff0c;并采用了先进的技术和架构进行设计和实现。系统实现了实…...

宝塔mysql数据库容量限制_宝塔数据库mysql-bin.000001占用磁盘空间过大

磁盘空间占用过多&#xff0c;排查后发现网站/www/wwwroot只占用7G&#xff0c;/www/server占用却高达8G&#xff0c;再深入排查发现/www/server/data目录下的mysql-bin.000001和mysql-bin.000002两个日志文件占去了1.5G空间。 百度后学到以下知识&#xff0c;做个记录。 mysql…...

2859.计算K置位下标对应元素的和

示例 1&#xff1a;输入&#xff1a;nums [5,10,1,5,2], k 1 输出&#xff1a;13 解释&#xff1a;下标的二进制表示是&#xff1a; 0 0002 1 0012 2 0102 3 0112 4 1002 下标 1、2 和 4 在其二进制表示中都存在 k 1 个置位。 因此&#xff0c;答案为 nums[1] nums[…...

8. 网络编程

网络的基本概念 TCP/IP协议概述 OSI和TCP/IP模型 socket&#xff08;套接字&#xff09; 创建socket 字节序 字节序转换函数 通用地址结构 因特网地址结构 IPV4地址族和字符地址间的转换(点分十进制->网络字节序) 填写IPV4地址族结构案例 掌握TCP协议网络基础编程 相关函数 …...

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

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

Git Bash 配置 zsh

博客食用更佳 博客链接 安装 zsh 安装 Zsh 安装 Oh-my-zsh github仓库 sh -c "$(curl -fsSL https://install.ohmyz.sh/)"让 zsh 成为 git bash 默认终端 vi ~/.bashrc写入&#xff1a; if [ -t 1 ]; thenexec zsh fisource ~/.bashrc再重启即可。 更换主题 …...

DeepSeek-R1 本地部署模型流程

DeepSeek-R1 本地部署模型流程 ***************************************************** 环境准备 操作系统&#xff1a;Windows11 内存&#xff1a;32GB RAM 存储&#xff1a;预留 300GB 可用空间 显存: 16G 网络: 100M带宽 ********************************************…...

C++ unordered_map和unordered_set的使用,哈希表的实现

文章目录 unordered_map&#xff0c;unorder_set和map &#xff0c;set的差异哈希表的实现概念直接定址法哈希冲突哈希冲突举个例子 负载因子将关键字转为整数哈希函数除法散列法/除留余数法 哈希冲突的解决方法开放定址法线性探测二次探测 开放定址法代码实现 哈希表的代码 un…...