个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
文章目录
- 前言
- ref
- props
- 生命周期
- hooks
前言
重拾 Vue3,查缺补漏、巩固基础。
ref
作用:用于注册模板引用。
- 用在普通 DOM 标签上,获取的是 DOM 节点
- 用在组件标签上,获取的是组件实例对象
App.vue
<template>
<h2 ref="title">你好</h2>
<button @click="showLog">App 测试</button>
<Person ref="ren"/>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Person from "./components/Person.vue";
const title = ref();
const ren = ref();
function showLog() {
console.log(title.value)
console.log(ren.value)
}
</script>
Person.vue
<template>
<div class="person">
<h2 ref="title">山东</h2>
<button @click="showLog">child 输出h2</button>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue"
const title = ref();
const a = ref(0);
const b = ref(1);
const c = ref(2);
function showLog() {
console.log(title.value);
}
// 仅暴露给父组件 a 和 b
defineExpose({ a, b });
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
props
使用 props 可以实现 父组件向子组件传递 数据。
index.ts(定义规则)
// person 接口
export interface PersonInter {
id: string,
name: string,
age: number
}
// export type Persons = Array<PersonInter>
export type Persons = PersonInter[]
App.vue(父组件)
<template>
<Person :list="personList" />
</template>
<script lang="ts" setup>
import Person from "./components/Person.vue";
import { reactive } from 'vue';
import { type Persons } from '@/types';
const personList = reactive<Persons>([
{ id: '1', name: '张三', age: 20 },
{ id: '2', name: '李四', age: 22 },
{ id: '3', name: '王五', age: 18 }
])
</script>
Person.vue(子组件)
<template>
<div class="person">
<ul v-for="person in list" :key="person.id">
<li>{{ person.name }} -- {{ person.age }}</li>
</ul>
</div>
</template>
<script lang="ts" setup>
import { defineProps, withDefaults } from "vue";
import { type Persons } from '@/types';
// 只接收 list
// defineProps(['list']);
// 接收 list + 限制类型
// defineProps<{ list: Persons }>();
// 接收 list + 限制类型 + 限制必要性 + 指定默认值
withDefaults(defineProps<{ list?: Persons }>(), {
list: () => [{id: '001', name: 'zhang', age: 20}]
})
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
生命周期
- 创建阶段:setup
- 挂载阶段:onBeforeMount、onMounted
- 更新阶段:onBeforeUpate、onUpdated
- 卸载阶段:onBeforeUnmount、onUnmounted
常用钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)
App.vue(父组件)
<template>
<div class="app">
<Person v-if=isShow />
<button @click="unMounted">卸载子组件</button>
</div>
</template>
<script lang="ts" setup>
import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref } from 'vue';
import Person from './components/Person.vue';
let isShow = ref(true);
function unMounted() {
isShow.value = false;
}
console.log('父--创建');
onBeforeMount(() => {
console.log('父--挂载前');
}),
onMounted(() => {
console.log('父--挂载完毕');
})
onBeforeUpdate(() => {
console.log('父--更新前');
})
onUpdated(() => {
console.log('父--更新完毕');
})
onBeforeUnmount(() => {
console.log('父--卸载前');
})
onUnmounted(() => {
console.log('父--卸载完毕');
})
</script>
<style scoped>
.app {
background-color: orange;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 10px 5px;
}
</style>
Person.vue(子组件)
<template>
<div class="person">
{{ sum }}
<button @click="add">求和</button>
</div>
</template>
<script lang="ts" setup>
import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref } from 'vue';
let sum = ref(0);
function add() {
sum.value += 1;
}
console.log('子--创建');
onBeforeMount(() => {
console.log('子--挂载前');
}),
onMounted(() => {
console.log('子--挂载完毕');
})
onBeforeUpdate(() => {
console.log('子--更新前');
})
onUpdated(() => {
console.log('子--更新完毕');
})
onBeforeUnmount(() => {
console.log('子--卸载前');
})
onUnmounted(() => {
console.log('子--卸载完毕');
})
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
hooks
hooks 主要用于在函数式组件中管理组件的状态和生命周期,下面我们进行一个示例。
Person.vue
<template>
<div class="person">
<h2>当前求和为:{{ sum }}</h2>
<h2>求和放大十倍:{{ bigSum }}</h2>
<button @click="add">+1</button>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch } from "vue";
import useSum from "../hooks/useSum";
const { sum, add, bigSum } = useSum();
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
useSum.ts
import { computed, onMounted, ref } from "vue";
export default function () {
let sum = ref(0);
function add() {
sum.value += 1;
}
onMounted(() => {
add();
});
let bigSum = computed(() => {
return sum.value * 10;
});
return { sum, add, bigSum };
}
参考资料:
https://www.bilibili.com/video/BV1Za4y1r7KE?spm_id_from=333.788.player.switch&vd_source=f839085517d2b7548b2939bfe214d466&p=29—