1、学习目标
知识点名称 | 知识点内容 | 难度系数 | 要求程度 |
---|---|---|---|
模板语法 | 数据绑定、事件绑定、条件渲染、列表渲染 | 2星 | 掌握 |
WXSS样式 | WXSS | 3星 | 掌握 |
配置操作 | 全局配置、TabBar配置、页面配置、 | 3星 | 掌握 |
网络请求和案例 | 网络数据请求、本地生活案例 | 3星 | 掌握 |
文章目录
- 1、学习目标
- 2、模板语法
- 2.1、数据绑定
- 数据绑定原则
- 动态绑定属性
- 2.2、事件绑定
- 什么是事件
- bindTap 的语法格式
- 事件对象
- target 和 currentTarget 的区别
- 为 data 中的数据赋值
- 事件传参
- bindinput的语法格式
- 模拟数据双向绑定
- 2.3、条件渲染
- if..elif..else
- 基于 block 标签使用 if 条件判断
- hidden
- if 和 hidden 的区别
- 2.4、列表渲染
- wx:for
- 手动指定索引和当前项的变量名
- wx:key 的使用
- 3、WXSS样式
- 什么是 wxss及和 css 之间的关系
- 什么是 rpx 及实现原理
- rpx 与 px 以及设计稿之间的换算关系
- @import 样式导入
- 全局样式和局部样式
- 4、配置操作
- 4.1、全局配置
- 全局配置文件以及常用的配置项
- 小程序窗口的组成
- 4.2、TabBar 配置
- Tab bar的概念
- TabBar 的组成部分
- TabBar 节点的配置项
- TabBar 案例
- 4.3、页面配置
- 页面配置文件的作用
- 页面配置和全局配置的关系
- 5、网络请求
- 5.1、小程序中网络数据请求的限制
- 5.2、配置 request 合法域名
- 5.3、发起 GET 请求
- 5.4、发起 POST 请求
- 5.5、在页面刚加载时请求数据
- 5.6、跳过 request 合法域名校验
- 5.7、关于跨域和 AJAX 的说明
- 5、案例
- 5.1、案例效果
- 5.2、实现思路
- 5.3、代码实现
2、模板语法
2.1、数据绑定
思考
❓ Vue 中如何进行数据的渲染与属性绑定绑定?
- Vue 中重点使用 插值表达式 渲染数据
- 绑定的动态绑定使用 v-bind 语法或者 : 简写用法
数据绑定原则
1、基本原则
- 在 data 中定义数据
- 在 wxml 中使用数据
2、 在 data 中定义页面的数据
在页面对应的 .js 文件中,把数据定义在 data 对象中即可:
Page({
data:{
// 字符串类型的数据
name:'小程序',
// 数组类型的数据
info:[
{id:1,name:'Vue'},
{id:2,name:'React'}
]
}
})
3、Mustache 语法的格式
把 data 中的数据绑定到页面中渲染,使用 Mustache 语法 (双大括号) 将变量包起来即可。语法格式如下:
<view>
<!--使用Mustache 语法渲染数据-->
<view>{{ name }}</view>
<view>{{ info[0].name }}</view>
</view>
动态绑定属性
1、Mustache 语法的应用场景
- 绑定内容
- 绑定属性
- 运算(三元运算、算术运算符)
2、属性绑定
页面数据如下:
Page({
data:{
// 图片变量
imgSrc: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
}
})
页面结构如下:
<view>
<!--渲染图片-->
<image src="{{ imgSrc }}" mode="aspectFit"></image>
</view>
3、三元运算
页面数据如下:
Page({
data:{
// 生成10以内的随机数
randomNum: Math.random() * 10
}
})
页面结构如下:
<view>
<view>{{ randomNum >5 ? '随机数大于5' : '随机数小于5' }}</view>
</view>
3、算术运算
页面数据如下:
Page({
data:{
// 生成100以内的随机数
randomNumber: Math.random().toFixed(2)
}
})
页面结构如下:
<view>
<!--100以内的随机数-->
<view>{{ randomNumber * 100 }}</view>
</view>
2.2、事件绑定
什么是事件
-
事件是视图层到逻辑层的通讯方式,事件可以将用户的行为或者组件的状态反馈到逻辑层进行处理
-
小程序中常用的事件
bindTap 的语法格式
- 通过 bindtap,可以为组件绑定tap触摸事件
<button bindtap="btnHandle" type="warn">按钮</button>
- 页面的 .js中定义对应的事件处理函数
Page({
btnHandle () {
console.log('触发事件')
}
})
事件对象
当事件回调触发的时候,会收到一个事件对象 event,它的详细属性如下:
target 和 currentTarget 的区别
- target 是触发该事件的源头组件
- currentTarget 则是当前事件所绑定的组件
- 点击内部的按钮时,点击事件以 冒泡 的方式向外扩散,也会触发外层 view 的 tap 事件处理程序,此时,对于外层的view 来说:
- e.target 指定的是触发事件的源头组件,因为 e.target 是内部的按钮组件
- e.currentTarget 指向的是当前正在触发事件的那个组件,因此 e.currentTarget 是当前的 view 组件
为 data 中的数据赋值
通过调用 this.setData(dataObject) 方法,可以给页面 data 中的数据重新赋值
this.setData() 方法有两个作用:1. 更新数据 , 2. 驱动视图更新
Page({
data: {
age:0
},
btnHandle (e) {
this.setData({
// 键需要更新的字段
// 值为最新的数据
age: this.data.age + 1
})
}
})
事件传参
-
事件传参错误方式
小程序中的事件传参比较特殊,不能在绑定事件的同时为事件处理程序传递参数
例如,下面的代码将不能正常工作,因为小程序会把 bindtap 的属性值,统一当作事件名称来处理,相当于要调用一个名称为 btnHandler(123) 的事件处理函数
-
事件传参正确的方式
可以为组件提供 data-* 自定义属性传参,其中 *** 代表的是参数的名字**,示例代码如下:
<view>
<!--正确的绑定方式-->
<button bindtap="fn" data-id="{{ 123 }}">事件传参</button>
</view>
最终:
- id 会被解析为 参数的名称
- 数值 123 会被解析为参数的值
-
接收事件传递的参数
在事件处理函数中, **通过 event.target.dataset.参数名 **即可获得 具体的参数的值,示例代码如下:
Page({
fn (e) {
// dataset 是一个对象,包含了所有通过 data-* 传递的参数
console.log(e.target.dataset)
// 通过dataset 可以访问到具体的参数值
console.log(e.target.dataset.id)
}
})
bindinput的语法格式
在小程序中,通过 input事件来响应文本框的输入事件,语法格式如下:
- 通过 bindinput,可以为文本框绑定输入事件
<input type="input" bindinput="inputFn"/>
- 在页面的.js 文件中定义事件处理函数
Page({
inputFn (e) {
// e.detail.value 是文本框最新的值
console.log(e.detail.value)
}
})
模拟数据双向绑定
- 定义数据
Page({
data:{
msg:'Hi~'
}
})
- 渲染结构
<input type="text" value="{{ msg }}" bindinput="inputFn" />
输入框的数据是==> {{ msg }}
- 美化样式
input{
border:1px solid #ccc;
padding:5px;
margin:5px;
border-radius:3px;
}
- 书写事件函数
Page({
inputFn(e){
// e.detail.value 是文本框最新的值
this.setData({
msg:e.detail.value
})
}
})
总结概况
❓ 小程序中事件如何传递参数?
- 为组件提供 data-* 自定义属性传参,其中 * 代表的是参数的名字
- 在事件处理函数中,通过 event.target.dataset.参数名 即可获取到具体参数的值
总结概况
❓ 如何获取到输入框最新的值
- 给 input 框绑定点击事件
- 通过事件对象 e.detail.value 获取到输入框最新的值
总结概况
❓ this.setData() 方法的作用是什么
- 更新数据
- 驱动视图更新
2.3、条件渲染
思考
❓ Vue 中如何进行条件渲染?
- v-if……v-else-if……v-else
- v-show
思考
❓ Vue 中两种条件渲染的区别是什么?
- v-if 会确保在切换过程中,将条件块内的事件监听器和子组件适当地被销毁和重建。
- v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换
if…elif…else
- 在框架中,使用 wx:if=“” 来判断是否需要渲染该代码块
<view wx:if="{{ condition }}">True</view>
- 也可以用 wx:elif 和 wx:else 来添加一个 else 块
<!--条件渲染-->
<view wx:if="{{ type === 1 }}"></view>
<view wx:elif="{{ type === 2 }}"></view>
<view wx:else>保密</view>
基于 block 标签使用 if 条件判断
如果要一次性判断多个组件标签,可以使用一个<block/>
标签将多个组件包装起来,并在上边使用 wx:if 控
制属性
<block wx:if="{{ true }}">
<view>View1</view>
<view>View2</view>
</block>
注意:<block/>
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
hidden
在小程序框架中,直接使用 hidden=“” 也能控制元素的显示与隐藏
<view hidden="{{ false }}">条件为true 隐藏, 条件false表示显示</view>
if 和 hidden 的区别
- 运行方式不同
- wx:if 以动态创建和移除元素的方式,控制元素的展示与隐藏
- hidden 以切换样式的方式(display: none/block),控制元素的显示和隐藏
- 使用建议
- 频繁切换时,建议使用 hidden
- 控制条件复杂时,建议使用 wx:if 搭配 wx:elif 、wx:else
2.4、列表渲染
思考
❓ Vue 中如何进行列表渲染 ?
使用 v-for 指令进行渲染,在渲染时给渲染的元素添加 :key 属性
思考
❓ key 的作用是什么 ?
指定列表中项目的唯一的标识符,让每一项保持自己的特征和状态
wx:for
- 通过 wx:for 可以根据指定的数组,循环渲染重复的组件结构
Page({
data:{
array:[
{ message:'Tom' },
{ message:'Jerrry' }
]
}
})
<view wx:for="{{ array }}" wx:key="index">
{{index}} : {{ item.message }}
</view>
- 默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
手动指定索引和当前项的变量名
- 使用 wx:for-item 可以指定数组当前元素的变量名
- 使用 wx:for-index 可以指定数组当前下标的变量名
<view wx:for="{{ array }}" wx:for-item="itemName" wx:key-index="i" wx:key="i">
{{ i }} : {{ itemName.message }}
</view>
wx:key 的使用
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态
(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符,从而提
高渲染的效率,示例代码如下
<view wx:for="{{ array }}" wx:key="index">
{{ index }} : {{ item.message }}
</view>
3、WXSS样式
什么是 wxss及和 css 之间的关系
- 什么是 WXSS
- WXSS (WeiXin Style Sheets) 是一套样式语言,用于描述 WXML 的组件样式
- WXSS 用来决定 WXML 的组件应该怎么显示
- WXSS 和 CSS 的关系
- WXSS 具有 CSS 大部分特性,为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改
- 与 CSS 相比,WXSS 扩展的特性有
- rpx 尺寸单位
- @import 样式导入
什么是 rpx 及实现原理
-
什么是 rpx
rpx(responsive pixel) 是微信小程序独有的,用来解决屏幕适配的尺寸单位
-
rpx 的实现原理
rpx 是实现原理非常简单:鉴于不同设备屏幕的大小不同,为了实现屏幕的自动适配,*rpx 把所有设置的屏幕,在***宽度上 等分为 750 份,即 当前屏幕的总宽度为750 rpx
- 在较小的设备上,1rpx 所代表的宽度较小
- 在较大的设备上,1rpx 所代表的宽度较大
小程序在不同的设备上运行的时候,会自动把 rpx 的样式单位换算成对应的像素单位来渲染,从而显示屏幕适配
rpx 与 px 以及设计稿之间的换算关系
-
rpx 与 px 之间的换算
以 iPhone6 为例,iPhone6 的屏幕宽度为 375px ,共有 750 个物理像素。则 750rpx = 375px = 750 物理像素,即 1rpx = 0.5px = 1 物理像素
-
rpx 和 iPhone6 设计稿的关系
官方建议:开发微信小程序时,设计师可以用 iPhone6 作为视觉稿的标准。(iPhone6 设计稿宽度为 750px)
如果要根据 iPhone6 的设计稿,绘制小程序页面,可以直接把单位从 px 替换为 rpx
例如,假设 iPhone6 设计稿上,要绘制一个 宽高为 200px 的盒子,换算为 rpx 为 200rpx
@import 样式导入
- 什么是样式导入
- 使用 @import 语句可以导入外联样式表
- 语法格式
- @import 后跟需要导入的外联样式表的相对路径,用 ; 表示语句结束
@import '../../styles/global.wxss';
全局样式和局部样式
-
什么是全局样式
定义在 app.wxss 中的样式为全局样式,作用于每一个页面
-
局部样式
- 在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器
- 注意:**当局部样式的**权重大于或等于全局样式的权重时,才会覆盖全局的样式效果
4、配置操作
4.1、全局配置
全局配置文件以及常用的配置项
小程序根目录下的 app.json 文件用来对微信小程序进行全局配置。常用的配置如下:
- pages 数组:配置小程序的页面路径
- window 对象:用于设置小程序窗口的外观
- tabBar 对象:配置小程序底部 tab 栏效果
- style 字段:是否启用新版的组件样式
小程序窗口的组成
小程序的窗口由 3 部分组成:导航栏区域、背景区域、页面主体区域
设置导航栏标题文字内容
设置步骤:app.json → window → navigationBarTitleText
设置导航栏背景色
设置步骤:app.json → window → navigationBarBackgroundColor
设置导航栏标题颜色
设置步骤:app.json → window → navigationBarTextStyle
注意:此选择仅支持 black / white
全局开启下拉刷新功能
通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为
设置步骤:app.json → window → enablePullDownRefresh
设置下拉刷新窗口的背景色
当全局开启下拉刷新功能之后,默认的窗口背景为白色
设置步骤:app.json → window → backgroundColor
设置下拉loading的样式
当全局开启下拉刷新功能之后,默认窗口的 loading 样式为白色
设置步骤:app.json → window → backgroundTextStyle
注意:仅支持 dark / light
设置上拉触底的距离
手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
设置步骤:app.json → window → onReachBottomDistance
注意: 默认距离为 50px,如果没有特殊需求,建议使用默认值即可
4.2、TabBar 配置
Tab bar的概念
- tabBar 是移动端应用常见的页面效果,用于实现多页面的快速切换小程序中
- 通常将其分为 底部 tabBar 和 顶部 tabBar
注意:
tabBar 中,只能配置最少 2 个、最多 5 个 tab 页签,
当渲染顶部 tabBar 的时候,不显示 icon,只显示文本
TabBar 的组成部分
- backgroundColor:导航条背景色
- selectedIconPath:选中时的图片路径
- borderStyle:tabBar上边框的颜色
- iconPath:未选中时的图片路径
- selectedColor:tab 上的文字选中时的颜色
- color:tab 上的文字默认(未选中)颜色
TabBar 节点的配置项
- TabBar 节点的配置项
- list 节点的配置项
TabBar 案例
-
根据素材中提供的小图标,实现下图中 TabBar 效果:
-
实现步骤
- 将 image 文件夹,拷贝到小程序项目根目录中
- 创建 3 个对应的 tab 页面
- 设置 tabBar 字段,同时设置 list 字段,配置 TabBar 即可
-
案例代码
"tabBar":{
"list":[
{
"pagePath":"pages/home/home",
"text":"首页",
"iconPath":"/images/tabs/home.png",
"selectedIconPath":"/images/tabs/home-active.png"
},
{
"pagePath":"pages/message/message",
"text":"消息",
"iconPath":"/images/tabs/message.png",
"selectedIconPath":"/images/tabs/message-active.png"
}
}
思考
❓ TabBar 配置项中注意事项
- List 配置项最多 5 个,最少 2 个
- 当 postision 的值为 Top 时,不显示 icon 图标
4.3、页面配置
页面配置文件的作用
小程序每个页面都有自己的 .json 文件,用来对本页面的窗口表现进行配置。页面中配置项在当前页面会覆盖 app.json 的 window 中相同的配置项
页面配置和全局配置的关系
小程序中, app.json 中的 window 节点,可以全局配置小程序中每个页面的窗口表现
如果某些小程序页面想要拥有特殊的窗口表现,此时,页面级别的 .json 配置文件就可以实现这种需求
注意:当页面配置与全局配置冲突时,根据就近原则,最终的效果以页面配置为准
5、网络请求
思考
❓ jQuery 中如何发起网络请求 ? 同时我们思考什么是跨域?小程序中是否存在跨域 ?
$.ajax({
url: ‘xxx’,
method: ‘GET’,
success: function (data) {
console.log(data)
}
})
5.1、小程序中网络数据请求的限制
出于安全性方面的考虑,小程序官方对数据接口的请求做出了如下两个限制:
- 只能请求 HTTPS 类型的接口
- 必须将接口的域名添加到信任列表中 (上线)
5.2、配置 request 合法域名
需求描述:假设在自己的微信小程序中,希望请求 https://www.escook.cn/ 域名下的接口
配置步骤:\登录微信小程序\管理后台 → 开发 → 开发设置 → 服务器域名 → 修改 request 合法域名
修改时需要注意事项:
- 域名只支持 https (request、uploadFile、downloadFile) 和 wss (connectSocket) 协议
- 域名不能使用 IP 地址或 localhost
- 域名必须经过 ICP 备案
- 服务器域名一个月内可申请 15 次修改
5.3、发起 GET 请求
调用微信小程序提供的 wx.request() 方法,可以发起 GET 数据请求
Page({
getHandler(){
wx.request({
url:'https://www.escook.cn/api/get',
method:'GET', // 请求方式
data:{ // 请求参数
id:1
},
success:(data)=>{ // 请求成功的回调函数
const { data:res } = data
console.log(res)
}
})
}
})
5.4、发起 POST 请求
调用微信小程序提供的 wx.request() 方法,可以发起 POST 数据请求
Page({
postHandler(){
wx.request({
url:'https://www.escook.cn/api/post',
method:'POST', // 请求方式
data:{ // 请求参数
id:1
},
success:(data)=>{ // 请求成功的回调函数
const { data:res } = data
console.log(res)
}
})
}
})
5.5、在页面刚加载时请求数据
在很多情况下,我们需要在页面刚加载的时候,自动请求一些初始化的数据。此时需要在页面的 onload 事件中调用获取数据的函数
onLoad: function(options){
this.postHandler()
}
5.6、跳过 request 合法域名校验
如果后端程序员 仅仅提供了 http 协议的接口、暂时没有提供 https 协议的接口,此时为了不耽误开发的进度,我们需要在微信开发者工具中,临时开启 [开发环境不校验请求域名、TLS 版本及 HTTPS 证书」 选项,跳过服务器域名的校验。此时,在微信开发者工具中及手机开启调试模式时,不会进行服务器域名的校验。
注意:在服务器域名配置成功后,建议开发者关闭此选项进行开发,并在各平台下进行测试,以确认服务器域名配置正确。
5.7、关于跨域和 AJAX 的说明
- 跨域问题只存在于基于浏览器的 Web 开发中。由于小程序的宿主环境不是浏览器,而是微信客户端,所以小程序中不存在跨域问题
- AJAX 技术的核心是依赖于浏览器中的 XMLHttpRequest 这个对象,由于 小程序宿主环境是微信客户端,所以小程序中不能叫做 发起 AJAX 请求,而是叫做 发起网络数据请求
5、案例
5.1、案例效果
5.2、实现思路
- 新建项目并梳理项目结构
- 配置 导航栏 效果
- 配置 tabBar 效果
- 实现 轮播图 效果
- 实现 九宫格 效果
- 实现 图片布局
5.3、代码实现
1、新建项目并梳理项目结构
- 使用微信开发者工具新建项目
- 创建三个页面,分别是
- pages/home/home
- pages/message/message
- pages/contact/contact
- 删除 index 和 log 页面
2、配置导航栏效果
app.json
里面的配置
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#2b4b6b",
"navigationBarTitleText": "本地生活",
"navigationBarTextStyle": "white"
}
3、配置 tabBar
app.json
里面配置
"tabBar": {
"selectedColor": "#ed523c",
"backgroundColor": "#fff",
"list": [
{
"pagePath": "pages/home/home",
"text": "主页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "联系我们",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
}
4、实现轮播图效果
- 配置轮播图数据
home.js
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
// 1. 创建存放轮播图数据的列表
swiperList:[]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 3. 调用获取轮播图数据方法
this.getSwiperList()
},
// 2. 定义获取轮播图数据的方法
getSwiperList () {
wx.request({
url: 'https://www.escook.cn/slides',
method:'GET',
success: res=>{
this.setData({
swiperList:res.data
})
}
})
}
})
- 渲染轮播图结构和样式
home.wxml
绘制结构
<!-- 轮播图区域 -->
<swiper indicator-dots circular>
<swiper-item wx:for="{{ swiperList }}" wx:key="id">
<image src="{{ item.image }}"></image>
</swiper-item>
</swiper>
home.wxss
绘制样式
swiper{
height: 350rpx;
}
swiper-item image{
width: 100%;
height: 100%;
}
5、获取九宫格数据
- 配置九宫格数据
home.js
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
// 创建存放轮播图数据的列表
swiperList:[],
// 存放九宫格数据的列表
gridList:[]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 调用获取轮播图数据方法
this.getSwiperList()
// 调用获取宫格数据的方法
this.getGridList()
},
// 定义获取轮播图数据的方法
getSwiperList () {
wx.request({
url: 'https://www.escook.cn/slides',
method:'GET',
success: res=>{
this.setData({
swiperList:res.data
})
}
})
},
// 定义获取九宫格数据的方法
getGridList () {
wx.request({
url: 'https://www.escook.cn/categories',
method:'GET',
success: res=>{
this.setData({
gridList: res.data
})
}
})
}
})
- 绘制九宫格结构和样式
home.wxml
绘制结构
<!-- 轮播图区域 -->
<swiper indicator-dots circular>
<swiper-item wx:for="{{ swiperList }}" wx:key="id">
<image src="{{ item.image }}"></image>
</swiper-item>
</swiper>
<!-- 九宫格区域 -->
<view class="grid-list">
<view class="grid-item" wx:for="{{ gridList }}" wx:key="id">
<image src="{{ item.icon }}"></image>
<text>{{ item.name }}</text>
</view>
</view>
home.wxss
绘制样式
.grid-list{
display: flex;
flex-wrap: wrap;
border-top: 1px solid #efefef;
border-left:1px solid #efefef;
}
.grid-item{
width: 32.333%;
height: 200rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-right: 1px solid #efefef;
border-bottom: 1px solid #efefef;
box-sizing: border-box;
flex-grow: 1;
}
.grid-item image{
width: 60rpx;
height: 60rpx;
}
.grid-item text{
font-size: 24rpx;
margin-top: 10rpx;
}
6、实现 图片布局
- 渲染底部图片结构
<!-- 轮播图区域 -->
<swiper indicator-dots circular>
<swiper-item wx:for="{{ swiperList }}" wx:key="id">
<image src="{{ item.image }}"></image>
</swiper-item>
</swiper>
<!-- 九宫格区域 -->
<view class="grid-list">
<view class="grid-item" wx:for="{{ gridList }}" wx:key="id">
<image src="{{ item.icon }}"></image>
<text>{{ item.name }}</text>
</view>
</view>
<!-- 图片区域 -->
<view class="img-box">
<image src="/images/link-01.png" mode="widthFix"></image>
<image src="/images/link-02.png" mode="widthFix"></image>
</view>
- 渲染底部图片样式
.img-box{
display: flex;
justify-content: space-around;
padding: 20rpx 10rpx;
}
.img-box image{
width: 45%;
}