关于程序员:Vue3-学习笔记Day2

38次阅读

共计 17937 个字符,预计需要花费 45 分钟才能阅读完成。

写在后面

本文为尚硅谷禹神 Vue3 教程的学习笔记。本着本人学习、分享别人的态度,分享学习笔记,心愿能对大家有所帮忙。举荐先按程序浏览往期内容:\
1. Vue3 学习笔记(Day1)


::: block-1

目录

  • 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,不便于保护和复用。

:::: column
::: column-left 44.5%

:::
::: column-right 55.5%

:::
::::

Composition API 的劣势:

能够用函数的形式,更加优雅的组织代码,让相干性能的代码更加有序的组织在一起。

:::: column
::: column-left 48.5%

:::
::: column-right 51.5%

:::
::::

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() ]
    })
  3. 第三步:<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)。
  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 作用统一)。

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

<center>完结 </center>

本文由 mdnice 多平台公布

正文完
 0