Java登陆第三十八天——VUE3生命周期、钩子函数、组件拼接、组件传参(组件通信)

生命周期

之前在Servlet等也学习过生命周期,相同的,VUE组件也有生命周期。

VUE组件完全解析到浏览器,会经过如下过程。(简单理解)
image

  1. vue组件被实例化的过程,称为,组件实例化。

  2. 组件实例解析到浏览器中,称为,挂载。

  3. 组件实例从浏览器中删除,称为,卸载。

钩子函数

vue组件解析到浏览器的这个过程中,会触发一些函数。

这些函数也被称为钩子函数。(钩子函数需手动导入)

常用钩子函数如下:

钩子函数名 什么时候调用
onBeforeMount() 组件挂载之前
onMounted() 组件挂载之后
onBeforeUpdate() 组件更新之前
onUpdated() 组件更新之后
onBeforeUnmount() 组件卸载之前
onUnmounted() 组件卸载之后

组件实例内部储存的属性,一般是响应式数据,响应式数据一更新,这个组件实例也就更新了。

栗子

App.vue

<script setup>
//生命周期
import {ref, onMounted, onUpdated} from 'vue';

let msg = ref("hello");

onMounted(function () {
  console.log("----------组件挂载完毕-------------")
  console.log(msg.value)
});

onUpdated(function () {
  console.log("----------组件更新后-------------")
  console.log(msg.value)
});
</script>

<template>
  <input v-model="msg" type="text"><br>
  {{ msg }}
</template>

<style scoped>
</style>

效果展示
image

组件拼接

之前提及过SFC(Single-File Component,简称 SFC,单文件组件)。

在VUE中,就是编写一个个的组件,再将各个组件拼凑成完整的页面。

假设需求如下:
image

栗子(仅展示部分代码)

App.vue

<script setup>
//组件拼接,注意 避免标签和vue自带的标签或原生标签重名。
import headte from './components/head.vue'
import menuer from './components/menu.vue'
import conter from './components/content.vue'
</script>

<template>
  <headte class="headte"></headte>
  <menuer class="menuer"></menuer>
  <conter class="conter"></conter>
</template>

<style scoped>
  .headte{
    height: 80px;
    border: 1px solid red;
  }
  .menuer{
    width: 15%;
    height: 400px;
    border: 1px solid red;
    float: left;
  }
  .conter{
    width: 80%;
    height: 400px;
    border: 1px solid red;
    float: right;
  }
</style>

效果展示
image

此时,就完成了组件的拼接。

需求:点击左侧的菜单,菜单文本信息会显示到右侧。

这就需要组件传参完成。

组件传参(组件通信)

组件传参有三种:

  1. 父传参子

    • 父组件传参给子组件
  2. 子传父

    • 子组件传参给父组件
  3. 兄弟传参

    • 基于父传子和子传父完成的传参。

image

所以只演示兄弟传参。

提供了两个函数:defineEmits和defineProps

语法格式如下:

//返回值是一个常量对象,对象.事件名就可以执行该事件(子传父)
 const emits = defineEmits(['一个自定义事件','或多个自定义事件','...']);

//这个函数负责接收自定事件的返回值。(父传子)
 defineProps({自定事件返回值:返回值类型})

利用这一点,完善组件拼接的需。

:点击左侧的菜单,菜单文本信息会显示到右侧。

完善组件拼接的栗子

menu.vue。利用defineEmits函数完成子传父。

<script setup>
import {defineEmits} from 'vue'

const emits = defineEmits(['sendMenuMsg']);

function sendMenuMsg(msg) {//因为menu的父组件是App.vue。sendMenuMsg可在父组件里充当一个事件。
  emits('sendMenuMsg',msg)
}
</script>

<template>
  <ul>
    <li @click="sendMenuMsg('我的世界')">我的世界</li>
    <li @click="sendMenuMsg('英雄联盟')">英雄联盟</li>
    <li @click="sendMenuMsg('吃饭睡觉')">吃饭睡觉</li>
  </ul>
</template>

<style scoped>
</style>

App.vue。是menu.vue的父组件,再转发给子组件content.vue。

<script setup>
//组件拼接,注意 避免标签和vue自带的标签或原生标签重名。
import {ref} from 'vue'
import headte from './components/head.vue'
import menuer from './components/menu.vue'
import conter from './components/content.vue'

let msg = ref("");

//事件就是menu.vue定义的sendMenuMsg。把数据传递给msg。
function getMenuMsg(data) {
  msg.value = data
}

</script>

<template>
  <headte class="headte"></headte>
  <!--子传父,通过事件-->
  <menuer class="menuer" @sendMenuMsg="getMenuMsg"></menuer>
  <!--父传子,通过属性-->
  <conter class="conter" v-bind:msg="msg"></conter>
</template>

<style scoped>
.headte {
  height: 80px;
  border: 1px solid red;
}

.menuer {
  width: 15%;
  height: 400px;
  border: 1px solid red;
  float: left;
}

.conter {
  width: 80%;
  height: 400px;
  border: 1px solid red;
  float: right;
}
</style>

content.vue.vue

<script setup>
import {defineProps} from 'vue'
defineProps({
  msg:String
})
</script>
<template>
  <h3>用户点击了:{{msg}}</h3>
</template>

<style scoped>
</style>

效果展示
image

不难发现,太复杂啦!!!在后面的学习中,会学习Pinia代替原生的方式完成组件通信。

posted @ 2024-04-05 17:34  rowbed  阅读(7)  评论(0编辑  收藏  举报