一、前言:
vue组件化开发是vue.js最强大的功能之一,采用这种开发模式,我们的代码会更加通用,也更方便后期的维护。
? ? 所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。?因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量。

二、组件化的开发思想(不同的功能封装到不同的组件)
- 标准:各个组件要能协调的组合到一块,就需要有统一的标准。有了标准规范写出来的代码?比较通用和维护。(例如:Web?components-->通过创建封装好功能的定制元素(简单理解为标签))
- 分治:把不同的功能封装到不同的组件中,每个组件都可以独立的开发生产,利于团队的协作开发。
- 重用:当一些组件不能使用和需要更换时,可以部分或者模块的更换,并且很多组件可以被回收。
- 组合:组件通过组合可以形成新的产品。
三、组件注册
1、全局组件注册语法(component?末尾不加s)

注意:
- 组件参数的data值必须是函数同时这个函数要求返回一个对象
- 组件模板必须是单个根元素(一个标签或者一个大盒子包含住)
- 组件模板的内容可以是模板字符串 ES6语法 (复杂内容模板字符串可复性更好)
 -
组件命名有什么规定
短横线?推荐(上文代码的命名方式)
驼峰命名(该组件使用
只能在字符串模板中
,不能在普通的标签模板中使用)
?2、局部组件注册语法(component?)
? ? ? ? 语法:
? ? ? ?实例:

? ? 注意:
- 局部组件只能在注册他的父组件中使用,
- 全局组件可以在任何地方使用


四、vue调试工具的用法
为了直观的体现各组件之间的层次关系,方便对组件数据进行调试,我们可以使用vue官方的调试工具。

?步骤:
- ① 克隆仓库
- ② 安装依赖包
- ③ 构建
- ④ 打开Chrome扩展页面
- ⑤ 选中开发者模式
- ⑥ 加载已解压的扩展,选择shells/chrome
候补-----
五、组件间的数据交互
1、父组件向子组件传值
<menu-item title="来自父组件的数据"></menu-item>
<menu-item :title="title"></menu-item>
? ?注意:传入的属性值可以是确定的状态,也可是动态绑定更新的数据。
Vue.component(‘menu-item', {
props: ['title'],
template: '<div>{{ title }}</div>'
})
? ?示例:

??
注意:
props属性名规则
- 在props中使用驼峰形式,模板中需要使用短横线的形式取代驼峰式 ?
- 字符串形式的模板中没有这个限制
Vue.component(‘menu-item', {
// 在 JavaScript 中是驼峰式的
props: [‘menuTitle'],
template: '<div>{{ menuTitle }}</div>'
})
<!– 在html中是短横线方式的 -->
<menu-item menu-title=“nihao"></menu-item>

?2、props属性值类型
- 字符串 String
- ?数值 Number
- ?布尔值 Boolean
- ?数组 Array
- ?对象 Object


?3、子组件向父组件传值
注:props可以实现对父级数据的操作,但是不符合规定,因为props是单向数据流。所以通过子组件自定义事件,父组件监听子组件事件的方式,进行子组件对父组件的传值。
<button v-on:click='$emit("enlarge-text") '>扩大父组件文本字体</button>
可在"enlarge-text"后携带参数,见下文
<menu-item v-on:enlarge-text='fontSize += 5'></menu-item>

?----------------------------------------------------------------------------------------------------------------------------
上文是进行了一个时间的传递,我们也可以同时将值进行传递(携带参数)

?注:$event是固定的,代表子组件传过来的值
4、兄弟之间的数据传递

?示例:
<body>
<div id="app">
<div>父组件</div>
<div>
<button @click="handle">销毁事件</button>
<!-- 点击销毁事件后,两个兄弟组件就不能实现传值操作了 -->
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script>
/*
兄弟组件之间数据传递
*/
// 提供事件中心
var hub = new Vue();
Vue.component("test-tom", {
data: function () {
return {
num: 0,
};
},
template: `
<div>
<div>TOM:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function () {
hub.$emit("jerry-event", 2);
},
},
mounted: function () {
// 监听事件
hub.$on("tom-event", (val) => {
// 使用箭头函数
this.num += val;
});
// 第一个val是对方事件传过来的值,第二个val是自己的值
},
});
Vue.component("test-jerry", {
data: function () {
return {
num: 0,
};
},
template: `
<div>
<div>JERRY:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function () {
// 触发兄弟组件的事件
hub.$emit("tom-event", 1);
},
},
mounted: function () {
// 监听事件
hub.$on("jerry-event", (val) => {
this.num += val;
});
},
});
var vm = new Vue({
el: "#app",
data: {},
methods: {
handle: function () {
hub.$off("tom-event");
hub.$off("jerry-event");
},
},
});
</script>
六、组件插槽
? ? ? ? ? ? 子组件需要提供slot标签
?
?
- ?具名插槽用法(根据name名称,对应匹配相应插槽)

? 应用场景:父组件对子组件的内容进行加工处理
? ? 在父组件中就可以决定子组件的数据是什么样子
<style>
.current {
color: orange;
}
</style>
<body>
<div id="app">
<fruit-list :list="list">
<template slot-scope="slotProps">
<strong v-if="slotProps.info.id==3" class="current"
>{{slotProps.info.name}}</strong
>
<!-- 在父组件中就可以决定子组件的数据是什么样子 -->
<span v-else>{{slotProps.info.name}}</span>
</template>
</fruit-list>
</div>
<script>
/*
作用域插槽
*/
Vue.component("fruit-list", {
props: ["list"],
template: `
<div>
<li :key='item.id' v-for='item in list'>
<slot :info='item'>{{item.name}}</slot>
</li>
</div>
`,
});
var vm = new Vue({
el: "#app",
data: {
list: [
{
id: 1,
name: "apple",
},
{
id: 2,
name: "orange",
},
{
id: 3,
name: "banana",
},
],
},
});
</script>
|