前言
因为本文冗长,有一些是考虑对于小白上手所需技能,需要直接考虑组件拆分思路,建议直接进入
三、1) 组件拆分原则
六、一般的组件化内容
因为组件的知识点过多,本文是用于闲(摸 )暇(鱼 )时间写的,具体某个功能的用法,强烈建议翻阅其他文章或官网
一、 技术关键字
vue2.0
二、何为组件
1.组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
2.组件化
组件化,就是将可封装的样式、逻辑进行封装,保证同项目甚至同工程以至于整个公司前端架构的用户操作体感的统一,界面的感官一致,以及复杂逻辑高度抽象,减少错误。
组件化应⽤提⾼了开发效率,增强可维护性,更好的去解决软件上的⾼耦合、低内聚、⽆重⽤的三⼤代码问。
三、组件封装
1.组件封装原则
其实可以将每个组件视为大前端架构下的独立前端项目,亦或是微服务架构下的独立服务。其设计思路基本相通。
Ⅰ框架组件
框架组件:来源于《在前端架构-从入门到微前端》一书
壹)原子设计
①原子
即事物的基本组成部分。他是最小的单元,不能再往下细分,也就是基本的HTML标签,比如表单标签、输入、按钮。
②分子
即由原子聚合而成的粒子。在UI设计中,分子是由几个基本的HTML标签组成的简单组织,如移动端Web应用的底部导航栏。
③有机体
是由分子、原子或其他有机体组成的相对复杂的UI组分。它用于创建一些独立、可复用的内容,比如header、footer等。
④模板
顾名思义就是整合签名档元素,构建整体的布局,它将组件在这个布局的上下文中结合到一起,比如,一个博客包含header、footer及博客内容,三者可以构建一个基本外观。
⑤页面
用真实的内容(数据)展示出来的最终产品,它还能测试设计系统的弹性。
贰)维护与文档
这是一个架构级组件是否还“活着”的凭证
Ⅱ业务组件
壹)单一职责
即每个组件,应且只应去完成一个事情,页面说基于一个又一个小功能点进行的叠加。例如,table组件不应当参与分页逻辑,而应当只考虑渲染table功能,而搜索功能也应当与table组件与分页器脱离。确保每个组件的功能单一,职责明确。
贰)简化复杂应用
当一个页面逻辑过于复杂时,试着将逻辑进行拆解一个个小功能点。而页面本身,只关心怎么帮助组件进行通讯即可,不去干扰组件内部的逻辑,而组件内部的方法,“非请勿入”,只有组件明确邀请,才可以通过$refs进行操作
叁)灵活组合
当页面拆解之后,将会得到一大堆零件,此时可以思考,哪些零件是雷同的,可以进行合并,哪些组件的功能冗余,包含了一大堆职责,而哪些组件被父页面频繁访问内部属性?
肆)业务组件拆分总结
简简单单六个字:高内聚、低耦合
2.组件封装类型
本人按照个人习惯,将组件封装简单划分为两种UI与功能
《在前端架构-从入门到微前端》一书中
将组件分为三类:
基础UI组件:这是最小化的组件,他们不依赖于其他组件(博主注:可以参考elementUI源码、iview源码)
复合组件:由多个组件组成的组件,他们依赖于现有组件(博主注:参考ruoyi、花裤衩等源码)
业务组件:带有业务功能的大量重复使用的组件(博主注:参考公司自身封装的业务组件源码或项目页面组件代码)
1)UI式组件
顾名思义,UI式组件主要是对于项目内相同的样式进行封装,也是新手最易上手的封装思路,因为能够根据直观的可视化界面进行封装,上手较为简单。
但是UI一般每个项目都有些许差异,因此大部分UI组件为项目级或业务级组件,很少会被提升为框架架构即组件。
如下图,一般而言会将商品单封装成组件,进行样式统一管理。
2)逻辑功能性组件
封装逻辑功能型组件,一般是有一定经验的前端会考虑的封装思路,其主要思想不局限于UI的展示,一般还可能进行业务逻辑的封装,保证新人不会遗落或设置错误的前端逻辑
如上图,这是一个后台管理界面demo,一般新人处理翻页逻辑以及搜索重置逻辑时,功能点较多导致逻辑混乱,经常导致如下的问题:
- 翻页未触发更新接口
- 翻页后搜索项被重置,导致用户每次翻页后,需要重新输入搜索条件,否则二次翻页会回显全量数据
- 翻页设置的条数项目内不一致
- 用户输入搜索项,未点击搜索,点击翻页时数据条目错误(搜索项用户未确认,前端却错误地传给后端服务了)
- 如此等等 …
如此多的逻辑处理,即使是经验老道的前端去处理,每个页面都要写一次,也是繁琐。因此将整个搜索列表页进行封装,将翻页逻辑,搜索逻辑,显示逻辑等进行统一处理,保证了项目使用感受的统一性,也保证了新手进入项目时逻辑混乱导致项目崩盘
一般功能性组件因其思路较为健全,符合整体设计,较于UI组件会较多的提升为架构级别的组件应用,融入公司框架项目,方便后续开发使用
3.组件封装思路
组件如何去封装,如何去搭建是新人比较头疼的事情,以下为本人的设计思路,其实与组件封装原则是互通的
1)由上及下眼光
首先就是由上及下地去观察,先看项目,再看页面,再看局部,哪些样式是相似的,哪些逻辑是统一的
相似一般出现在for循环内,复制粘贴过程中
2)由下及上搭建
当发现到哪些内容可以封装时,要确保其已经是最小的单元,其所谓最小单元不是局限于样式,也是逻辑功能的最小单元,例如,列表table就可以是一个单独的组件,不用怕组件多,一般浏览器性能都可以支撑起来,当然,如果是对于性能有极致要求,就要平衡一下封装与效率了
3)积木式构建页面
当由下及上的搭建组件时,会得到一大堆分离的组件,当绘制页面时肯定不能将组件直接扔在页面上,因此,需要对于组件进行搭建,其搭建就如同积木一般,将所需的组件放在他应该所处的位置,并在多个组件的父页面上,进行组件间的通信,
切记:尽量不要把组件通信扔在某个单一组件内,因为其破坏了组件封装的原则,组件不能触碰他所未涉及的领域功能
如下图:此列表页面,组件通信逻辑应当在页面的index内,而不是table组件内
四、组件设计
上文均为组件化设计思维,主要焦点为如何进行组件化,组件拆分依据
下文主要是组件封装相关技术
1.数据传递
1)prop &&emit
propu与emit的组件通信是最为常见的使用方式,一般来说此类封装的组件通信能占50%以上的组件,或80%以上的业务组件封装。
Ⅰ.单向数据流
原文如下
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
需要注意的是,prop的通信方向仅可以父向子进行数据传递,emit仅进行子向父传递内容。
但是因vue2.0的数据监听方式以及浅拷贝问题,通过对象或数组是可以绕过检测,进行数据变更且不会抛出异常。此方法是绝对禁止的!
正常操作应当是子组件仅更新组件内部的相关数据,而不应该污染父页面的数据。对于数组或对象的数据的接收及处理,正确做法应当是深拷贝数组或对象后,扔进子组件的data内,可以在监听器内或生命周期内进行处理,此处不再赘述。
Ⅱ.父子传值
父子传值是较为常见的,即简单的prop &&emit应用,不做过多描述,以下为简单示例
壹)prop
子组件的prop绑定的值会接收父页面传来的值,当没有传值且未定义default时,将会默认undefined。
父页面:
<children :test="123456" />
子组件:
props:{
test:Number
}
以下为经验之谈
[Vue warn]: Invalid prop: type check failed for prop "error". Expected Number with value NaN, got String with value "error".
看到类似错误基本上就是数据类型出问题了
①类型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise //或任何其他构造函数
}
②验证
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
贰)emit
this. e m i t ( k e y , p a r a m s ) e m i t 传 递 的 数 据