一、组件的基本概念
1.组件是什么?
可复用的vue实例,封装标签,样式,js
2.什么时候封装组件
遇到重复的标签,可以复用的时候
3.组件的好处
各自独立,互不影响
二、组件使用
1.全局组件
①创建组件 - 文件名.vue
②引入组件 - 引入组件: import 组件对象 from "vue文件路径"
③全局使用 - 注册组件
语法:Vue.component("组件名",组件对象)
Vue.component("PannelG", Pannel);
2.局部组件
①创建组件 - 文件名.vue
②引入组件 - 引入组件: import 组件对象 from "vue文件路径"
③局部使用 - 注册组件
语法:export default {
components: {
"组件名":Pannel
}
};
export default {
components: {
PannelL: Pannel,
},
};
3.使用
注意:组件名当作标签使用
<template>
<div id="app">
<h3>案例:折叠面板</h3>
<!-- 组件名当作标签使用 -->
<PannelG></PannelG>
<PannelL></PannelL>
</div>
</template>
三、scoped作用过程
1.给style上添加scoped,vue组件内样式,只针对当前组件内标签生效
2.scoped原理和过程:scoped会自动给标签添加data-v-hash值属性,所有选择都带属性选择
四、组件通信
1.父向子传值
目标:父(App.vue)->子(MyProduct.vue) 分别传值进入
需求:每次组件显示不同的数据信息
步骤:
1.子组件 - props - 变量(准备接收)
2.父组件 - 传值进去
子文件:MyProduct.vue
<template>
<div class="my-product">
<h3>标题:{{ title }}</h3>
<p>价格:{{ price}}元</p>
<p>{{intro }}</p>
</div>
</template>
<script>
export default {
props: ["title", "price", "intro"],
};
</script>
父文件:App.vue
<template>
<div>
<!--
目标:父(App.vue)->子(MyProduct.vue) 分别传值进入
需求:每次组件显示不同的数据信息
步骤:
1.子组件 - props - 变量(准备接收)
2.父组件 - 传值进去
-->
<Product
title="好吃的口水鸡"
price="50"
intro="开业大酬宾,全场八折"
></Product>
<Product title="冰糖葫芦" price="10" intro="新鲜出炉"></Product>
<Product title="北京烤鸭" price="20" :intro="str"></Product>
</div>
</template>
<script>
// 1.创建组件(.vue文件)
// 2.引入组件
import Product from "./components/2-MyProduct";
export default {
// 3.注册组件
components: {
// Product:Product //组件名和组件对象同名,可以简写
Product,
},
data() {
return {
str: "百年老店",
};
},
};
</script>
2.父向子传值--配合循环
父文件:App.vue
<template>
<div>
<MyProduct v-for="obj in list" :key="obj.id" :title="obj.proname" :price="obj.proprice" :intro="obj.info"></MyProduct>
</div>
</template>
<script>
// 1.引入组件
import MyProduct from "./components/2-MyProduct.vue";
export default {
components: {
MyProduct,
},
data() {
return {
list: [
{
id: 1,
proname: "超级好吃的棒棒糖",
proprice: 18.8,
info: "开业大酬宾, 全场8折",
},
{
id: 2,
proname: "超级好吃的大鸡腿",
proprice: 34.2,
info: "好吃不腻, 快来买啊",
},
{
id: 3,
proname: "超级无敌的冰激凌",
proprice: 14.2,
info: "炎热的夏天, 来个冰激凌了",
},
],
};
},
};
</script>
<style lang="scss" scoped></style>
3-组件通信-单项数据流
①子组件改父组件传入的数据不通知父亲,数据不一致性
②vue规定props"本身" 只读的(不允许重新赋值)
子文件(MyProduct_sub.vue)
<template>
<div class="my-product">
<h3>标题:{{ title }}</h3>
<p>价格:{{ price }}元</p>
<p>{{ intro }}</p>
<button @click="subFn">砍一刀</button>
</div>
</template>
<script>
export default {
props: ["title", "price", "intro"],
methods: {
subFn() {
/*
错误:
1.子组件改父组件传入的数据不通知父亲,数据不一致性
2.vue规定props"本身" 只读的(不允许重新赋值)
*/
// this.price--;
},
},
};
</script>
4.组件通信-子传父
①在子文件加入索引变量
export default {
props: ["index", "title", "price", "intro"],
};
②父文件给索引变量赋值--用于区分是哪个子组件
③父组件内, 绑定自定义事件和事件处理函数 语法: @自定义事件名="父methods里函数名"
④子组件内, 恰当的时机, 触发父给我绑定的自定义事件, 导致父methods里事件处理函数执行
语法:this.$emit('事件名', 事件处理函数传参)
⑤定义自定义事件时传入的参数优先级大于子组件中传入参数的优先级
5.跨组件传值
目标:将MyProduct.vue的值传入list.vue
①在components/list.vue
<template>
<ul class="my-product">
<li v-for="(item, index) in arr" :key="index">
<span>{{ item.proname }}</span>
<span>{{ item.proprice }}</span>
</li>
</ul>
</template>
<script>
export default {
props: ["arr"],
}
};
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
②在App.vue中引入list.vue并给arr数组赋值
③在src创建/EventBus/index.js
import Vue from "vue";
//导出空白的vue对象
export default new Vue();
④在list.vue和myProduct.vue引入vue对象
import EventBus from '../EventBus';
⑤在list.vue监听事件
目标:跨组件传值
1.引入空白vue对象(EventBus)
2.接收方 - $on监听事件
⑥在 myProduct.vue触发事件