Vue第四节:组件化、组件生命周期

1. 组件

1)组件的概念

  • 组件是一个独立、可复用的vue实例,也是一段独立的UI视图。
  • 把需要复用的代码放到一个vue文件中,即为一个组件。
  • 组件由3部分组成:template,script,style。

让组件支持less/scss,style标签中 lang = "less/scss"

装包:npm i less less-loader -D 或者 npm i sass -D

  • 哪里需要用到这个文件,就在哪里导入,当作标签使用即可。

如下代码所示,此处的TestThree.vue就可以看成是一个组件,被App.vue文件引用。

使用时,我们把TestThree当作一个组件使用,即<TestThree>。

2)组件化

一种开发思想,把页面看作由一个个组件组合而成。可以化大为小、化繁为简,增加代码复用性。

例如:下面这个页面的代码如果都写在一起,内容就会比较混乱,不易理解,不好维护。可以考虑模块化的方式,拆分这个页面。

3)根组件 App.vue

根组件是整个应用的最上层,包裹所有普通小组件

4) 组件的使用

① 创建:新建.vue文件,编写组件代码

② 导入

import 组件对象 from '组件路径'

//例如

import MyPanel from '.components/MyPanel.vue'

**注意:**A组件内部导入的组件不能在B组件使用

③ 注册(仅限于全局组件):局部组件无需注册,全局组件需要在main.js中注册

④ 使用:把组件当作自定义标签使用(单双标签均可)

<组件名> </组件名>

<组件名/>

**组件的命名规范:**大驼峰法:MyPanel

示例:

App.vue

html 复制代码
<script setup lang="ts">
import MyHeader from './components/MyHeader.vue'
import MyMain from './components/MyMain.vue'
import MyFooter from './components/MyFooter.vue'
</script>

<template>
  <div class="top">
    <MyHeader />
    <MyMain />
    <MyFooter />
  </div>
</template>

<style scoped>
.top {
  width: 550px;
  height: 400px;
  background-color: lightblue;
}
</style>

MyHeader.vue

html 复制代码
<script lang="ts"></script>
<template>
  <div class="header">
    <h1>我是header组件</h1>
  </div>
</template>
<style>
.header {
  width: 500px;
  height: 50px;
  background-color: purple;
  color: white;
  margin: 20px 20px;
}
</style>

MyMain.vue

html 复制代码
<script lang="ts"></script>
<template>
  <div class="main">
    <h1>我是main组件</h1>
  </div>
</template>
<style>
.main {
  width: 500px;
  height: 200px;
  background-color: orange;
  color: white;
  margin: 20px 20px;
}
</style>

MyFooter.vue

html 复制代码
<script lang="ts"></script>
<template>
  <div class="footer">
    <h1>我是footer组件</h1>
  </div>
</template>
<style>
.footer {
  width: 500px;
  height: 100px;
  background-color: lightseagreen;
  color: white;
  margin: 20px 20px;
}
</style>

5)组件的全局注册

main.js 导入并全局注册

import MyButton from './components/MyButton.vue'

app.component('MyButton', MyButton)

注册 app.component('组件命名', 组件对象)

注意:在应用挂载前注册通用组件

示例:给刚刚的三个组件分别增加一个通用按钮

main.ts

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import MyButton from './components/MyButton.vue'

const app = createApp(App)
app.component('MyButton', MyButton)
app.mount('#app')

MyHeader.vue

html 复制代码
<script lang="ts"></script>
<template>
  <div class="header">
    我是header组件
    <MyButton />
  </div>
</template>
<style>
.header {
  font-size: larger;
  width: 500px;
  height: 50px;
  background-color: purple;
  color: white;
  margin: 20px 20px;
}
</style>

MyMain.vue

html 复制代码
<script lang="ts"></script>
<template>
  <div class="main">
    我是main组件
    <MyButton />
  </div>
</template>
<style>
.main {
  font-size: larger;
  width: 500px;
  height: 200px;
  background-color: orange;
  color: white;
  margin: 20px 20px;
}
</style>

MyFooter.vue

html 复制代码
<script lang="ts"></script>
<template>
  <div class="footer">
    我是footer组件
    <MyButton />
  </div>
</template>
<style>
.footer {
  font-size: larger;
  width: 500px;
  height: 100px;
  background-color: lightseagreen;
  color: white;
  margin: 20px 20px;
}
</style>

2. 组件生命周期

1)组件生命周期的概念:

vue组件从 创建 到 卸载 的全过程。

2)生命周期的四个阶段:

① 创建:创建响应式数据

② 挂载:渲染模板

③ 更新:修改数据,更新视图

④ 卸载:卸载组件

3)生命周期钩子:

  • 每个组件在创建时都会经历一些初始化步骤,比如设置好数据监听,编译模板,挂载到DOM树上,在数据改变时更新DOM等。在此过程中会自动运行一些函数,称为vue生命周期钩子。
  • 钩子的本质就是函数,只不过这些函数比较特殊,无需程序员调用,而是由vue3内部的执行机制调用
  • 钩子函数的意义:给了程序员在特定时机有添加自己代码的机会。比如组件创建完毕时,就想发送ajax请求,那么可以在创建的钩子函数中编写相关代码;还比如页面渲染完成后,立刻让输入框自动聚焦,那么可以在挂载后的钩子函数中编写相关代码。

生命周期钩子官网示意图:

vue3代码编写风格:① 选项式API(Option API) ② 组合式API(Composition API)

4)选项式API生命周期钩子

选项式API下,组件首次渲染,会执行5个钩子:

setup / beforeCreate / created / beforeMount / mounted

  • created:一进入组件就发请求
  • mounted:最早可操作原生DOM
  • unmounted:组件销毁,做优化工作

代码示例:(选项式API)

components/LifeCycle.vue

html 复制代码
<script>
export default {
// 提供响应式数据
data() {
return {
count: 0
}
},
// 提供⽅法/函数
 methods: {
 fn() {
 console.log('fn 函数执⾏了')
 }
 },
 setup() {
 console.log('0-setup')
 },
 // 创建阶段(第⼀阶段):Vue组件创建/出⽣阶段:

 // 创建前:此时⽆法访问 data 数据,也⽆法调⽤ methods ⽅法
 beforeCreate() {
 console.log('1-beforeCreate')
 // console.log(this.count) // undefined
 // console.log(this.fn) // undefined
 },
 // 创建后:此时可以访问 data 数据,也可以调⽤ methods ⽅法
 created() {
 console.log('2-created')
 // console.log(this.count) // 0
 // // console.log(this.fn)// 访问到函数
 // this.fn()

 // 开启定时器
 // 给当前组件实例新增了⼀个 timerId 属性,保存了当前定时器的 id 值
 this.timerId = setInterval(() => {
 console.log(this.count)
 }, 1000)
 },

 // 挂载阶段(第⼆阶段):模版渲染阶段

 // 挂载前:此时写在 template 下的标签还没有变成真实DOM,故⽽⽆法获取DOM
 beforeMount() {
 console.log('3-beforeMount')
 console.log(document.querySelector('p')) // null
 },

 // 挂载后:此时写在 template 下的标签已经变成了真实DOM,故⽽可以获取DOM(是最早可以
//作DOM的时机)
 mounted() {
 console.log('4-mounted')
 console.log(document.querySelector('p')) // <p>0</p>
 document.querySelector('p').style.color = 'red'
 },

 // 更新阶段(第三阶段):数据变了,组件重新渲染的过程

 // 更新前
 beforeUpdate() {
 console.log('5-beforeUpdate')
 // console.log(this.count)

 console.log(document.querySelector('p').innerText) // 旧内容(以前的内容)
 },

 // 更新后
 updated() {
 console.log('6-updated')
 // console.log(this.count)
 console.log(document.querySelector('p').innerText) // 新内容
 },

 // 卸载阶段(第四阶段):组件移除阶段
 beforeUnmount() {
 console.log('7-beforeUnmount')
 },

unmounted() {
console.log('8-mounted')
// 关闭定时器
clearInterval(this.timerId)
}
}
</script>
<template>
<div>
<p>{{ count }}</p>
<button @click="count++">+1</button>
</div>
</template>
<style scoped></style>

App.vue

javascript 复制代码
<script setup>
import { ref } from 'vue'
import LifeCycle from './components/LifeCycle.vue'
const isAlive = ref(true)
</script>
<template>
<life-cycle v-if="isAlive"/>
</template>

5)组合式API生命周期钩子

与vue2(选项式生命周期钩子对比)

|------|----------------------|--------------------------------|--------------------------|-----------------------------------|
| | 创建阶段 | 挂载阶段 | 更新阶段 | 销毁阶段 |
| vue2 | beforeCreate created | beforeMount mounted | beforeUpdate updated | beforeUnmount unmounted |
| vue3 | setup(网络请求) | onBeforeMount onMounted(操作DOM) | onBeforeUpdate onUpdated | onBeforeUnmount onUnmounted(清理工作) |

setup:一进入组件就发请求

onMounted:最早可操作原生DOM

onUnmounted:销毁组件,做优化工作

代码示例:

javascript 复制代码
<script setup>
import { onMounted, onUnmounted } from 'vue'
// 开启定时器
const timer = setInterval(() => {
console.log('Hello World')
}, 1000)
// 组件挂载后
onMounted(() => {
// console.log(document.querySelector('p'))
// 将 p 标签的字体颜⾊设置为 green
document.querySelector('p').style.color = 'green'
})
// 组件卸载后
onUnmounted(() => {
// 关闭定时器
clearInterval(timer)
})
</script>

6)案例:生命周期钩子的应用

javascript 复制代码
<script>
  import {onMounted, onUnmounted} from 'vue'

  //开启定时器
  const timer = setInterval(() => {
    console.log('hello world')
  },1000)

  //组件挂载后
  onMounted(()=>{
    //将p标签字体颜色设置为green
    document.querySelector('p').style.color = 'green'
  })

  //组件卸载后
  onUnmounted(()=>{
    //关闭定时器
    clearInterval(timer)
  })
</script>

7)在onMounted中操作DOM

html 复制代码
<script lang="ts" setup>
import { onMounted } from 'vue'

onMounted(() => {
  const input = document.querySelector('input')
  input.focus()
})
</script>
<template>
  <div class = "search-box">
    <input type = "text"/>
    <button>搜索</button>
  </div>
</template>
相关推荐
yuzhiboyouye2 小时前
web前端开发自测清单
前端
妮妮分享2 小时前
H5获取定位的方式是什么?
java·前端·javascript
weixin_439930642 小时前
前端js日期计算跨月导致的错误
开发语言·前端·javascript
niujiangyao2 小时前
vue v-for列表渲染, 无key、key为index 、 有唯一key三种情况下的对比。 列表有删除操作时的表现
vue.js
零一科技3 小时前
瑞吉外卖项目,前端源码(用户端)解析
前端
用户93051065822243 小时前
module federation,monorepo分不清楚?
前端·架构
柳安3 小时前
手写new操作符执行过程
前端·javascript
狗哥哥3 小时前
Vue 3 统一面包屑导航系统:从配置地狱到单一数据源
前端·vue.js·架构
可乐红烧西红柿3 小时前
tauri2+vue+vite实现基于webview视图渲染的桌面端开发
前端·前端框架