当前位置: 首页 > 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…...

基于springboot+vue的流浪动物救助系统的设计与实现

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

MySQL(单表访问)

今天是新年&#xff0c;祝大家新年快乐&#xff0c;但是生活还是得继续。 后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 大部分截图和文章采…...

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

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

SpringBoot 中的测试jar包knife4j(实现效果非常简单)

1、效果图 非常快的可以看见你实现的接口 路径http://localhost:8080/doc.html#/home 端口必须是自己的 2、实现效果 2.1、导入jar包 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-star…...

Java Web 开发基础介绍

Java学习资料 Java学习资料 Java学习资料 一、引言 在当今数字化时代&#xff0c;Web 应用无处不在。Java 凭借其强大的功能、良好的跨平台性和丰富的开发框架&#xff0c;成为 Web 开发领域的热门选择之一。Java Web 开发允许开发者构建动态、交互式的 Web 应用程序&#x…...

Android Studio:视图绑定的岁月变迁(2/100)

一、博文导读 本文是基于Android Studio真实项目&#xff0c;通过解析源码了解真实应用场景&#xff0c;写文的视角和读者是同步的&#xff0c;想到看到写到&#xff0c;没有上帝视角。 前期回顾&#xff0c;本文是第二期。 private Unbinder mUnbinder; 只是声明了一个 接口…...

LabVIEW春节快乐

尊敬的LabVIEW开发者与用户朋友们&#xff1a; 灵蛇舞动辞旧岁&#xff0c;春风送暖贺新年&#xff01;值此癸巳蛇年新春佳节来临之际&#xff0c;向每一位深耕LabVIEW开发领域的伙伴致以最诚挚的祝福&#xff1a;愿您与家人在新的一年里平安顺遂、阖家幸福&#xff0c;事业如…...

rewrite规则

NGINX 中 rewrite最后的标记含义&#xff1a; flag标记有&#xff1a; last 相当于Apache里的[L]标记&#xff0c;表示完成rewrite&#xff0c;匹配完&#xff0c;再向下匹配。地址栏会显示跳转后的地址 break 终止匹配, 不再匹配后面的rewrite规则&#xff0c;地址栏会显示跳…...

Android车机DIY开发之学习篇(七)NDK交叉工具构建

Android车机DIY开发之学习篇(七)NDK交叉工具构建 1.ubuntu安装GCC sudo apt-get update sudo apt-get install gcc g sudo gcc --version sudo g --version 2.测试GCC VSCODE中新建Hello.c编译 #include <stdio.h> int main(void) { printf(“Hello, this is a progr…...

【初/高中生讲机器学习】0. 本专栏 “食用” 指南——写在一周年之际⭐

创建时间&#xff1a;2025-01-27 首发时间&#xff1a;2025-01-29 最后编辑时间&#xff1a;2025-01-29 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名高一学生&#xff0c;热爱计…...

虚幻基础11:坐标计算旋转计算

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 坐标line startget actor rotationget forward vector 旋转计算 坐标 ue中通常使用向量计算坐标。 line start 起始坐标点。 get actor rotation 获取旋转值&#xff1a; 当前角色朝向 get forward vector 获…...

Rust:Rhai脚本编程示例

当然&#xff0c;以下是一个简单的Rhai脚本编程示例&#xff0c;展示了如何在Rust中使用Rhai执行脚本。 首先&#xff0c;你需要确保你的Rust项目中包含了rhai库。你可以在你的Cargo.toml文件中添加以下依赖项&#xff1a; [dependencies] rhai "0.19" # 请检查最…...

关于el-table翻页后序号列递增的组件封装

需求说明&#xff1a; 项目中经常会用到的一个场景&#xff0c;表格第一列显示序号&#xff08;1、2、3...&#xff09;&#xff0c;但是在翻页后要递增显示序号&#xff0c;例如10、11、12&#xff08;假设一页显示10条数据&#xff09;&#xff0c;针对这种情况&#xff0c;封…...

【深度学习】softmax回归

softmax回归 回归可以用于预测多少的问题。 比如预测房屋被售出价格&#xff0c;或者棒球队可能获得的胜场数&#xff0c;又或者患者住院的天数。 事实上&#xff0c;我们也对分类问题感兴趣&#xff1a;不是问“多少”&#xff0c;而是问“哪一个”&#xff1a; 某个电子邮…...

设计模式-建造者模式、原型模式

目录 建造者模式 定义 类图 优缺点 角色 建造者模式和工厂模式比较 使用案例 原型模式 定义 类图 优缺点 应用场景 应用类型 浅克隆 深克隆 建造者模式 定义 将一个复杂的对象的构造与它的表示分离&#xff0c;使同样的构建过程可以创建不同的表示&#xff0c;…...

【Redis】List 类型的介绍和常用命令

1. 介绍 Redis 中的 list 相当于顺序表&#xff0c;并且内部更接近于“双端队列”&#xff0c;所以也支持头插和尾插的操作&#xff0c;可以当做队列或者栈来使用&#xff0c;同时也存在下标的概念&#xff0c;不过和 Java 中的下标不同&#xff0c;Redis 支持负数下标&#x…...

三个不推荐使用的线程池

线程池的种类 其实看似这么多的线程池&#xff0c;都离不开ThreadPoolExecutor去创建&#xff0c;只不过他们是简化一些参数 newFixedThreadPool 里面全是核心线程 有资源耗尽的风险&#xff0c;任务队列最大长度为Integer.MAX_VALUE&#xff0c;可能会堆积大量的请求&#xff…...

mybatis(78/134)

前天学了很多&#xff0c;关于java的反射机制&#xff0c;其实跳过了new对象&#xff0c;然后底层生成了字节码&#xff0c;创建了对应的编码。手搓了一遍源码&#xff0c;还是比较复杂的。 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE …...

Progressive Pretext Task Learning for Human Trajectory Prediction | 文献翻译

祥龙回首留胜景&#xff0c;金蛇起舞贺新程。 概述 行人轨迹预测是一项旨在预测行人未来位置的任务&#xff0c;它通常涵盖了从短期到长期的整个时间范围内的轨迹。然而&#xff0c;现有的研究试图通过单一、统一的训练范式来解决整个轨迹预测问题&#xff0c;往往忽视了行人轨…...

54.数字翻译成字符串的可能性|Marscode AI刷题

1.题目 问题描述 小M获得了一个任务&#xff0c;需要将数字翻译成字符串。翻译规则是&#xff1a;0对应"a"&#xff0c;1对应"b"&#xff0c;依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的…...

【数据结构】_链表经典算法OJ(力扣版)

目录 1. 移除链表元素 1.1 题目描述及链接 1.2 解题思路 1.3 程序 2. 反转链表 2.1 题目描述及链接 2.2 解题思路 2.3 程序 3. 链表的中间结点 3.1 题目描述及链接 3.2 解题思路 3.3 程序 1. 移除链表元素 1.1 题目描述及链接 原题链接&#xff1a;203. 移除链表…...

【Linux】统计文本中每行指定位置出现的字符串的次数

统计文本中每行指定位置出现的字符串的次数 假定情景 某些项目&#xff0c;会把某个特定事件记录到Log中并且落盘&#xff08;保持到硬盘&#xff09;。基于落盘后的日志&#xff0c;要统计这些日志里产生该特定事件的次数 统计脚本 可以写一个sh脚本&#xff0c;来解析某个…...

【赵渝强老师】K8s中Pod探针的ExecAction

在K8s集群中&#xff0c;当Pod处于运行状态时&#xff0c;kubelet通过使用探针&#xff08;Probe&#xff09;对容器的健康状态执行检查和诊断。K8s支持三种不同类型的探针&#xff0c;分别是&#xff1a;livenessProbe&#xff08;存活探针&#xff09;、readinessProbe&#…...

商品信息管理自动化测试

目录 前言 一、思维导图 二、代码编写 1.在pom.xml文件中添加相关依赖 2.自动化代码编写 三、代码测试 小结 前言 1. 针对商品信息管理项目进行测试&#xff0c;商品信息管理项目主要有商品列表页、部门列表页、员工列表页&#xff0c;主要功能&#xff1a;对商品信息的…...

Redis实战(黑马点评)——redis存储地理信息、位图、HyperLogLog 用法

Redis存储geo数据类型基本介绍 geo 就是 geolocation 的简写形式&#xff0c;代表地理坐标。redis 在 3.2 版本中加入了对 geo 的支持&#xff0c;允许存储地理坐标信息&#xff0c;帮助我们根据经纬度来检索数据。常见的命令有&#xff1a; geoadd&#xff1a;添加一个地理空…...

判断1到100之间有多少个素数,并输出所有的素数。

def is_prime(num): #判断一个数是否素数if num<1:return False #因为1和负数都不是素数for i in range(2,int(num**0.5)1): #从2开始到根号num的整数结束&#xff0c;因为一个数num不是素数&#xff0c;那么把必定有一个小于或等于根号num的因素if num%i0:return False #如…...

JAVA:利用 Content Negotiation 实现多样式响应格式的技术指南

1、简述 Content Negotiation&#xff08;内容协商&#xff09; 是 RESTful 服务的重要特性&#xff0c;允许客户端和服务器根据请求的不同特性动态选择适合的响应格式。它是一种在 HTTP 协议中实现的机制&#xff0c;通过它&#xff0c;服务器能够根据客户端需求返回适合的内…...

layui Table单元格编辑支持Enter键换行,包括下拉框单元格

layui Table表格编辑支持Enter键换行 可编辑单元格 $(".layui-table td").keydown(function (e) {// console.log("111",e);var index $(this).index(),tr $(this).parent(tr),isKeydown (event.type "keydown");if (e.code "Enter&q…...

Swoole的MySQL连接池实现

在Swoole中实现MySQL连接池可以提高数据库连接的复用率&#xff0c;减少频繁创建和销毁连接所带来的开销。以下是一个简单的Swoole MySQL连接池的实现示例&#xff1a; 首先&#xff0c;确保你已经安装了Swoole扩展和PDO_MySQL扩展&#xff08;或mysqli&#xff0c;但在这个示…...