微信小程序入门学习教程,从入门到精通,自定义组件与第三方 UI 组件库(以 Vant Weapp 为例) (16) - 教程

自定义组件与第三方 UI 组件库(以 Vant Weapp 为例)

适用于微信小程序开发


一、组件化开发

1.1 什么是组件化开发

组件化开发是将 UI 拆分为独立、可复用的模块(组件),每个组件拥有自己的结构(WXML)、样式(WXSS)、逻辑(JS)和配置(JSON)。组件之间通过 属性(properties)事件(events)插槽(slots) 进行通信。

1.2 组件化开发的优势

  • 提高代码复用性
  • 便于团队协作
  • 降低维护成本
  • 逻辑清晰,结构解耦

二、自定义组件

2.1 创建自定义组件

步骤:
  1. 在项目中新建文件夹(如 components/my-button
  2. 创建四个文件:my-button.jsmy-button.jsonmy-button.wxmlmy-button.wxss
案例:自定义按钮组件

components/my-button/my-button.json

{
"component": true,
"usingComponents": {}
}

component: true 表示这是一个组件。

components/my-button/my-button.js

Component({
// 组件属性定义
properties: {
text: {
type: String,
value: '默认按钮'
},
type: {
type: String,
value: 'primary' // primary / default
}
},
// 组件内部数据
data: {
isClicked: false
},
// 组件方法
methods: {
handleClick() {
this.setData({ isClicked: true });
// 触发自定义事件,通知父组件
this.triggerEvent('tap', { text: this.properties.text });
}
}
});

components/my-button/my-button.wxml

<view
  class="my-button {{type}} {{isClicked ? 'clicked' : ''}}"
  bindtap="handleClick"
>
{{text}}
</view>

components/my-button/my-button.wxss

.my-button {
padding: 10rpx 20rpx;
border-radius: 8rpx;
display: inline-block;
text-align: center;
}
.primary {
background-color: #1989fa;
color: white;
}
.default {
background-color: #f5f5f5;
color: #333;
}
.clicked {
opacity: 0.7;
}

2.2 使用自定义组件

pages/index/index.json

{
"usingComponents": {
"my-button": "/components/my-button/my-button"
}
}

pages/index/index.wxml

<view class="container">
  <my-button
    text="点击我"
    type="primary"
    bind:tap="onMyButtonTap"
  />
</view>

pages/index/index.js

Page({
onMyButtonTap(e) {
console.log('按钮被点击,内容:', e.detail.text);
}
});

三、Vant Weapp 组件库

3.1 安装 Vant Weapp

方法一:通过 npm(推荐)
  1. 初始化 npm(如未初始化):

    npm init -y
  2. 安装 vant-weapp:

    npm i @vant/weapp -S --production
  3. 微信开发者工具 → 工具 → 构建 npm

  4. 勾选“使用 npm 模块”

方法二:手动下载(不推荐)

GitHub 下载 dist 目录,放入项目如 miniprogram_npm/@vant/weapp/

3.2 引入组件

pages/index/index.json

{
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"van-cell": "@vant/weapp/cell/index",
"van-cell-group": "@vant/weapp/cell-group/index"
}
}

四、Vant Weapp 核心组件介绍

4.1 Button 按钮

属性(properties)

  • type: 按钮类型(primary / success / danger / default)
  • loading: 是否加载中
  • disabled: 是否禁用

事件(events)

  • bind:click:点击事件

插槽(slots)

  • 默认插槽:按钮内容

案例:

<van-button type="primary" bind:click="handleVantClick">
  Vant 按钮
</van-button>
Page({
handleVantClick() {
wx.showToast({ title: 'Vant 按钮被点击' });
}
});

4.2 Cell 单元格

常用属性:

  • title:左侧标题
  • value:右侧内容
  • is-link:是否展示右侧箭头

案例:

<van-cell-group>
  <van-cell title="用户名" value="张三" />
  <van-cell title="设置" is-link bind:click="goToSetting" />
</van-cell-group>

五、组件的属性、事件与插槽

5.1 属性(Properties)

  • 父组件通过属性向子组件传递数据
  • 支持类型校验、默认值、观察器(observer)

示例:带 observer 的属性

properties: {
count: {
type: Number,
value: 0,
observer(newVal, oldVal) {
console.log('count 从', oldVal, '变为', newVal);
}
}
}

5.2 事件(Events)

  • 子组件通过 triggerEvent 触发事件
  • 父组件通过 bind:eventName 监听

示例:

// 子组件
this.triggerEvent('change', { id: 123 });
// 父组件
<my-component bind:change="handleChange" />

5.3 插槽(Slots)

  • 默认插槽:<slot />
  • 具名插槽:<slot name="header" />

子组件模板:

<view class="card">
<slot name="header"></slot>
<slot></slot> <!-- 默认插槽 -->
</view>

父组件使用:

<my-card>
<view slot="header">标题</view>
<text>内容区域</text>
</my-card>

六、业务组件开发实践

场景:封装一个“用户信息卡片”业务组件

components/user-card/user-card.json

{
"component": true,
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
}

components/user-card/user-card.js

Component({
properties: {
avatar: String,
name: String,
level: {
type: Number,
value: 1
}
},
methods: {
onEdit() {
this.triggerEvent('edit', { name: this.data.name });
}
}
});

components/user-card/user-card.wxml

<view class="user-card">
  <image class="avatar" src="{{avatar}}" mode="aspectFill" />
    <view class="info">
  <text class="name">{{name}}</text>
  <text class="level">等级:{{level}}</text>
  </view>
<van-button size="mini" bind:click="onEdit">编辑</van-button>
</view>

components/user-card/user-card.wxss

.user-card {
display: flex;
align-items: center;
padding: 20rpx;
border-bottom: 1rpx solid #eee;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.info {
flex: 1;
}
.name {
font-weight: bold;
display: block;
}

父页面使用:

<user-card
  avatar="/images/avatar.png"
  name="李四"
  level="5"
  bind:edit="handleEditUser"
/>

七、综合性案例:商品列表页(结合自定义组件 + Vant)

功能:

  • 使用 Vant 的 Cell 展示商品
  • 自定义“加入购物车”按钮
  • 点击商品跳转详情

页面结构:

pages/product-list/product-list.json

{
"usingComponents": {
"van-cell": "@vant/weapp/cell/index",
"van-cell-group": "@vant/weapp/cell-group/index",
"add-cart-btn": "/components/add-cart-btn/add-cart-btn"
}
}

pages/product-list/product-list.js

Page({
data: {
products: [
{ id: 1, name: 'iPhone 15', price: 5999 },
{ id: 2, name: 'MacBook Pro', price: 12999 }
]
},
onAddToCart(e) {
const product = this.data.products.find(p => p.id === e.detail.id);
wx.showToast({ title: `已添加 ${product.name}` });
},
goToDetail(e) {
const id = e.currentTarget.dataset.id;
wx.navigateTo({ url: `/pages/detail/detail?id=${id}` });
}
});

pages/product-list/product-list.wxml

<van-cell-group>
  <van-cell
    wx:for="{{products}}"
    wx:key="id"
    title="{{item.name}}"
    value="¥{{item.price}}"
    is-link
    data-id="{{item.id}}"
    bind:click="goToDetail"
  >
  <add-cart-btn
    slot="right-icon"
    product-id="{{item.id}}"
    bind:add="onAddToCart"
  />
</van-cell>
</van-cell-group>

components/add-cart-btn/add-cart-btn.js

Component({
properties: {
productId: Number
},
methods: {
handleAdd() {
this.triggerEvent('add', { id: this.properties.productId });
}
}
});

components/add-cart-btn/add-cart-btn.wxml

<van-button size="mini" type="success" bind:click="handleAdd">+</van-button>

八、本章小结

知识点说明
组件化开发模块化、复用、解耦
自定义组件四文件结构,properties/events/slots
Vant Weapp丰富 UI 组件,提升开发效率
属性父传子,支持类型校验与 observer
事件子传父,通过 triggerEvent
插槽内容分发,支持默认与具名
业务组件封装领域逻辑,提升复用性

建议:在实际项目中,优先使用成熟的 UI 库(如 Vant Weapp),对高频业务逻辑封装为自定义业务组件,实现“原子组件 + 业务组件”双层架构。


✅ 以上内容涵盖语法细节、完整案例、注释说明及综合实战,适用于微信小程序开发者系统学习组件开发。

posted @ 2025-11-11 23:49  ycfenxi  阅读(19)  评论(0)    收藏  举报