我正在参加跨端技术专题征文活动,详情查看:juejin.cn/post/710123… 。
一、什么是组件
在前端开发中,组件可谓是非常有用的工具。
什么是组件,组件就是一个封装起来的,单独且可复用的功能模块,英文叫做:Component。
在 uni-app
中有很多内置的基础组件和扩展组件,开发者可以根据需要自行选择,虽然这些组件可以满足日常开发中大部分业务需求了,但是实际上仍然有部分需求需要个性化,因为每个项目是不一样的。
当遇到有些组件没有时,我们就可以自己去封装,当然,DCloud
插件市场中的插件也足够丰富,使用之前可以先查找是否有符合自己需求的插件,DCloud 插件市场传送门,点击直达。
使用组件的优势:
- 可以将组件进行任意次数的复用。
- 合理的划分组件,有助于提高应用性能。
- 代码更加方便组织和管理,并且扩展性也更强,便于多人协同开发。
- 组件化开发能大幅度提高应用开发效率、测试性、复用性等。
二、如何封装组件
下面以封装一个卡片为例,来体验如何封装组件。
1. 创建组件目录
首先在项目目录下新建一个 components
目录,这个目录用来存放组件。
然后可以进一步细分目录,每一个组件一个单独的目录,比如这里新建一个 my-card
目录。
2. 新建组件文件
在组件目录下新建一个 vue
文件,组件名称最好和目录名称一致(符合 easycom
规范引入)。
3. 开发组件
在组件中简单实现一个卡片:
my-card.vue
:
<template>
<view class="card-wrapper">{{content}}</view>
</template>
<script>
export default {
name:"myCard",
data() {
return {
content: "这是组件内容"
};
}
}
</script>
<style>
.card-wrapper {
height: 150px;
padding: 10px;
border-radius: 10px;
background-color: red;
}
</style>
这个文件中,有两点需要注意:
(1)结构部分的根节点,也就是最外层元素,必须为 template
标签,而且这个 template
标签里面只能出现一个 view
,否则会造成错误。
比如:
<template>
<view>这是第一个view</view>
<view>这是第二个view</view>
</template>
则报错:
Errors compiling template:Component template should contain exactly one root element.
(2)一个组件中的 data
部分,要定义成一个函数,而不是一个对象。
正确(定义成函数):
data() {
return {
content: "这是组件内容"
};
}
错误(定义成对象):
data: {
content: "这是组件内容"
}
如果将 data
部分定义成对象,控制台会报错:
[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
如果注意了这两点并且没有出错的话,那么一个简单的组件就封装好了。
三、如何使用组件
组件封装好后,就可以使用了,我们在另一个 vue
文件中使用这个组件,使用方法很简单:
index.vue
:
<template>
<view class="content">
<!-- 使用组件 -->
<my-card></my-card>
</view>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
margin: 20px;
}
</style>
只需要在使用组件的地方写组件的名称即可,即组件文件名,注意使用的时候是双标签。
以上例子的效果为:
可以看出和以往不同的是,在使用组件的时候,并没有进行任何的引入和注册操作,其实这是 uni-app
的 easycom
引入机制,它将组件的引入精简到了一步。
怎么确定组件符合 easycom
规范?
只要组件安装在项目的 components
目录下,并符合 components/组件名称/组件名称.vue
目录结构,就可以不用引用、注册,直接在页面中使用,这就是符合 easycom
规范的组件。
easycom
是自动开启的,不需要手动开启。- 不管
components
目录下安装了多少组件,easycom
打包后会自动剔除没有使用的组件,对组件库的使用尤为友好。
更多关于 easycom
的介绍,点我前往 >>>。
四、Props
prop
是组件中一种自定义的属性,是用来从父组件向子组件传递数据的,给子组件输入其需要的数据。
比如,卡片的背景色需要显示不同的颜色,每个卡片的颜色可能不一样,这就需要在使用卡片组件的时候给组件传递一个颜色值,这个颜色值,就是一个 prop
。
首先我们需要在组件中声明需要的 prop
:
my-card.vue
:
<script>
export default {
name:"myCard",
// 在此声明 props
props: {
// 卡片背景色属性
bgColor: {
// 值类型
type: String,
// 默认值
default: '#FFFFFF'
}
},
data() {
return {
content: "这是组件内容"
};
}
}
</script>
然后把声明好的 prop
应用到样式中:
my-card.vue
:
<template>
<view class="card-wrapper" :style="{ backgroundColor: bgColor }">{{content}}</view>
</template>
在使用组件的时候就可以给卡片指定背景色了:
index.vue
:
<template>
<view class="content">
<!-- 使用组件 -->
<my-card bgColor="green"></my-card>
</view>
</template>
这时候卡片的背景色就是 bgColor
这个 prop
的值,如果使用组件的时候不传值,默认是白色。
prop
在声明的时候可以是简单的数组,也可以是对象类型,对象类型具有更丰富的操作,如类型检测、自定义验证和设置默认值。
对象类型可以有以下几个属性:
选项 | 类型 | 说明 |
---|---|---|
type | String 、 Number 、 Boolean 、 Array 、 Object 、 Date 、 Function 、 Symbol ,任何自定义构造函数、或上述内容组成的数组 | 会检查一个 prop 是否是给定的类型,否则抛出警告 |
default | any | 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。 |
required | Boolean | 定义该 prop 是否是必填项 |
validator | Function | 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 false 的值 (也就是验证失败),一个控制台警告将会被抛出。 |
简单的数组可以这样使用:
props: [
'bgColor'
]
然后我们再给卡片加一个 prop
,来改变卡片中文字的颜色:
my-card.vue
:
props: {
// 卡片背景色属性
bgColor: {
// 值类型
type: String,
// 默认值
default: '#FFFFFF'
},
// 卡片文字的颜色
fontColor: {
// 值类型
type: String,
// 默认值
default: '#000000'
}
}
再应用到 style
中:
my-card.vue
:
<template>
<view class="card-wrapper" :style="{ backgroundColor: bgColor, color: fontColor }">{{content}}</view>
</template>
使用组件时的传值:
index.vue
:
<my-card bgColor="green" fontColor="white"></my-card>
以上传入的颜色值都是静态的,当然也可以动态绑定,比如:
index.vue
:
<template>
<view class="content">
<!-- 使用组件 -->
<my-card :bgColor="cardBackgroundColor" :fontColor="cardFontColor"></my-card>
</view>
</template>
<script>
export default {
data() {
return {
// 卡片背景色
cardBackgroundColor: 'green',
// 卡片文字颜色
cardFontColor: 'white'
}
}
}
</script>
以上操作出现的效果:
五、插槽
插槽就是替换内容的,现在卡片的背景色和文字颜色可以在使用组件的时候指定,但是卡片中的内容还没有做到值的传入,我们在使用组件的时候也可以传入卡片的内容。
首先需要在组件中写入 <slot></slot>
标签。
my-card.vue
:
<template>
<view class="card-wrapper" :style="{ backgroundColor: bgColor, color: fontColor }">
<slot></slot>
</view>
</template>
然后在使用组件的地方传入内容即可:
index.vue
:
<my-card :bgColor="cardBackgroundColor" :fontColor="cardFontColor">我是组件内容</my-card>
当组件渲染的时候,<slot></slot>
将会被替换为 “我是组件内容”。
插槽内可以包含任何模板代码,比如加入一个基础按钮组件:
<my-card :bgColor="cardBackgroundColor" :fontColor="cardFontColor">
我是组件内容
<button type="primary">按钮</button>
</my-card>
如果组件中原来就有内容,也不会受到影响,比如:
my-card.vue
:
<view class="card-wrapper" :style="{ backgroundColor: bgColor, color: fontColor }">
这是组件中本来就有的内容
<br />
<slot></slot>
</view>
index.vue
:
<!-- 使用组件 -->
<my-card :bgColor="cardBackgroundColor" :fontColor="cardFontColor">
我是组件内容
</my-card>
渲染结果为:
六、总结
关于组件的使用,先介绍到这里,这只是基本的使用方法,组件还包括其它很多知识,比如 ref
、单向数据流、自定义事件、插槽的其它使用等等,可以到 uni-app
官网进一步的学习。
简单总结一下:
- 先定义组件,最好符合
easycom
规范。 - 定义需要使用的
prop
。 - 定义插槽,替换内容。
- 使用组件,传入相应的
prop
和内容。
最后放一个完整的小案例:
my-card.vue
:
<template>
<view class="card-wrapper" :style="{ backgroundColor: bgColor, color: fontColor }">
欢迎使用组件
<br />
<slot></slot>
</view>
</template>
<script>
export default {
name:"myCard",
props: {
// 卡片背景色属性
bgColor: {
// 值类型
type: String,
// 默认值
default: '#FFFFFF'
},
// 卡片文字的颜色
fontColor: {
type: String,
default: '#000000'
}
},
data() {
return {
content: "这是组件内容"
};
}
}
</script>
<style>
.card-wrapper {
padding: 10px;
border-radius: 10px;
background-color: red;
height: 150px;
margin-bottom: 10px;
}
</style>
index.vue
:
<template>
<view class="content">
<!-- 使用组件 -->
<my-card v-for="item in cardList" :bgColor="item.bg_color" :fontColor="item.font_color">
{{item.content}}
</my-card>
</view>
</template>
<script>
export default {
data() {
return {
cardList: [
{
id: 1,
bg_color: 'red',
font_color: 'white',
content: '组件一'
},
{
id: 2,
bg_color: 'black',
font_color: 'white',
content: '组件二'
},
{
id: 3,
bg_color: 'orange',
font_color: 'white',
content: '组件三'
}
]
}
}
}
</script>
<style>
.content {
margin: 20px;
}
</style>