微信小程序07-开发进阶
零、文章目录
微信小程序07-开发进阶
1、案例:自定义标签栏
(1)案例分析
- 需求:通过前面的学习,我们知道微信小程序的底部标签栏可以在app.json全局配置文件中通过添加tabBar配置项的属性来实现。但是在实际开发中,底部标签栏会有不同的需求,例如需要设计更美观的样式或者需要添加更多的功能,此时就需要自定义标签栏。
(2)知识储备-创建自定义组件
-
自定义组件
- 在实际开发中,可能会遇到多个页面中有相同功能区域的情况。例如,多个页面中都有搜索栏。如果为每个页面复制同一份代码,会造成代码冗余,而且不利于后期代码维护。此时,开发者可以将页面内的重复部分封装成自定义组件,以便于在不同的页面中重复使用,从而有助于代码维护。
- 一个自定义组件是由JSON、JS、WXML和WXSS这4个文件组成的,自定义组件的组成文件通常存放在项目的components目录中,并且为了保证目录结构的清晰,通常会将不同的组件放在不同的子目录下。
-
创建自定义组件
-
①打开微信开发者工具,创建一个新项目或打开现有项目。
-
②在项目的根目录中右键单击,选择“新建文件夹”,然后输入新文件夹的名称“components”,按回车键确认。
-
③在components文件夹上右键单击,选择“新建文件夹”,然后输入新文件夹的名称“test”,按回车键确认。
-
④在test文件夹上右键单击,选择“新建Component”,然后输入组件的名称“test”,按回车键确认。确认后,微信开发者工具会自动生成组件的JS、JSON、WXML和WXSS文件。
-
组件和页面的JS与JSON文件区别如下
-
①组件的JSON文件中需要声明component属性,将属性值设为true,表示它是一个组件,而页面的JSON文件不需要添加该属性。
-
②组件的JS文件中调用的是Component()函数,而页面的JS文件调用的是Page()函数。
-
③组件的事件处理函数需要定义到methods中,页面的事件处理函数需要定义在Page({})中。
-
-
(2)知识储备-使用自定义组件
-
自定义组件创建完成后,在使用自定义组件之前,首先要引用自定义组件,需要提供每个自定义组件的标签名和对应自定义组件的文件路径。
-
自定义组件的引用方式分为局部引用和全局引用
- 在页面的JSON文件中引用自定义组件的方式称为局部引用,局部引用的自定义组件只能在当前被引用的页面内使用;
- 在app.json全局配置文件中引用组件的方式称为全局引用,全局引用的自定义组件可以在每个页面中使用。
-
局部引用
- 在pages/index/index.json文件中添加引用自定义组件的代码
"usingComponents": {"test": "/components/test/test" }
- 在pages/index/index.wxml文件中通过
<test>
标签使用自定义组件
<test></test>
-
全局引用
- 全局配置文件app.json文件中添加引用自定义组件的代码
"usingComponents": {"test": "/components/test/test" }
- 在pages/index/index.wxml文件中,通过
<test>
标签使用组件
<test></test>
(2)知识储备-用自定义组件渲染标签栏
-
微信小程序允许开发者使用自定义组件渲染标签栏,这样开发者就能自定义标签栏的显示效果,并且可以为自定义标签栏添加功能。
-
首先在app.json文件中配置两个页面
"pages": ["pages/home/home","pages/message/message"
],
- 然后在app.json文件的tabBar配置项中添加"custom": true开启自定义标签栏
"tabBar": {"custom": true,"list": [{"pagePath": "pages/home/home"}, {"pagePath": "pages/message/message"}]
}
- 在项目根目录下创建名称为custom-tab-bar的文件夹,并在该文件夹中创建名称为index的组件,最后使用自定义组件的方式编写index组件即可。
(2)知识储备-Vant Weapp组件库
-
Vant Weapp组件库
- 在微信小程序实际开发中,内置的组件经常无法满足需求,手动编写自定义组件又会花费大量的时间,此时可以使用市场上成熟的开源组件库,提高开发效率。
- Vant Weapp是有赞前端团队开发的一套开源的微信小程序UI组件库,其界面风格统一、功能齐全,受到广泛关注。Vant Weapp组件库提供了一整套UI基础组件和业务组件,能够快速搭建出风格统一的页面。
- 若要在微信小程序中使用Vant Weapp组件库,需要利用Node.js提供的npm命令将Vant Weapp组件库安装到项目中,并在项目中进行一些配置。
-
具体的使用步骤如下
- ①在微信开发者工具中创建一个新的微信小程序项目,项目名称为“Vant”。
- ②打开命令提示符,切换工作目录到本项目的根目录,然后在命令提示符中执行以下命令,生成package.json文件。
npm init -y
- ③在命令提示符中执行以下命令,安装Vant Weapp包。
npm install @vant/weapp@1.10.4 -S –production
- ④修改app.json全局配置文件,将里面的"style": "v2"配置项删除,该配置项表示使用微信小程序的新版基础组件样式,删除该配置项表示使用旧版基础组件样式。Vant Weapp组件库需要覆盖基础组件样式才能生效,由于新版基础组件样式难以覆盖,可能会出现样式混乱的问题,所以应使用旧版基础组件样式。
- ⑤构建npm。微信小程序不能直接使用npm安装的包,需要将npm安装的包转换成微信小程序可以使用的包,具体方法是在微信开发者工具的菜单栏中执行“工具”→“构建npm”命令。
- miniprogram_npm是构建npm完成后的包的存放目录
- node_modules是npm安装的包的存放目录。
-
代码演示button组件使用
- 在app.json文件或页面的JSON文件的usingComponents配置项中引入button组件,以app.json文件为例。
"usingComponents": {"van-button": "@vant/weapp/button/index" }
- 在pages/index/index.wxml文件中使用button组件。
<van-button type="primary">按钮</van-button>
(3)案例实现
-
准备工作
- ①创建项目。在微信开发者工具中创建一个新的微信小程序项目,项目名称为“自定义标签栏”,模板选择“不使用模板”。
- ②安装Vant Weapp组件库。根据知识储备中的步骤进行安装。
- ③创建images文件夹。复制需要的图片素材进去,该文件夹保存了自定义标签栏的图片。
-
项目初始化
- ①创建自定义组件。在项目根目录下创建custom-tab-bar文件夹,然后在custom-tab-bar文件夹中创建index组件。
- ②编写全局配置文件app.json。
{"pages": ["pages/home/home","pages/message/message","pages/contact/contact"],"window": {"backgroundTextStyle": "light","navigationBarBackgroundColor": "#fff","navigationBarTitleText": "自定义标签栏","navigationBarTextStyle": "black"},"tabBar": {"custom": true,"list": [{"pagePath": "pages/home/home"}, {"pagePath": "pages/message/message"}, {"pagePath": "pages/contact/contact"}]},"usingComponents": {"van-tabbar": "@vant/weapp/tabbar/index","van-tabbar-item": "@vant/weapp/tabbar-item/index"},"sitemapLocation": "sitemap.json" }
- ③编写3个页面中的内容。以pages/home/home页面为例,编写pages/home/home.wxml文件。
<!--pages/home/home.wxml--> <view>首页</view>
-
**实现标签栏页面布局:**在custom-tab-bar/index.wxml文件中实现页面布局
<!--components/custom-tab-bar/index.wxml-->
<van-tabbar active="{{ active }}" bind:change="onChange"><van-tabbar-item wx:for="{{ list }}" wx:key="index" name="{{ item.name }}"><image slot="icon" src="{{ item.iconPath }}" mode="aspectFit" style="width: 30px; height: 18px;" /><image slot="icon-active" src="{{ item.selectedIconPath }}" mode="aspectFit" style="width: 30px; height: 18px;" />{{ item.text }}</van-tabbar-item>
</van-tabbar>
-
实现标签栏页面逻辑
- 在custom-tab-bar/index.js文件中编写标签栏逻辑。
// components/custom-tab-bar/index.js Component({/*** 组件的属性列表*/properties: {},/*** 组件的初始数据*/data: {active: 'home',list: [{// "pagePath": "/pages/home/home","text": "首页","iconPath": "/images/tabs/home.png","selectedIconPath": "/images/tabs/home-active.png","name": "home"}, {// "pagePath": "/pages/message/message","text": "消息","iconPath": "/images/tabs/message.png","selectedIconPath": "/images/tabs/message-active.png","name": "message"}, {"pagePath": "/pages/contact/contact","text": "联系我们","iconPath": "/images/tabs/contact.png","selectedIconPath": "/images/tabs/contact-active.png","name": "contact"}]},/*** 组件的方法列表*/methods: {onChange({ detail }) {wx.switchTab({url: `/pages/${ detail }/${ detail }`,})}} })
- 在pages/home/home.js文件的Page({})中编写onShow()函数,将该页面对应的标签项激活。
onShow: function () {this.getTabBar().setData({active: 'home'}) },
- 在pages/message/message.js文件的Page({})中编写onShow()函数,将该页面对应的标签项激活。
onShow: function () {this.getTabBar().setData({active: 'message'}) },
- 在pages/contact/contact.js文件的Page({})中编写onShow()函数,将该页面对应的标签项激活。
onShow: function () {this.getTabBar().setData({active: 'contact'}) },
-
页面实现效果
2、案例:电影列表
(1)案例分析
- 需求:电影列表”微信小程序用于展示正在热映的电影。
- “电影列表”微信小程序利用WeUI组件库实现页面效果,页面顶部有一个标签栏,标签栏中有3个标签项,分别是“正在热映”“搜索”“分类”,当用户点击其中一个标签项时,就会跳转到对应的标签页。
- 页面顶部的标签栏使用了WeUI组件库中的tab和navbar组件。
- “正在热映”标签页使用了WeUI组件库中的panel组件;
- “搜索”标签页使用了WeUI组件库中的searchbar组件;
- “分类”标签页使用了WeUI组件库中的grid组件。
(2)知识储备-WeUI组件库
-
在微信小程序开发中,经常会遇到多人协作开发的情况,不同开发者的风格不同,很难做到风格统一。微信官方设计团队为微信移动Web开发量身设计了一套与微信原生视觉体验一致的组件库——WeUI,该组件库可以让用户的使用感知更加统一。
-
在微信小程序中引入WeUI组件库有两种方式
-
通过useExtendedLib扩展库引入WeUI组件库:app.json文件中的useExtendedLib配置项用于添加扩展库,通过这种方式引入的组件将不会计入代码包大小。在app.json文件中添加配置。
"useExtendedLib": {"weui": true },
-
通过npm构建的方式引入WeUI组件库
- ①打开命令提示符,切换工作目录到当前项目的根目录,然后在命令提示符中执行如下命令,生成package.json文件。
npm init -y
- ②安装WeUI组件库。在项目根目录下执行以下命令进行安装。
npm install weui-miniprogram@1.2.3 --save
- ③构建npm。打开微信小程序开发工具,在菜单栏中执行“工具”→“构建npm”命令,构建完成后会在项目根目录生成miniprogram_npm文件夹。
- ④在项目的app.wxss文件中引入WeUI组件库
@import 'miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss';
-
-
WeUI组件库中的组件有两种类型
- 一种是直接通过class样式类使用的组件
- 另一种是需要在页面的JSON文件或app.json文件中引入的组件。
- 关于这些组件的详细用法可以参考WeUI官方文档。
-
代码演示使用dialog弹窗组件
- 在pages/index/index.json文件中引入dialog弹窗组件。
{"usingComponents": {"mp-dialog": "/miniprogram_npm/weui-miniprogram/dialog/dialog"} }
- 在pages/index/index.wxml文件中使用dialog弹窗组件。
<!--index.wxml--> <mp-dialog title="微信小程序" show="{{ show }}" bindbuttontap="tapDialogButton" buttons="{{ buttons }}"><view>好好学习,天天向上!!!</view> </mp-dialog>
- 在pages/index/index.js文件中编写页面逻辑。
// index.js Page({data: {show: true,buttons: [{text: '取消'},{text: '确认'}]},tapDialogButton: function (e) {console.log(e.detail)this.setData({show: false})} })
(2)知识储备-navigator组件
-
navigator组件
- 在HTML中,
<a>
标签可以实现页面间的跳转。 - 在WXML中,navigator组件常用于实现页面之间的跳转。
<navigator>navigator组件</navigator>
- navigator组件的常用属性如下。
- navigator组件的open-type属性用于指定跳转方式,常用的open-type合法值如下。
- 跳转tabBar页面,必须设置open-type属性值为switchTab;
- 跳转非tabBar页面且保留当前页面,设置open-type属性值为navigate时open-type属性可以省略。
- 在HTML中,
-
代码演示
- 创建pages/index/index和pages/detail/detail这两个页面。
- 在pages/index/index.wxml文件中添加navigator组件,实现点击“跳转到详情页”的时候进行页面跳转。
<navigator url="/pages/detail/detail?id=1" open-type="navigate">跳转到详情页</navigator>
- 在pages/detail/detail.js文件的onLoad()函数中输出options参数的值。
onLoad: function(options) {console.log(options) }
(3)案例实现
-
准备工作
- ①创建项目。在微信开发者工具中创建一个新的微信小程序项目,项目名称为“电影列表”,模板选择“不使用模板”。
- ②配置页面。本项目中的页面文件如下。
- ③配置导航栏。在pages/index/index.json文件中配置页面导航栏。
- ④配置样式和图片。在pages/index/index.wxss文件中配置样式,在images文件夹中放入图片素材。
- ⑤通过useExtendedLib扩展库的方式引入WeUI组件库,在全局配置文件app.json中添加配置
"useExtendedLib": {"weui": true }
-
**实现标签栏页面结构:**在pages/index/index.wxml文件中编写页面结构。
<!--index.wxml-->
<view class="page" data-weui-theme="{{ theme }}" data-weui-mode="{{ mode }}"><view class="page__bd" style="height: 100%;"><view class="weui-tab"><!-- 标签栏 --><view class="weui-navbar"><block wx:for="{{ tabs }}" wx:key="index"><view aria-selected="{{ activeIndex == index ? true: false }}" id="{{ index }}" class="weui-navbar__item {{ activeIndex == index ? 'weui-bar__item_on' : '' }}" aria-role="tab" bindtap="tabClick">{{ item }}</view></block></view><!-- 正在热映 --><view id="panel1" aria-labelledby="tab1" class="weui-tab__panel" aria-role="tabpanel" hidden="{{ activeIndex != 0 }}"><include src="tab1.wxml" /></view><!-- 搜索 --><view id="panel2" aria-labelledby="tab2" class="weui-tab__panel" aria-role="tabpanel" hidden="{{ activeIndex != 1 }}"><include src="tab2.wxml" /></view><!-- 分类 --><view id="panel3" aria-labelledby="tab3" class="weui-tab__panel" aria-role="tabpanel" hidden="{{ activeIndex != 2 }}"><include src="tab3.wxml" /></view></view></view>
</view>
- **实现“正在热映”标签页页面结构:**在pages/index/tab1.wxml文件中编写页面结构。
<view class="page__hd"><view class="page__title">电影列表</view>
</view>
<view class="page__bd"><view class="weui-panel weui-panel_access"><view class="weui-panel__bd"><navigator wx:for="{{ contents }}" wx:key="index" aria-labelledby="js_p1m1_bd" class="weui-media-box weui-media-box_appmsg" url="../test/test"><view aria-hidden="true" class="weui-media-box__hd"><image class="weui-media-box__thumb" src="{{ item.poster }}" /></view><view aria-hidden="true" id="js_p1m1_bd" class="weui-media-box__bd"><text class="weui-media-box__title">{{ item.title }}</text><view class="weui-media-box__desc">{{ item.article }}</view></view></navigator></view><view class="weui-panel__ft"><navigator class="weui-cell weui-cell_active weui-cell_access weui-cell_link" url="../index/index"><text class="weui-cell__bd">查看更多</text><text class="weui-cell__ft"></text></navigator></view></view>
</view>
- **实现“搜索”标签页页面结构:**在pages/index/tab2.wxml文件中编写搜索框的页面结构。
<view class="page__bd"><view class="weui-search-bar {{ inputShowed ? 'weui-search-bar_focusing' : '' }}" id="searchBar"><form class="weui-search-bar__form" aria-role="combobox" aria-haspopup="true" aria-expanded="{{ inputVal.length > 0 ? 'true' : 'false' }}" aria-owns="searchResult"><view class="weui-search-bar__box"><i class="weui-icon-search"></i><input aria-controls="searchResult" type="text" class="weui-search-bar__input" placeholder="搜索" value="{{ inputVal }}" focus="{{ inputShowed }}" bindinput="inputTyping" /><view aria-role="button" aria-label="清除" class="weui-icon-clear" wx:if="{{ inputVal.length > 0 }}" bindtap="clearInput"></view></view><label class="weui-search-bar__label" bindtap="showInput"><i class="weui-icon-search"></i><span class="weui-search-bar__text">搜索</span></label></form><view aria-role="button" class="weui-search-bar__cancel-btn" bindtap="hideInput">取消</view></view>
</view>
<view class="page__bd page__bd_spacing"><view class="weui-flex"><view class="weui-flex__item"><view class="placeholder">英雄儿女</view></view></view><view class="weui-flex"><view class="weui-flex__item"><view class="placeholder">大国工匠</view></view><view class="weui-flex__item"><view class="placeholder">大国重器</view></view></view><view class="weui-flex"><view class="weui-flex__item"><view class="placeholder">长津湖</view></view><view class="weui-flex__item"><view class="placeholder">集结号</view></view><view class="weui-flex__item"><view class="placeholder">红海行动</view></view></view>
</view>
- **实现“分类”标签页页面结构:**在pages/index/tab3.wxml文件中编写页面结构。
<view class="weui-grids"><navigator class="weui-grid" aria-role="button" url="../index/index" wx:for="{{ grids }}" wx:key="index"><view class="weui-grid__icon"><image src="../../images/icon_tabbar.png" /></view><view class="weui-grid__label">{{ item }}</view></navigator>
</view>
- **实现页面逻辑:**在pages/index/index.js文件中实现页面逻辑。
// index.js
Page({data: {activeIndex: 0,tabs: ['正在热映', '搜索', '分类'],contents: [{title: '英雄儿女',article: '该影片讲述了多位英雄人物的故事,其中有浴血奋战的志愿军英模。',poster: '/images/1.jpg',}, {title: '大国工匠',article: '这部影片讲述了不同岗位劳动者用自己的灵巧双手,匠心筑梦的故事。',poster: '/images/2.jpg',}, {title: '我和我的祖国',article: '该影片取材新中国成立以来经历的无数个历史性经典瞬间,讲述普通人与国家之间息息相关密不可分的动人故事。',poster: '/images/3.jpg',}],inputShowed: false,inputVal: '',grids: ['爱情', '剧情', '喜剧', '家庭', '动画', '文艺', '都市', '动作', '科幻']},tabClick: function (e) {this.setData({activeIndex: e.currentTarget.id})},inputTyping: function(e) {this.setData({inputVal: e.detail.value})},showInput: function () {this.setData({inputShowed: true})},hideInput: function () {this.setData({inputVal: '',inputShowed: false})},clearInput() {this.setData({inputVal: ''})},})
- 页面实现效果