vue如何编写可复用的组件步骤,vuejs 组件与复用
本文主要介绍Vue组件的复用和扩展。对vue感兴趣的同学可以参考一下。
目录
是否需要扩展组件概述slot JavaScript工具功能扩展组件组合的几种模式APImixin高级组件无渲染组件模板扩展
概述
软件编程的一个重要原则是D.R.Y(不要重复自己),就是尽可能的重用代码和逻辑,减少重复。组件扩展可以避免代码重复,更易于快速开发和维护。那么,扩展Vue组件的最好方法是什么呢?
Vue提供了许多API和模式来支持组件重用和扩展,您可以根据自己的目的和偏好进行选择。
本文介绍几种常见的方法和模式,希望对你有所帮助。
扩展组件是否必要
要知道,所有的组件扩展方法都会增加复杂度,额外的代码,有时还会增加性能消耗。
因此,在决定扩展组件之前,最好看看是否有其他更简单的设计模式可以完成目标。
以下组件设计模式通常足以替换扩展组件:
道具协调模板逻辑
插槽插槽
JavaScript工具函数
道具协调模板逻辑
最简单的方法就是通过道具结合模板条件渲染实现组件的多功能。
例如,通过类型属性:MyVersatileComponent.vue
模板
div class=wrapper
div v-if=type===a ./div
div v-else-if=type===b ./div
!等等等等
/div
/模板
脚本
导出默认值{
道具:{ type: String },
.
}
/脚本
使用组件时,通过传递不同的类型值可以获得不同的结果。
//*ParentComponent.vue*
模板
MyVersatileComponent type=a /
MyVersatileComponent type=b /
/模板
如果出现以下两种情况,说明该模式不适用,或者用法不正确:
组件模式将状态和逻辑分解成原子部分,从而使应用程序具有可扩展性。如果组件中有大量的条件判断,可读性和可维护性就会变差。
Props和模板逻辑旨在使组件动态化,但也存在运行时资源消耗。如果您使用这种机制来解决运行时的代码合成问题,它就是一种反模式。
slot(插槽)
另一种避免组件扩展的方法是使用插槽,即让父组件在子组件中设置自定义内容。
//*MyVersatileComponent.vue*
模板
div class=wrapper
H3通用标记/div
插槽/
/div
/模板
//*ParentComponent.vue*
模板
MyVersatileComponent组件
h4插入插槽/h4
/MyVersatileComponent
/模板
渲染结果:
div class=wrapper
H3通用标记/div
h4插入插槽/h4
/div
这种模式有一个潜在的约束,因为槽中的元素从属于父组件的上下文,所以分离逻辑和状态可能不自然。作用域slot将更加灵活,这将在后面不呈现组件的部分中提到。
JavaScript 工具函数
如果只需要复用组件间的独立函数,只需要提取这些JavaScript模块,根本不需要使用组件扩展模式。
JavaScript的模块系统是一种非常灵活和健壮的代码共享方式,所以你应该尽可能地依赖它。MyUtilityFunction.js
导出默认函数(){
.
}
我的组件. vue
从“”导入MyUtilityFunction。/MyUtilityFunction ;
导出默认值{
方法:{
我的效用函数
}
}
扩展组件的几种模式
如果你考虑过以上简单的模型,但是这些模型不够灵活,无法满足需求。然后可以考虑扩展组件。
有四种最流行的方法来扩展Vue组件:
合成函数
混入类
高阶分量
没有渲染组件
每种方式都有其优缺点,根据使用场景也有或多或少的适用部分。
Composition API
组件间共享状态和逻辑的最新方案是组合API。这是Vue 3推出的API,在Vue 2中也可以作为插件使用。
与以前在组件定义配置对象中声明数据、计算、方法和其他属性的方式不同,组合API通过设置函数来声明和返回这些配置。
例如,计数器组件是以Vue 2配置属性的方式声明的:Counter.vue
模板
按钮@click=增量
计数为:{{ count }},双精度为:{{ double }}
/按钮
模板
脚本
导出默认值{
数据:()=({
计数:0
}),
方法:{
增量(){
this.count
}
},
计算值:{
double () {
返回this . count * 2;
}
}
}
/脚本
用Composition API重构这个组件有一模一样的功能:Counter.vue
模板!-如上-模板
脚本
从“vue”导入{ reactive,computed };
导出默认值{
setup() {
恒定状态=反应({
计数:0,
double:computed(()=state . count * 2)
});
函数增量(){
状态.计数
}
返回{
数数,
双倍,
增量
}
}
}
/脚本
用Composition API声明组件的主要好处之一是逻辑重用和提取变得非常容易。
进一步重构,将计数器的功能移到JavaScript模块useCounter.js: usecounter.js中。
从“vue”导入{ reactive,computed };
导出默认函数{
恒定状态=反应({
计数:0,
double:computed(()=state . count * 2)
});
函数增量(){
状态.计数
}
返回{
数数,
双倍,
增量
}
}
现在,计数器函数可以通过setup函数无缝地引入到任何Vue组件中:MyComponent.vue
模板!-如上-/模板
脚本
从导入useCounter。/use counter ;
导出默认值{
setup() {
const { count,double,increment }=use counter();
返回{
数数,
双倍,
增量
}
}
}
/脚本
组合功能使功能模块化、可重用,是组件扩展最直接、成本最低的方式。
组合API的缺点
Composition API的缺点其实不算什么。3354可能看起来有点冗长,新用法对一些Vue开发者来说有点陌生。
关于组合API优缺点的讨论,推荐阅读:何时使用新的vue组合API(以及何时不使用)
mixin
如果你还在用Vue 2,或者只是喜欢通过配置对象来定义组件功能,可以使用mixin模式。Mixin将公共逻辑和状态提取到单独的对象中,并使用mixin将它们与组件的内部定义对象合并。
让我们继续使用前面的Counter组件示例,将常见的逻辑和状态放入CounterMixin.js模块中。CounterMixin.js
导出默认值{
数据:()=({
计数:0
}),
方法:{
增量(){
this.count
}
},
计算值:{
double () {
返回this . count * 2;
}
}
}
使用mixins也很简单,只需要导入相应的模块,在mixins数组中添加变量即可。当组件初始化时,mixin对象将与组件的内部定义对象合并。我的组件. vue
从导入计数器。/counter mixin ;
导出默认值{
米辛:[反米辛],
方法:{
减量(){
this . count-;
}
}
}
选项合并
组件中的选项和mixin冲突怎么办?
比如给一个组件定义一个内置的增量方法,哪个优先级更高?我的组件. vue
从导入计数器。/counter mixin ;
导出默认值{
米辛:[反米辛],
方法:{
//内置的increment `方法会覆盖mixin的增量吗?
增量(){.}
}
}
这是谈论Vue合并策略的时候了。Vue有一系列的规则来决定如何处理同名的选项。
通常,组件附带的选项会覆盖mixin提供的选项。但是也有例外,比如同类型的生命周期挂钩。不是直接覆盖它们,而是全部放入一个数组,按顺序执行。
您还可以通过自定义合并策略来更改默认行为。
mixin的缺点
作为一种扩展组件的模式,mixin非常适合简单的场景。一旦规模扩大,问题就来了。不仅要注意命名冲突(尤其是第三方mixin),而且很难搞清楚某个函数是从哪里来的,也很难定位问题。
高阶组件
高阶分量(HOC)是从React借来的概念,Vue也可以用。
为了理解这个概念,让我们抛开组件,看看两个简单的JavaScript函数,increment和double。
函数增量(x) {
返回x;
}
双(x)函数{
返回x * 2;
}
假设我们想给这两个函数都添加一个函数:在控制台中输出结果。
所以我们可以利用高阶函数模式创建一个新的addLogging函数,接受函数作为参数,返回一个有新函数的函数。
函数添加日志记录(fn) {
返回函数(x) {
const结果=fn(x);
console.log(结果为: ,result);
返回结果;
};
}
const incrementwithloging=add logging(increment);
const doublewithloging=add logging(double);
组件如何利用这种模式?类似地,我们创建一个高级组件来呈现计数器组件,并添加一个减量方法作为实例属性。
实际代码相当复杂,所以这里只给出伪代码作为说明:
从导入计数器。/Counter ;
//伪代码
const CounterWithDecrement=({
渲染(createElement) {
常量选项={
减量(){
this . count-;
}
}
返回createElement(计数器,选项);
}
});
HOC模式比mixin更简洁,可扩展性更强,但代价是增加了一个包组件,实现起来也需要技巧。
无渲染组件
如果您需要在多个组件上使用相同的逻辑和状态,但以不同的方式显示,那么您可以考虑非呈现组件模式。
该模式需要两种组件:声明逻辑和状态的逻辑组件,以及显示数据的表示组件。
逻辑模块
让我们回到计数器的例子。假设我们需要在多个地方重用这个组件,但是以不同的方式显示它。
创建一个CounterRenderless.js来定义逻辑组件,包括逻辑和状态,但不包括模板。相反,通过render函数声明作用域槽。
作用域slot向父组件公开了三个属性:状态计数、方法增量和计算属性double。CounterRenderless.js
导出默认值{
数据:()=({
计数:0
}),
方法:{
增量(){
this.count
}
},
计算值:{
double () {
返回this . count * 2;
}
},
render() {
归还这个。$scopedSlots.default({
伯爵:这个.伯爵,
double: this.double,
increment: this.toggleState,
})
}
}
这里的作用域槽是这个模式中逻辑组件的关键。
显示组件
接下来,作为非呈现组件的用户,显示组件提供特定的显示模式。
的所有元素标记都包含在作用域槽中。正如您所看到的,这些属性在使用中与直接放在逻辑组件中的模板没有什么不同。CounterWithButton.vue
模板
反渲染slot-scope=“{ count,double,increment }”
divCount是:{{ count }}/div
divDouble是:{{ double }}/div
按钮@click=increment 增量/按钮
/无反渲染
/模板
脚本
从导入无反渲染器。/count renderless ;
导出默认值{
组件:{
无反渲染
}
}
/脚本
无组件渲染模式非常灵活且易于理解。但是没有前面的方法普遍,应用场景可能只有一个,就是用来开发组件库。
模板扩展
上面的API或者设计模式有一个限制,就是不能扩展组件的模板。Vue有办法重用逻辑和状态,但是对模板标签无能为力。
比较hack的一种方法是使用HTML预处理程序,比如Pug,来处理模板扩展。
第一步是创建一个基本模板。包含公共页面元素的pug文件。还包括一个块输入作为模板扩展的占位符。
BaseTemplate.pug
分区包装器
h3 {{ myCommonProp }}!-通用标记-
阻止输入!-扩展标记出口-
要扩展这个模板,需要安装Vue Loader的Pug插件。然后您可以引入基本模板并用块输入语法替换占位符:MyComponent.vue
模板语言=帕格
扩展BaseTemplate.pug
块输入
h4 {{ myLocalProp }}!-包含在基本模板中-
/模板
起初,你可能会认为它和slot是同一个概念,但有一点不同。这里的基本模板不属于任何单独的组件。它在编译时与当前组件合并,而不是像slot一样在运行时被替换。
以上是复用和扩展Vue组件方式的详细说明。更多关于Vue组件复用和扩展的信息,请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。