
哈喽~大家好,
🥇个人主页:个人主页
🥈 系列专栏:【】
🥉与这篇相关的文章:
|---|---|
| | |
| | |
| | |
一、前言
1、什么是组件化
Vue组件化是一种将复杂的业务拆分为多个组件进行开发的方法,每个组件可以包含自己的HTML模板、JavaScript代码和CSS样式。这些组件可以独立开发和维护,并且可以复用在不同的项目中。
二、普通组件的注册使用
1、局部注册
在子组件使用export default 局部注册,然后在父组件使用 import 组件对象 from '.vue文件路径' 导入需要注册的组件。
javascript
// 导入需要注册的组件
import 组件对象 from '.vue文件路径'
import HmHeader from './components/HmHeader'
export default { // 局部注册
components: {
'组件名': 组件对象,
HmHeader:HmHeaer,
HmHeader
}
}
App.vue
javascript
<script setup>
import test02 from './components/test02.vue'
import test03 from './components/test03.vue'
import test04 from './components/test04.vue'
</script>
<template>
<test02 />
<test03 />
<test04 />
</template>
<script>
export default {
components: {
test02,
test03,
test04
}
}
</script>
test02.vue
javascript
<template>
<div class="hm-header">
我是hm-header
</div>
</template>
<script>
export default {
name: "test02"
}
</script>
<style>
.hm-header {
height: 100px;
line-height: 100px;
text-align: center;
font-size: 30px;
background-color: #8064a2;
color: white;
}
</style>
test03.vue
javascript
<template>
<div class="hm-main">
我是hm-main
</div>
</template>
<script>
export default {
name: "test03"
}
</script>
<style>
.hm-main {
height: 400px;
line-height: 400px;
text-align: center;
font-size: 30px;
background-color: #f79646;
color: white;
margin: 20px 0;
}
</style>
test04.vue
javascript
<template>
<div class="hm-footer">
我是hm-footer
</div>
</template>
<script>
export default {
name: "test04"
}
</script>
<style>
.hm-footer {
height: 100px;
line-height: 100px;
text-align: center;
font-size: 30px;
background-color: #4f81bd;
color: white;
}
</style>
效果

2、全局注册
全局注册的组件,在项目的任何组件中都能使用。他的语法是:Vue.component('组件名', 组件对象)。
进入到main.js中,代码为
javascript
import { createApp } from 'vue'
import App from './App.vue'
import test02 from './components/test02.vue'
// createApp(App).mount('#app')
const app = createApp(App)
app.component("test02", test02)
app.mount('#app')
然后效果是

但是在项目中,一般不使用全局注册,为什么?
全局注册,但并没有被使用的组件无法在生产打包时被自动移除(也叫"tree-shaking")。如果你全局注册了个组件,即使它并没有被实际使用,它仍然会出现在打包后的JS 文件中。
全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不大容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性。
三、组件通信
1、什么是组件通信?
组件通信,就是指组件与组件 之间的数据传递
-
组件的数据是独立的,无法直接访问其他组件的数据。
-
想使用其他组件的数据,就需要组件通信
组件与组件之间是需要存在交互的,否则完全没关系,组件的意义就很小了。
父组件通过 props 将数据传递给子组件
Prop 是你可以在组件上注册的一些自定义 attribute。
格式:
javascript
<my-componentVue title="标题"/>
<template>
<h3>单文件组件</h3>
<p>{{ title }}</p>
</template>
<script>
export default {
name:"MyComponent",
props:{
title:{
type:String,
default:""
}
}
}
</script>
在父组件里面,加上以下代码
javascript
<test02 :title="msg"></test02>
data() {
return {
msg: "active",
num: 10
}
},
components: {
test02,
// test03,
// test04
}
子组件加上
javascript
<p @click="dianji">{{ title }}</p>
export default {
name: "test02",
props: ['title'],
methods: {
dianji(){
console.log(this.title);
}
}
}
效果

Prop传递参数其实是没有类型限制的,以下类型都可以。
javascript
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function
}
温馨提示数据类型为数组或者对象的时候,默认值是需要返回工厂模式。
上面是父向子通信,那子向父通信是怎么样的呢?
子组件利用 $emit 通知父组件修改更新。

test05是父页面,test06是子页面,效果是在输入框输入文本,p标签里面自动更新(不采用v-model)。
test05
javascript
<template>
<p>Main</p>
<p>搜索内容为: {{ search }}</p>
<test06 @search="getSearch"/>
</template>
<script>
import test06 from './test06.vue';
export default {
data() {
return {
search: ""
}
},
methods:{
getSearch(data){
this.search = data
}
},
components: { test06 }
}
</script>
test06
javascript
<template>
<hr>
<p>搜索页面</p>
<input type="text" v-model="search">
</template>
<script>
export default {
name: "test06",
data() {
return {
search: ""
}
},
watch: {
search(newData, oldData){
this.$emit("search", newData)
}
}
}
</script>
效果

四、插槽
1、默认插槽
我们已经了解到,子组件可以接受 props,来接受父组件传递数据,它可以是任何类型的 JavaScript 值。
但是模板内容呢?在某些情况下,我们可能希望把模板片段传递给子组件,并让子组件在其自己的模板中渲染该片段。

<slot>元素是一个插槽出口,表示了父元素提供的插槽内容将在哪里被渲染。
思路:将SlotsBase里面的模板显示在子组件test07里面
SlotsBase
javascript
<template>
<p>插槽的基本知识</p>
<slot></slot>
</template>
javascript
<script setup>
import SlotBase from './SlotsBase.vue'
</script>
<template>
<SlotBase>
<div>
<h3>插槽的标题</h3>
<p>内容</p>
</div>
</SlotBase>
</template>
<script>
export default {
components: {
SlotBase
},
name: "test07"
}
</script>
效果

2、插槽默认值
默认槽:不带名称的插槽,或者名称是 default。
将父组件的SlotsBase2里的template的msg如果为空那么就显示子组件的默认值,不为空就显示父组件的默认值。
javascript
<SlotsBase2>
<template v-slot:header>
</template>
<template v-slot:main>
</template>
</SlotsBase2>
export default {
data() {
return {
msg: "我是test08的默认值",
// num: 10
}
},
components: {
SlotsBase2
},
name: "test08"
}
<template>
<h3>插槽</h3>
<slot name="header">我是SlotsBase2的默认值</slot>
<hr>
<slot name="main">插槽的main值</slot>
</template>
<script>
export default {
data() {
return{
}
},
}
效果

将msg加上,就显示了父组件的默认值。

3、具名插槽
有时,在一个组件中,包含多个插槽出口是很有用的。
模板如下
javascript
子级
<div class="container">
<header>
<!-- 标题内容放这里 -->
</header>
<main>
<!-- 主要内容放这里 -->
</main>
<footer>
<!-- 底部内容放这里 -->
</footer>
</div>
javascript
父级
<BaseLayout>
<template v-slot:header>
<!-- header 插槽的内容放这里 -->
</template>
</BaseLayout>
例子
test08
javascript
<script setup>
import SlotsBase2 from './SlotsBase2.vue'
</script>
<template>
<SlotsBase2>
<template v-slot:header>
</template>
<template v-slot:main>
</template>
</SlotsBase2>
</template>
<script>
export default {
components: {
SlotsBase2
},
name: "test08"
}
</script>
SlotsBase2
javascript
<template>
<h3>插槽</h3>
<slot name="header">插槽的默认值</slot>
<hr>
<slot name="main">插槽的main值</slot>
</template>
<script>
export default {
data() {
return{
}
},
}
</script>
效果

v-slot写起来太长,vue给我们提供一个简单写法 v-slot ---> #

不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!向着明天更好的自己前进吧!