Vue3+ts(day05:ref、props、生命周期、hook)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes

觉得有帮助的同学,可以点心心支持一下哈(笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】,记录一下学习笔记,用于自己复盘,有需要学习的可以去b站学习原版视频)

一、标签的 ref 属性

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

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

子组件:

<template>
  <div class="person">
    <h1>尚硅谷</h1>
    <h2 ref="title2">前端</h2>
    <h3>Vue</h3>
    <button @click="showLog">点我输出这个元素</button>
  </div>
</template>

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

<style>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0px 5px;
}
</style>

父组件:

<!-- 父组件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)
  // console.log(ren.value.name)
  // console.log(ren.value.age)
}
</script>

二、props

父组件传递值给子组件

// 定义一个接口,限制每个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>

三、生命周期

解析流程:index.html=>main.ts=>person(子组件)=>app(父组件) 【先解析子组件再父组件】

  • 概念:Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue会在合适的时机,调用特定的函数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子
  • 规律:生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。

Vue2的生命周期

创建阶段:beforeCreate、created挂载阶段:beforeMount、mounted更新阶段:beforeUpdate、updated销毁阶段:beforeDestroy、destroyed

  • 实例代码:

子组件

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

<script>
export default {
  /* eslint-disable */
  name: 'Person',
  // 数据
  data() {
    return {
      sum: 1
    }
  },
  // 方法
  methods: {
    add() {
      this.sum += 1
    }
  },
  // 创建前
  beforeCreate() {
    console.log('创建前')
  },
  // 创建完毕
  created() {
    console.log('创建完毕')
  },
  // 挂载前
  beforeMount() {
    console.log('挂载前')
  },
  // 挂载完毕
  mounted() {
    console.log('挂载完毕')
  },
  // 更新前
  beforeUpdate() {
    console.log('更新前')
  },
  // 更新完毕
  updated() {
    console.log('更新完毕')
  },
  // 销毁前
  beforeDestroy() {
    console.log('销毁前')
  },
  // 销毁完毕
  destroyed() {
    console.log('销毁完毕')
  }
}
</script>

父组件:

<template>
  <div id="app"><Person v-if="isshow" /></div>
</template>

<script>
import Person from './components/Person.vue'

export default {
  name: 'App',
  components: {
    Person
  },
  data () {
    return {
      isshow: true
    }
  }
}
</script>

Vue3的生命周期

创建阶段:setup挂载阶段:onBeforeMount、onMounted更新阶段:onBeforeUpdate、onUpdated卸载阶段:onBeforeUnmount、onUnmounted

  • 常用的钩子: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>

父组件:

<template>
  <Person v-if="isShow" />
</template>

<script lang="ts" setup name="App">
import Person from './components/Person.vue'
import { ref, onMounted } from 'vue'
let isShow = ref(true)
onMounted(() => {
  console.log('父---挂载完毕')
})
</script>

四、自定义hook

  • 什么是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" :key="index" :src="u" />
  <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>
<style>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0px 5px;
}
</style>

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值