Vue3 学习笔记(Day2)

这篇具有很好参考价值的文章主要介绍了Vue3 学习笔记(Day2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

「写在前面」

本文为尚硅谷禹神 Vue3 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容:
1. Vue3 学习笔记(Day1)


目录

  • 3 Vue3 核心语法
    • 3.1 选项式API 与 组合式API
    • 3.2 setup
    • 3.3 ref 和 reactive
    • 3.4 computed
    • 3.5 watch
    • 3.6 标签的 ref 属性
    • 3.7 props
    • 3.8 生命周期
    • 3.9 hook

3 Vue3 核心语法

3.1 选项式API 与 组合式API

P6:https://www.bilibili.com/video/BV1Za4y1r7KE?p=6

  • Vue2API设计是 Options(选项式)风格的。
  • Vue3API设计是 Composition(组合式)风格的。

Options API 的弊端:

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

Vue3 学习笔记(Day2),前端,vue.js
Vue3 学习笔记(Day2),前端,vue.js

Composition API 的优势:

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

Vue3 学习笔记(Day2),前端,vue.js
Vue3 学习笔记(Day2),前端,vue.js

3.2 setup

setup 概述

P7:https://www.bilibili.com/video/BV1Za4y1r7KE?p=7

setupVue3中一个新的配置项,值是一个函数,它是 Composition API “表演的舞台”,组件中所用到的:数据、方法、计算属性、监视......等等,均配置在setup中。

特点如下:

  • setup函数返回的对象中的内容,可直接在模板中使用。
  • setup中访问 thisundefined
  • setup函数会在 beforeCreate之前调用,它是“领先”所有钩子执行的。
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">年龄+1</button>
<button @click="showTel">点我查看联系方式</button>
</div>
</template>

<script lang="ts">
export default {
name:'Person',
setup(){
// 数据,原来写在data中(注意:此时的name、age、tel数据都不是响应式数据)
let name = '张三'
let age = 18
let tel = '13888888888'

// 方法,原来写在methods中
function changeName(){
name = 'zhang-san' //注意:此时这么修改name页面是不变化的
console.log(name)
}
function changeAge(){
age += 1 //注意:此时这么修改age页面是不变化的
console.log(age)
}
function showTel(){
alert(tel)
}

// 返回一个对象,对象中的内容,模板中可以直接使用
return {name,age,tel,changeName,changeAge,showTel}
}
}
</script>
setup 的返回值

P8:https://www.bilibili.com/video/BV1Za4y1r7KE?p=8

  • 若返回一个 对象:则对象中的:属性、方法等,在模板中均可以直接使用 (重点关注)。
  • 若返回一个 函数:则可以自定义渲染内容,代码如下:
setup(){
return ()=> '你好啊!'
}
setup 与 Options API 的关系

P9:https://www.bilibili.com/video/BV1Za4y1r7KE?p=9

  • Vue2 的配置( datamethos......)中 可以访问到 setup中的属性、方法。
  • 但在 setup不能访问到 Vue2的配置( datamethos......)。
  • 如果与 Vue2冲突,则 setup优先。
setup 语法糖

P10:https://www.bilibili.com/video/BV1Za4y1r7KE?p=10

setup函数有一个语法糖,这个语法糖,可以让我们把setup独立出去,代码如下:

<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changName">修改名字</button>
<button @click="changAge">年龄+1</button>
<button @click="showTel">点我查看联系方式</button>
</div>
</template>

<script lang="ts">
export default {
name:'Person234', // 定义组件名
}
</script>

<!-- 下面的写法是setup语法糖 -->
<script setup lang="ts">
console.log(this) //undefined

// 数据(注意:此时的name、age、tel都不是响应式数据)
let name = '张三'
let age = 18
let tel = '13888888888'

// 方法
function changName(){
name = '李四'//注意:此时这么修改name页面是不变化的
}
function changAge(){
console.log(age)
age += 1 //注意:此时这么修改age页面是不变化的
}
function showTel(){
alert(tel)
}
</script>

扩展:上述代码,还需要编写一个不写setupscript标签,去指定组件名字,比较麻烦,我们可以借助vite中的插件简化

  1. 第一步: npm i vite-plugin-vue-setup-extend -D
  2. 第二步:在 vite.config.ts文件中添加以下内容
import { defineConfig } from 'vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'

export default defineConfig({
plugins: [ VueSetupExtend() ]
})
  1. 第三步: <script setup lang="ts" name="Person234">

3.3 ref 和 reactive

ref 创建:基本类型的响应式数据

P11:https://www.bilibili.com/video/BV1Za4y1r7KE?p=11

  • 作用:定义响应式变量。
  • 语法: let xxx = ref(初始值)
  • 返回值:一个 RefImpl的实例对象,简称 ref对象refref对象的 value 属性是响应式的
  • 注意点:
    • JS中操作数据需要: xxx.value,但模板中不需要 .value,直接使用即可。
    • 对于 let name = ref('张三')来说, name不是响应式的, name.value是响应式的。
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">年龄+1</button>
<button @click="showTel">点我查看联系方式</button>
</div>
</template>

<script setup lang="ts" name="Person">
import {ref} from 'vue'
// name和age是一个RefImpl的实例对象,简称ref对象,它们的value属性是响应式的。
let name = ref('张三')
let age = ref(18)
// tel就是一个普通的字符串,不是响应式的
let tel = '13888888888'

function changeName(){
// JS中操作ref对象时候需要.value
name.value = '李四'
console.log(name.value)

// 注意:name不是响应式的,name.value是响应式的,所以如下代码并不会引起页面的更新。
// name = ref('zhang-san')
}
function changeAge(){
// JS中操作ref对象时候需要.value
age.value += 1
console.log(age.value)
}
function showTel(){
alert(tel)
}
</script>
reactive 创建:对象类型的响应式数据

P12:https://www.bilibili.com/video/BV1Za4y1r7KE?p=12

  • 作用:定义一个 响应式对象(基本类型不要用它,要用 ref,否则报错)
  • 语法: let 响应式对象= reactive(源对象)
  • 返回值:一个 Proxy的实例对象,简称:响应式对象。
  • 注意点: reactive定义的响应式数据是“深层次”的。
<template>
<div class="person">
<h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
<h2>游戏列表:</h2>
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
<h2>测试:{{obj.a.b.c.d}}</h2>
<button @click="changeCarPrice">修改汽车价格</button>
<button @click="changeFirstGame">修改第一游戏</button>
<button @click="test">测试</button>
</div>
</template>

<script lang="ts" setup name="Person">
import { reactive } from 'vue'

// 数据
let car = reactive({ brand: '奔驰', price: 100 })
let games = reactive([
{ id: 'ahsgdyfa01', name: '英雄联盟' },
{ id: 'ahsgdyfa02', name: '王者荣耀' },
{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = reactive({
a:{
b:{
c:{
d:666
}
}
}
})

function changeCarPrice() {
car.price += 10
}
function changeFirstGame() {
games[0].name = '流星蝴蝶剑'
}
function test(){
obj.a.b.c.d = 999
}
</script>
ref 创建:对象类型的响应式数据

P13:https://www.bilibili.com/video/BV1Za4y1r7KE?p=13

  • 其实 ref接收的数据可以是: 基本类型对象类型
  • ref接收的是对象类型,内部其实也是调用了 reactive函数。
<template>
<div class="person">
<h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
<h2>游戏列表:</h2>
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
<h2>测试:{{obj.a.b.c.d}}</h2>
<button @click="changeCarPrice">修改汽车价格</button>
<button @click="changeFirstGame">修改第一游戏</button>
<button @click="test">测试</button>
</div>
</template>

<script lang="ts" setup name="Person">
import { ref } from 'vue'

// 数据
let car = ref({ brand: '奔驰', price: 100 })
let games = ref([
{ id: 'ahsgdyfa01', name: '英雄联盟' },
{ id: 'ahsgdyfa02', name: '王者荣耀' },
{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = ref({
a:{
b:{
c:{
d:666
}
}
}
})

console.log(car)

function changeCarPrice() {
car.value.price += 10
}
function changeFirstGame() {
games.value[0].name = '流星蝴蝶剑'
}
function test(){
obj.value.a.b.c.d = 999
}
</script>
ref 对比 reactive

P14:https://www.bilibili.com/video/BV1Za4y1r7KE?p=14

宏观角度看:

  1. ref用来定义: 基本类型数据对象类型数据
  2. reactive用来定义: 对象类型数据

区别:

  1. ref创建的变量必须使用 .value(可以使用 volar插件自动添加 .value)。 Vue3 学习笔记(Day2),前端,vue.js
  2. reactive重新分配一个新对象,会 失去响应式(可以使用 Object.assign去整体替换)。

使用原则:

  1. 若需要一个基本类型的响应式数据,必须使用 ref
  2. 若需要一个响应式对象,层级不深, refreactive都可以。
  3. 若需要一个响应式对象,且层级较深,推荐使用 reactive
toRefs 与 toRef

P15:https://www.bilibili.com/video/BV1Za4y1r7KE?p=15

  • 作用:将一个响应式对象中的每一个属性,转换为 ref对象。
  • 备注: toRefstoRef功能一致,但 toRefs可以批量转换。
  • 语法如下:
<template>
<div class="person">
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2>性别:{{person.gender}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeGender">修改性别</button>
</div>
</template>

<script lang="ts" setup name="Person">
import {ref,reactive,toRefs,toRef} from 'vue'

// 数据
let person = reactive({name:'张三', age:18, gender:'男'})

// 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
let {name,gender} = toRefs(person)

// 通过toRef将person对象中的gender属性取出,且依然保持响应式的能力
let age = toRef(person,'age')

// 方法
function changeName(){
name.value += '~'
}
function changeAge(){
age.value += 1
}
function changeGender(){
gender.value = '女'
}
</script>

3.4 computed

P16:https://www.bilibili.com/video/BV1Za4y1r7KE?p=16

作用:根据已有数据计算出新数据(和Vue2中的computed作用一致)。

Vue3 学习笔记(Day2),前端,vue.js
<template>
<div class="person">
姓:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
全名:<span>{{fullName}}</span> <br>
<button @click="changeFullName">全名改为:li-si</button>
</div>
</template>

<script setup lang="ts" name="App">
import {ref,computed} from 'vue'

let firstName = ref('zhang')
let lastName = ref('san')

// 计算属性——只读取,不修改
/* let fullName = computed(()=>{
return firstName.value + '-' + lastName.value
}) */



// 计算属性——既读取又修改
let fullName = computed({
// 读取
get(){
return firstName.value + '-' + lastName.value
},
// 修改
set(val){
console.log('有人修改了fullName',val)
firstName.value = val.split('-')[0]
lastName.value = val.split('-')[1]
}
})

function changeFullName(){
fullName.value = 'li-si'
}
</script>

3.5 watch

P17:https://www.bilibili.com/video/BV1Za4y1r7KE?p=17

  • 作用:监视数据的变化(和 Vue2中的 watch作用一致)
  • 特点: Vue3中的 watch只能监视以下 四种数据
  1. ref定义的数据。
  2. reactive定义的数据。
  3. 函数返回一个值( getter函数)。
  4. 一个包含上述内容的数组。

我们在Vue3中使用watch的时候,通常会遇到以下几种情况:

情况一

监视ref定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。

<template>
<div class="person">
<h1>情况一:监视【ref】定义的【基本类型】数据</h1>
<h2>当前求和为:{{sum}}</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>
情况二

P18:https://www.bilibili.com/video/BV1Za4y1r7KE?p=18

监视ref定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视。

注意:

  • 若修改的是 ref定义的对象中的属性, newValueoldValue 都是新值,因为它们是同一个对象。
  • 若修改整个 ref定义的对象, newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
<template>
<div class="person">
<h1>情况二:监视【ref】定义的【对象类型】数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</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>
情况三

P19:https://www.bilibili.com/video/BV1Za4y1r7KE?p=19

监视reactive定义的【对象类型】数据,且默认开启了深度监视。

<template>
<div class="person">
<h1>情况三:监视【reactive】定义的【对象类型】数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改整个人</button>
<hr>
<h2>测试:{{obj.a.b.c}}</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>
情况四

P20:https://www.bilibili.com/video/BV1Za4y1r7KE?p=20

监视refreactive定义的【对象类型】数据中的某个属性,注意点如下:

  1. 若该属性值 不是【对象类型】,需要写成函数形式。
  2. 若该属性值 依然是【对象类型】,可直接编,也可写成函数,建议写成函数。

结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。

<template>
<div class="person">
<h1>情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</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>
情况五

P21:https://www.bilibili.com/video/BV1Za4y1r7KE?p=21

监视上述的多个数据

<template>
<div class="person">
<h1>情况五:监视上述的多个数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</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>
watchEffect

P22:https://www.bilibili.com/video/BV1Za4y1r7KE?p=22

官网:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。

watch对比watchEffect

  1. 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
  2. watch:要明确指出监视的数据
  3. watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。

示例代码:

<template>
<div class="person">
<h1>需求:水温达到50℃,或水位达到20cm,则联系服务器</h1>
<h2 id="demo">水温:{{temp}}</h2>
<h2>水位:{{height}}</h2>
<button @click="changePrice">水温+1</button>
<button @click="changeSum">水位+10</button>
</div>
</template>

<script lang="ts" setup name="Person">
import {ref,watch,watchEffect} from 'vue'
// 数据
let temp = ref(0)
let height = ref(0)

// 方法
function changePrice(){
temp.value += 10
}
function changeSum(){
height.value += 1
}

// 用watch实现,需要明确的指出要监视:temp、height
watch([temp,height],(value)=>{
// 从value中获取最新的temp值、height值
const [newTemp,newHeight] = value
// 室温达到50℃,或水位达到20cm,立刻联系服务器
if(newTemp >= 50 || newHeight >= 20){
console.log('联系服务器')
}
})

// 用watchEffect实现,不用
const stopWtach = watchEffect(()=>{
// 室温达到50℃,或水位达到20cm,立刻联系服务器
if(temp.value >= 50 || height.value >= 20){
console.log(document.getElementById('demo')?.innerText)
console.log('联系服务器')
}
// 水温达到100,或水位达到50,取消监视
if(temp.value === 100 || height.value === 50){
console.log('清理了')
stopWtach()
}
})
</script>

3.6 标签的 ref 属性

P23:https://www.bilibili.com/video/BV1Za4y1r7KE?p=23

作用:用于注册模板引用。

  • 用在普通 DOM标签上,获取的是 DOM节点。
  • 用在组件标签上,获取的是组件实例对象。

用在普通DOM标签上:

<template>
<div class="person">
<h1 ref="title1">尚硅谷</h1>
<h2 ref="title2">前端</h2>
<h3 ref="title3">Vue</h3>
<input type="text" ref="inpt"> <br><br>
<button @click="showLog">点我打印内容</button>
</div>
</template>

<script lang="ts" setup name="Person">
import {ref} from 'vue'

let title1 = ref()
let title2 = ref()
let title3 = ref()

function showLog(){
// 通过id获取元素
const t1 = document.getElementById('title1')
// 打印内容
console.log((t1 as HTMLElement).innerText)
console.log((<HTMLElement>t1).innerText)
console.log(t1?.innerText)

/************************************/

// 通过ref获取元素
console.log(title1.value)
console.log(title2.value)
console.log(title3.value)
}
</script>

用在组件标签上:

<!-- 父组件App.vue -->
<template>
<Person ref="ren"/>
<button @click="test">测试</button>
</template>

<script lang="ts" setup name="App">
import Person from './components/Person.vue'
import {ref} from 'vue'

let ren = ref()

function test(){
console.log(ren.value.name)
console.log(ren.value.age)
}
</script>


<!-- 子组件Person.vue中要使用defineExpose暴露内容 -->
<script lang="ts" setup name="Person">
import {ref,defineExpose} from 'vue'
// 数据
let name = ref('张三')
let age = ref(18)
/****************************/
/****************************/
// 使用defineExpose将组件中的数据交给外部
defineExpose({name,age})
</script>

3.7 props

回顾 TS 中的接口

P24:https://www.bilibili.com/video/BV1Za4y1r7KE?p=24

props 的使用

P25:https://www.bilibili.com/video/BV1Za4y1r7KE?p=25

type/index.ts中代码:

// 定义一个接口,限制每个Person对象的格式
export interface PersonInter {
id:string,
name:string,
age:number
}

// 定义一个自定义类型Persons
export type Persons = Array<PersonInter>

App.vue中代码:

<template>
<Person :list="persons"/>
</template>

<script lang="ts" setup name="App">
import Person from './components/Person.vue'
import {reactive} from 'vue'
import {type Persons} from './types'

let persons = reactive<Persons>([
{id:'e98219e12',name:'张三',age:18},
{id:'e98219e13',name:'李四',age:19},
{id:'e98219e14',name:'王五',age:20}
])
</script>

Person.vue中代码:

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

<script lang="ts" setup name="Person">
import {defineProps} from 'vue'
import {type PersonInter} from '@/types'

// 第一种写法:仅接收
// const props = defineProps(['list'])

// 第二种写法:接收+限制类型
// defineProps<{list:Persons}>()

// 第三种写法:接收+限制类型+指定默认值+限制必要性
let props = withDefaults(defineProps<{list?:Persons}>(),{
list:()=>[{id:'asdasg01',name:'小猪佩奇',age:18}]
})
console.log(props)
</script>

3.8 生命周期

P26:https://www.bilibili.com/video/BV1Za4y1r7KE?p=26

概念:Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue会在合适的时机,调用特定的函数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子

规律:生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。

P27:https://www.bilibili.com/video/BV1Za4y1r7KE?p=27

Vue2的生命周期

  • 创建阶段: beforeCreatecreated
  • 挂载阶段: beforeMountmounted
  • 更新阶段: beforeUpdateupdated
  • 销毁阶段: beforeDestroydestroyed

P28:https://www.bilibili.com/video/BV1Za4y1r7KE?p=28

Vue3的生命周期

  • 创建阶段: setup
  • 挂载阶段: onBeforeMountonMounted
  • 更新阶段: onBeforeUpdateonUpdated
  • 卸载阶段: onBeforeUnmountonUnmounted

常用的钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)

示例代码:

<template>
<div class="person">
<h2>当前求和为:{{ sum }}</h2>
<button @click="changeSum">点我sum+1</button>
</div>
</template>

<!-- vue3写法 -->
<script lang="ts" setup name="Person">
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'

// 数据
let sum = ref(0)
// 方法
function changeSum() {
sum.value += 1
}
console.log('setup')
// 生命周期钩子
onBeforeMount(()=>{
console.log('挂载之前')
})
onMounted(()=>{
console.log('挂载完毕')
})
onBeforeUpdate(()=>{
console.log('更新之前')
})
onUpdated(()=>{
console.log('更新完毕')
})
onBeforeUnmount(()=>{
console.log('卸载之前')
})
onUnmounted(()=>{
console.log('卸载完毕')
})
</script>

3.9 hook

P29:https://www.bilibili.com/video/BV1Za4y1r7KE?p=29

什么是hook?—— 本质是一个函数,把setup函数中使用的Composition API进行了封装,类似于vue2.x中的mixin

自定义hook的优势:复用代码, 让setup中的逻辑更清楚易懂。

示例代码:

  • useSum.ts中内容如下:
import {ref,onMounted} from 'vue'

export default function(){
let sum = ref(0)

const increment = ()=>{
sum.value += 1
}
const decrement = ()=>{
sum.value -= 1
}
onMounted(()=>{
increment()
})

//向外部暴露数据
return {sum,increment,decrement}
}
  • useDog.ts中内容如下:
import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'

export default function(){
let dogList = reactive<string[]>([])

// 方法
async function getDog(){
try {
// 发请求
let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')
// 维护数据
dogList.push(data.message)
} catch (error) {
// 处理错误
const err = <AxiosError>error
console.log(err.message)
}
}

// 挂载钩子
onMounted(()=>{
getDog()
})

//向外部暴露数据
return {dogList,getDog}
}
  • 组件中具体使用:
<template>
<h2>当前求和为:{{sum}}</h2>
<button @click="increment">点我+1</button>
<button @click="decrement">点我-1</button>
<hr>
<img v-for="(u,index) in dogList.urlList" :key="index" :src="(u as string)">
<span v-show="dogList.isLoading">加载中......</span><br>
<button @click="getDog">再来一只狗</button>
</template>

<script lang="ts">
import {defineComponent} from 'vue'

export default defineComponent({
name:'App',
})
</script>

<script setup lang="ts">
import useSum from './hooks/useSum'
import useDog from './hooks/useDog'

let {sum,increment,decrement} = useSum()
let {dogList,getDog} = useDog()
</script>

「结束」
Vue3 学习笔记(Day2),前端,vue.js

本文由 mdnice 多平台发布文章来源地址https://www.toymoban.com/news/detail-834734.html

到了这里,关于Vue3 学习笔记(Day2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Node.js学习 day2——预备知识】

    1、概念 Buffer是一个类似于数组的对象,用于表示固定长度的字节序列 Buffer本质是一段内存空间,专门用来处理二进制数据 2、特点 Buffer大小规定且无法调整 Buffer性能较好,可以直接对计算机内存进行操作 每个元素的大小为1字节(byte) 3、使用 创建Buffer(3种方式) 4、 B

    2024年01月25日
    浏览(47)
  • 前端HTML、CSS、JS、VUE3 汇总

    学习https://developer.mozilla.org/zh-CN/docs/Learn/CSS 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 使用VS Code运行前端代码 在VS Code上安装前端插件 正在更新中~ ✨ 提示:这里可以添加本文要记录的大概内容: 学习路线 知识定位 HTML基础 标签、表格、表单、

    2024年02月13日
    浏览(50)
  • Vue2+Vue3笔记(尚硅谷张天禹老师)day02

    声明:只是记录,初心是为了让页面更好看,会有错误,我并不是一个会记录的人,所以有点杂乱无章的感觉,我先花点时间把视频迅速过掉,再来整理这些杂乱无章的内容 按照视频来的话,这里应该有一些概念的东西,但我不管这些东西,我这里只做一个浅显得记录 组件:实现

    2024年02月10日
    浏览(45)
  • Vue2+Vue3笔记(尚硅谷张天禹老师)day01

    声明:只是记录,初心是为了让页面更好看,会有错误,我并不是一个会记录的人,所以有点杂乱无章的感觉,我先花点时间把视频迅速过掉,再来整理这些杂乱无章的内容 下载vue:Vue下载 下面两个是可选的,主要是我想让控制台干净点 vue_dev_tool安装 vue_dev_tool安装 : Vue 控制台出现

    2024年02月11日
    浏览(43)
  • 【前端vue升级】vue2+js+elementUI升级为vue3+ts+elementUI plus

    gogo code 是一个基于 AST (源代码的抽象语法结构树状表现形式)的 JavaScript/Typescript/HTML 代码转换工具,可以用它来构建一个代码转换程序来帮助自动化完成如框架升级、代码重构、多平台转换等工作。 当前 GoGoCode 支持解析和操作如下类型的代码: ○JavaScript(JSX) ○Typescript

    2024年02月12日
    浏览(53)
  • 【cs61b】学习笔记day2

    【cs61b】学习笔记day1 思考下面两个代码分别输出什么 从下图可以看出,a和b指向的同一个实例,而x和y是两个独立的 在计算机中,数字72和大写字母H都是以01001000来存储,那么java是如何区分他们的? 答: 以类型区分 在Java, 有8 八种基本类型: byte, short, int, long, float, double, b

    2024年02月13日
    浏览(35)
  • Vue3学习日记 Day4 —— pnpm,Eslint

    注:此课程需要有Git的基础才能学习 1、使用原因     1.1、速度快,远胜过yarn和npm     1.2、节省磁盘空间   2、使用方式     2.1、安装方式         npm install -g pnpm     2.2、创建项目         pnpm create vue     1、禁用Prettier插件(如果安装了) 2、安装Eslint插件,并配置保存

    2024年04月12日
    浏览(34)
  • Verilog语法-模块module[Day2学习笔记]

    1概述 Verilog HDL是一种用于数字逻辑电路设计的硬件描述语言,可用来进行数字电路的仿真验证、时序分析、逻辑综合。 用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型。 Verilog HDL既是一种 行为 描述语言,也是一种 结构 描述语言。 既可以用电路的功能描述,也可以用

    2024年02月15日
    浏览(41)
  • Vue学习笔记六--Vue3学习

    前提:node -v 查看node版本,需要在16.0及以上 创建命令 npm init vue@latest,先安装create-vue然后创建项目 然后执行npm run dev 提示 sh: vite: command not found,需要执行 npm i 重新安装依赖,之后再执行 npm run build ,再执行 npm run dev 可以正常运行了 更换npm淘宝源 首先打开命令提示符或者终端

    2024年01月20日
    浏览(46)
  • 【前端】vue.js从入门到项目实战笔记

    【前端目录贴】 文本插值中的代码被解释为节点的文本内容,而HTML插值中的代码则被渲染为视图节点。 3.1.1 文本插值 文本插值的方式:用 双大括号 将要绑定的变量、值、表达式括住就可以实现,Vue将会 获取计算后的值 ,并以 文本的形式 将其展示出来。 结果: 3.1.2 HTM

    2024年01月21日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包