一.组件的定义和应用
1.全局组件
全局组件是指在任何页面中不必再单独引入组件并注册,直接在模板中使用组件名称就可以引用的组件。
全局组件注册方法一
先在src目录下新建一个globalComponents文件夹,再新建一个Header.vue的全局组件。
<template><div>全局组件Header</div>
</template><script>
export default {name: 'Header' //以大写字母开头的组件名称
}
</script>
进入main.js, 进行全局组件的注册,代码如下:
import { createApp } from 'vue'
import App from './App.vue'//引入全局组件Header,注意vite启动的项目引入Header的路径需要加后缀.vue
import Hearder from './globalComponents/Header.vue'//初始化实例
const app = createApp(App)// 使用component方法注册全局组件
app.component('Header', Hearder)//将实例挂载到#app标签上
app.mount('#app')
注册为全局组件后,进入App.vue, 引用全局组件,代码如下:
<template><div><Header></Header></div>
</template>
<script>
export default {}
</script>
启动项目,渲染效果如下,则渲染成功
全局组件注册方法二
在globalComents文件夹下新建Footer.vue
<template><div>全局组件Footer</div>
</template><script>
export default {name: 'Footer' //以大写字母开头的组件名称
}
</script>
注意,name要写上,否则后续不方便定义名称
与方法一不同的是,在globalComponents下新建index.js,用于注册全局组件
import Header from './Header.vue'
import Footer from './Footer.vue'//定义组件,将组件填入
const components = [Header, Footer]export default {install (app) {//利用数组的foreach循环,注册全局组件components.forEach(item => {app.component(item.name, item)})}
}
修改main.js,如下
import { createApp } from 'vue'
import App from './App.vue'
import GlobalComponents from './globalComponents'//引入自定义的全局组件库//初始化实例
const app = createApp(App)//使用实例的use方法,传入自定义全局组件库
app.use(GlobalComponents)//将实例挂载到#app标签上
app.mount('#app')
在App.vue脚本中,引入组件库的Header和Footer两个组件
<template><div><Header></Header><Footer></footer></div>
</template>
<script>
export default {}
</script>
运行一下,全局配置成功
2.局部组件
在src/components下写一个Test.vue
<template><div>局部组件</div>
</template><script>
export default {name: 'Test' //以大写字母开头的组件名称
}
</script>
在App.vue中引入Test
<template><div><Header></Header><Footer></footer><Test></Test></div>
</template>
<script>
// 引入Test组件
import Test from './components/Test.vue'
export default {components: {//注册Test组件Test}
}
</script>
注意,引入局部组件,其他的vue并不能直接使用该组件,上述< Test >可以用小写< test >
components: {//注册Test组件NickTest:Test}
也可以用驼峰命名,使用时则用中横线
<nick-test></nick-test>
3.动态组件
Vue提供了一个关键字is,通过v-bind:is=“组件名”,修改is的组件名从而达到更换,组件的注册方法上面已经讲过了,就不举例说明了。
二,组件间的值传递
1.父子组件通信
创建Son.vue组件
<template><div>我是子组件</div><!-- 将父组件传进来的值展示在模板上 --><div>count: {{ count }}</div>
</template><script>
export default {//定义传值的名称和类型,这里key需要和父组件传值的属性保持一致props: {count: String},setup (props) {//打印props属性下的count变量console.log("🚀 ~ file: Son.vue:14 ~ setup ~ props:", props)}
}
</script>
在父组件App.vue中引入子组件,使用并传入count值,注意子组件一定要定义props属性,否则setup函数无法获取父组件的传的值
//父组件传值的方法
<Son count="1"></Son>
//其余代码同上面引入组件一样,在此省略
控制台成功打印父组件传的值
2.子传父
上面属于正向传递,反过来,子组件传值给父组件属于逆向传递,此时需要用emit方法,将子组件的内容返回父组件,修改Son.vue如下
<template><div>我是子组件</div><!-- 将父组件传进来的值展示在模板上 --><div>count: {{ count }}</div>
</template><script>
export default {//定义传值的名称和类型,这里key需要和父组件传值的属性保持一致props: {count: String},setup (props,ctx) {//打印props属性下的count变量console.log("🚀 ~ file: Son.vue:15 ~ setup ~ props:", props)ctx.emit('callback', '子组件执行callback')}
}
</script>
App.vue中添加下面代码:
<Son @callback="callback" count="1"></Son>
并添加setup函数
setup () {//传递给子组件返回内容的回调函数const callback = (val) => {console.log("🚀 ~ file: App.vue:23 ~ callback ~ val:", val)}return {callback}}
上面代码可以看出,值是在子组件中传过来,并在父组件里使用的,但实际上还是父传子,
这里是父组件用@关键字,将callback方法传递给子组件,子组件使用该回调方法,最终实现子传父。
3.兄弟组件通信
没有上下极关系,需要跨组件通信的方式,就是兄弟组件通信,虽然兄弟组件没有上下级关系,但他们会有一个共同的父组件,那么就能通过父组件为媒介,帮助两个组件通信。
分别创建Son1.vue和Son2.vue
<template><div>我是子组件1</div><!-- 将父组件传进来的值展示在模板上 --><div>Son2传的值: {{ count2 }}</div><button @click="change">传值给Son2</button>
</template><script>
export default {//定义传值的名称和类型,这里key需要和父组件传值的属性保持一致props: {//父组件定义一个count2,传值给子组件1count2: Number},setup (props,ctx) {//打印props属性下的count变量console.log("🚀 ~ file: Son.vue:15 ~ setup ~ props:", props)const change = () => {ctx.emit('callback', 111)}return {change}}
}
</script>
<template><div>我是子组件2</div><!-- 将父组件传进来的值展示在模板上 --><div>Son1传的值: {{ count1 }}</div><button @click="change">传值给Son1</button>
</template><script>
export default {//定义传值的名称和类型,这里key需要和父组件传值的属性保持一致props: {//父组件定义一个count1,传值给子组件2count1: Number},setup (props,ctx) {//打印props属性下的count变量console.log("🚀 ~ file: Son.vue:15 ~ setup ~ props:", props)//触发父组件传递的方法const change = () => {ctx.emit('callback', 222)}return {change}}
}
</script>
下面修改App.vue
<template><div><Son1 @callback="change1" :count2="count2"/><hr><Son2 @callback="change2" :count1="count1"/></div>
</template>
<script>
import {ref} from 'vue'
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'
export default {components: {Son1,Son2},setup () {const count1 = ref(0)const count2 = ref(0)//传递给子组件返回内容的回调函数const change1 = (val) => {count1.value = val}const change2 = (val) => {count2.value = val}return {count1,count2,change1,change2}}}
</script>
简单来说,就是父组件和Son1通信,父组件和Son2通信,而通信的结果绑定在对方组件上,结果就显示为两个组件通信了。
这里还有种方式,就是事件总线(EventBus),简单介绍下,就是各组件将方法,参数都注册到一个池中,改池中的方法,参数其他组件都能获取,以此达到通信的目的,官方推荐第三发插件mitt,有兴趣的可以自行了解下。
4.祖孙组件通信
当祖孙组件中间套了很多层之后,用普通的父子通信会很难维护,代码也会很复杂,当他们想要通信时,可以用provide/inject来传值,祖先组件用provide定义值,孙子组件用inject获取值,代码逻辑和父子组件通信一样,大家可以自行了解。
总结
以上只是我对用vite构建vue3项目时,对于组件的一些理解和看法,比较浅显,希望对大家有所帮助。