网站图标怎么上传,网站常用配色,我想接app注册推广单,怎么自己做直播网站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…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 from ./App.vuecreateApp(App).mount(#app)
App 是根组件createApp是盆
npm run dev
APP.vue
templatediv classapph1你好啊/h1/div
/templatescript langtsexport default {name:App //组件名}
/scriptstyle.app {background-color: #ddd;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}
/style
简单效果实现
templatediv classpersonh2姓名{% raw %}{{name}}{% endraw %}/h2h2年龄{% raw %}{{age}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/button/div
/templatescript langtsexport default {name:Person,data(){return {name:张三,age:18,tel:13888888888}},methods:{// 修改姓名changeName(){this.name zhang-san},// 修改年龄changeAge(){this.age 1},// 展示联系方式showTel(){alert(this.tel)}}}
/scriptstyle 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
templatediv classpersonh2姓名{% raw %}{{name}}{% endraw %}/h2h2年龄{% raw %}{{age}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/button/div
/template
脚本部分
脚本定义了vue组件的逻辑部分 data 组件的状态即组件中使用的数据 Methods:定义组件的方法这些方法可以在模版中调用来响应用户事件 name : 组件的名字这里是Person,在vue开发工具中查看到这个组件 script langtsexport 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
templatediv classapph1你好啊/h1Person//div
/templatescript langtsimport Person from ./components/Person.vueexport default {name:App, //组件名components:{Person} //注册组件}
/scriptstyle.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数据、方法、计算属性等是分散在data、methods、computed中的若想新增或者修改一个需求就需要分别修改data、methods、computed不便于维护和复用。
Composition API 的优势
可以用函数的方式更加优雅的组织代码让相关功能的代码更加有序的组织在一起。
templatediv classpersonh2姓名{% raw %}{{name}}{% endraw %}/h2h2年龄{% raw %}{{age}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/button/div
/templatescript langtsexport default {name:Person,beforeCreate(){console.log(beforeCreate)},setup(){console.log(this) //setup中的this是undefinedVue3在弱化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}}}
/scriptstyle 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是undefinedVue3在弱化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与optionAPIxompositionAPI 模版部分 templatediv classpersonh2姓名{% raw %}{{name}}{% endraw %}/h2h2年龄{% raw %}{{age}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/buttonhrh2测试1{% raw %}{{a}}{% endraw %}/h2h2测试2{% raw %}{{c}}{% endraw %}/h2h2测试3{% raw %}{{d}}{% endraw %}/h2button clickb测试/button/div
/template
• name、age显示 data 或 setup 中的数据。
• a、c、d展示的是通过 data() 中的数据。
• 还有一些按钮和方法如 changeName、changeAge 和 showTel。 脚本部分 beforeCreate(){console.log(beforeCreate)
}记清楚这个模版 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 13888888888function changeName() {name zhang-sanconsole.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语法糖 templatediv classpersonh2姓名{% raw %}{{name}}{% endraw %}/h2h2年龄{% raw %}{{age}}{% endraw %}/h2h2地址{% raw %}{{address}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/button/div
/templatescript langts setup namePerson// 数据原来是写在data中的此时的name、age、tel都不是响应式的数据let name 张三let age 18let tel 13888888888let 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)}
/scriptstyle scoped.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
/style
重点是分析脚本
script langts setup namePerson// 数据原来是写在data中的此时的name、age、tel都不是响应式的数据let name 张三let age 18let tel 13888888888let 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 langts setup namePerson// 数据原来是写在data中的此时的name、age、tel都不是响应式的数据
这里发生了改变
1. script setup
• setup 是 Vue 3 的 Composition API 的新语法。它简化了组件的声明并且没有 export default所有的变量和方法都自动暴露给模板。
• namePerson 是组件的名称但是在 script setup 中并不需要显式定义可以直接通过文件名推导。
2. 定义的变量
• let name 张三let age 18let tel 13888888888let address 北京昌平区宏福苑·宏福科技园这些变量是普通的 JavaScript 变量它们 不是响应式的。如果你修改这些变量视图不会自动更新。
3. 修改数据的函数
• changeName 和 changeAge 中直接修改了 name 和 age但是由于没有使用 Vue 的响应式 API页面不会随着这些变量的变化而自动重新渲染。
• 这是一个问题因为 Vue 3 中的响应式系统通过 ref 或 reactive才能让数据变化时自动更新视图。
ref创建
哪一个是响应式的就改变哪一个
templatediv classpersonh2姓名{% raw %}{{name}}{% endraw %}/h2h2年龄{% raw %}{{age}}{% endraw %}/h2h2地址{% raw %}{{address}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/button/div
/templatescript langts setup namePersonimport {ref} from vue// 数据原来是写在data中的此时的name、age、tel都不是响应式的数据let name ref(张三)let age ref(18)let tel 13888888888let 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)}
/scriptstyle 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 langts setup namePerson// 使用 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-对象类型
templatediv classpersonh2汽车信息一辆{% raw %}{{car.brand}}{% endraw %}车价值{% raw %}{{car.price}}{% endraw %}万/h2button clickchangePrice修改汽车的价格/buttonbrh2游戏列表/h2ulli v-forg in games :keyg.id{% raw %}{{g.name}}{% endraw %}/li/ulbutton clickchangeFirstGame修改第一个游戏的名字/buttonhrh2测试{% raw %}{{obj.a.b.c}}{% endraw %}/h2button clickchangeObj测试/button/div
/templatescript langts setup namePersonimport { reactive } from vue// 定义数据类型type Car {brand: string;price: number;}type Game {id: string;name: string;}type Obj {a: {b: {c: number;}}}// 响应式数据let car reactiveCar({ brand: 奔驰, price: 100 })let games reactiveGame[]([{ id: aysdytfsatr01, name: 王者荣耀 },{ id: aysdytfsatr02, name: 原神 },{ id: aysdytfsatr03, name: 三国志 }])let obj reactiveObj({a: {b: {c: 666}}})// 方法function changePrice() {car.price 10console.log(car.price)}function changeFirstGame() {games[0].name 流星蝴蝶剑}function changeObj() {obj.a.b.c 999}
/scriptstyle 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 或者其他方法来设置响应式。
templatediv classpersonh2姓名{% raw %}{{ person.name }}{% endraw %}/h2h2年龄{% raw %}{{ person.age }}{% endraw %}/h2h2地址{% raw %}{{ person.address }}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickshowTel查看联系方式/button/div
/templatescript langts setup namePersonimport { reactive } from vue// 使用 reactive 来定义响应式对象const person reactive({name: 张三,age: 18,tel: 13888888888,address: 北京昌平区宏福苑·宏福科技园})// 修改姓名function changeName() {person.name zhang-sanconsole.log(person.name) }// 修改年龄function changeAge() {person.age 1 console.log(person.age) }// 展示联系方式function showTel() {alert(person.tel)}
/scriptstyle scoped.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}
/style templatediv classpersonh2汽车信息一辆{% raw %}{{car.brand}}{% endraw %}车价值{% raw %}{{car.price}}{% endraw %}万/h2button clickchangeBrand修改汽车的品牌/buttonbutton clickchangePrice修改汽车的价格/buttonbutton clickchangeCar修改汽车/buttonhrh2当前求和为{% raw %}{{sum}}{% endraw %}/h2button clickchangeSum点我sum1/button/div
/templatescript langts setup namePersonimport {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}/scriptstyle 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 类似于解构
templatediv classpersonh2姓名{% raw %}{{person.name}}{% endraw %}/h2h2年龄{% raw %}{{person.age}}{% endraw %}{% raw %}{{nl}}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/button/div
/templatescript langts setup namePersonimport {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}/scriptstyle 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计算属性
templatediv classperson姓input typetext v-modelfirstName br名input typetext v-modellastName brbutton clickchangeFullName将全名改为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
/templatescript langts setup namePersonimport {ref,computed} from vuelet 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}
/scriptstyle scoped.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
/style
在这里面有一个计算属性她的作用是基于已有的响应式数据计算新的值计算属性的返回值会自动缓存只有当它依赖的数据发生变化时才会重新计算。
计算属性是只读的也可以是可读可导的
现在展开对代码进行讲解 模版部分 templatediv classperson姓input typetext v-modelfirstName br名input typetext v-modellastName brbutton clickchangeFullName将全名改为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 langts setup namePersonimport {ref,computed} from vuelet 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监视 情况一
templatediv classpersonh1情况一监视【ref】定义的【基本类型】数据/h1h2当前求和为{% raw %}{{sum}}{% endraw %}/h2button clickchangeSum点我sum1/button/div
/templatescript langts setup namePersonimport {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()}})
/scriptstyle 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 langts setup namePersonimport { 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就停止监视。
templatediv classpersonh1情况二监视【ref】定义的【对象类型】数据/h1h2姓名{% raw %}{{ person.name }}{% endraw %}/h2h2年龄{% raw %}{{ person.age }}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangePerson修改整个人/button/div
/templatescript langts setup namePersonimport {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 会接收到两个参数
• newValueperson 变化后的新值。
• oldValueperson 变化前的旧值。
• deep: true由于 watch 默认只监视对象的引用变化如果你需要监视对象内部属性的变化即对象内部的数据变化需要设置 { deep: true }这样 Vue 会递归地监视对象内部的每个属性变化。
• 深度监视
• deep 是 watch 的一个选项它使得 Vue 能够监听 对象属性的变化。当对象的嵌套属性发生变化时watch 的回调也会被触发。
• 如果没有开启深度监视那么只有对象的引用变化如直接替换整个对象才会触发回调。如果只是修改对象的某个属性默认不会触发回调。
3. person.value { name: 李四, age: 90 }
• 在 changePerson 方法中直接给 person 赋值一个新的对象这会改变 person 的引用从而触发 watch 监听的回调。
情况3
templatediv classpersonh1情况三监视【reactive】定义的【对象类型】数据/h1h2姓名{% raw %}{{ person.name }}{% endraw %}/h2h2年龄{% raw %}{{ person.age }}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangePerson修改整个人/buttonhrh2测试{% raw %}{{obj.a.b.c}}{% endraw %}/h2button clicktest修改obj.a.b.c/button/div
/templatescript langts setup namePersonimport {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)})/scriptstyle scoped.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
/style
情况四
templatediv classpersonh1情况四监视【ref】或【reactive】定义的【对象类型】数据中的某个属性/h1h2姓名{% raw %}{{ person.name }}{% endraw %}/h2h2年龄{% raw %}{{ person.age }}{% endraw %}/h2h2汽车{% raw %}{{ person.car.c1 }}{% endraw %}、{% raw %}{{ person.car.c2 }}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div
/templatescript langts setup namePersonimport {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})/scriptstyle 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-监视多个事件
templatediv classpersonh1情况五监视上述的多个数据/h1h2姓名{% raw %}{{ person.name }}{% endraw %}/h2h2年龄{% raw %}{{ person.age }}{% endraw %}/h2h2汽车{% raw %}{{ person.car.c1 }}{% endraw %}、{% raw %}{{ person.car.c2 }}{% endraw %}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div
/templatescript langts setup namePersonimport {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})/scriptstyle 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
templatediv classpersonh2需求当水温达到60度或水位达到80cm时给服务器发请求/h2h2当前水温{% raw %}{{temp}}{% endraw %}℃/h2h2当前水位{% raw %}{{height}}{% endraw %}cm/h2button clickchangeTemp水温10/buttonbutton clickchangeHeight水位10/button/div
/templatescript langts setup namePersonimport {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(给服务器发请求)}})/scriptstyle 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(给服务器发请求)。
• 这段逻辑可以用于监测水温或水位达到某个阈值时触发某些操作例如发送请求给服务器。
标签属性
templatediv classpersonh1中国/h1h2 reftitle2北京/h2h3尚硅谷/h3button clickshowLog点我输出h2这个元素/button/div
/templatescript langts setup namePersonimport {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})
/scriptstyle 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 ArrayPersonInter
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 langts setup namePersonimport {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 属性
] props的使用
templatediv classpersonulli v-forp in list :keyp.id{% raw %}{{p.name}}{% endraw %} -- {% raw %}{{p.age}}{% endraw %}/li/ul/div
/templatescript langts setup namePersonimport {withDefaults} from vueimport {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) *//scriptstyle scoped.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}
/style
拆分代码 模版部分 templatediv classpersonulli v-forp in list :keyp.id{% raw %}{{p.name}}{% endraw %} -- {% raw %}{{p.age}}{% endraw %}/li/ul/div
/template
这里面含有v-for循环那么这个是什么 遍历list数据(通过props传递到组件中) 每个p是list数组中的一项 :keyp.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 ArrayPersonInter
export type Persons PersonInter[]