目录
新建项目和配置
项目基本结构
新建小程序页面
修改项目首页
全局配置
窗口
tabBar
页面配置
小程序基本语法
wxml
数据绑定
条件渲染
列表渲染
wxss
wxss 对比 css
rpx
@import
全局样式和局部样式
js
wxs
数据请求
get和post请求
小程序和跨域
小程序和Ajax
小程序API的 Promise 化
最后
前言
随着微信小程序的推出,小程序逐渐成为了一个热门话题。各大平台相继推出了自己的小程序框架,如支付宝小程序、百度智能小程序等。它们以其便捷的用户体验、无需下载安装即可使用的特性,受到了广大用户的喜爱。因此,学会如何开发一款小程序,不仅能够提升个人的技术能力,还能为未来的职业发展打开新的窗口。
新建项目和配置
项目基本结构
创建一个微信小程序项目,目录结构
如下:
- pages: 存放所有小程序的页面 - utils:存放工具性质的模块 - app.js:小程序入口文件 - app.json:小程序全局配置文件。包含小程序所有页面路径、窗口外观、界面表现(所有页面的背景色、文字颜色、小程序组件所使用的样式版本)、底部tab - project.config.json:项目配置文件。记录我们对小程序开发工具做的个性化配置,如项目名、小程序账号ID、编译相关配置(ES6转ES5、上传代码时自动压缩混淆、上传代码时样式自动补全) - sitemap.json:配置小程序及其页面是否允许被微信索引。微信现已开放了小程序内搜索,类似网页的SEO。
小程序官方建议所有小程序页面都放在 pages
目录中,以单独文件夹存放:
- pages - index - index.js 页面脚本 - index.wxml 页面结构 - index.wxss 页面样式 - index.json 当前页面的配置,如窗口的外观 - pageb - pageb.js - pageb.wxml - pageb.wxss - pageb.json
Tip:小程序中有4种json配置文件
(具体作用后面会介绍)
-
项目根目录中的 app.json
-
项目根目录中的 project.config.json
-
项目根目录中的 sitemap.json
-
每个页面文件夹中的 json
新建小程序页面
在 app.json->pages 中新增页面存放路径,ctrl+s保存,工具会自动
创建对应页面文件。
{ pages: [ "pages/index/index", "pages/pageb/pageb", + "pages/pageb/pagec" ] }
修改项目首页
只需调整
app.json->pages 数组中页面路径的顺序
,小程序会把排在第一位的页面,当做项目首页渲染。
全局配置
小程序根目录下的 app.json
是小程序全局配置文件。
常用配置:
-
pages 记录当前小程序所有页面的存放路径
-
window 全局设置小程序窗口外观
-
tabBar 设置小程序底部的 tabBar 效果
-
style 是否启用新版的组件样式
示例:
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"navigationBarTitleText": "小程序示例",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light",
"enablePullDownRefresh": true,
"onReachBottomDistance": 50
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "images/icon_home.png",
"selectedIconPath": "images/icon_home_active.png"
},
{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath": "images/icon_logs.png",
"selectedIconPath": "images/icon_logs_active.png"
}
]
},
"style": "v2"
}
窗口
小程序窗口组成部分(从上到下):
-
navigationBar
导航栏区域
:包含时间、电量、微信标题 -
background
背景区域,默认不可见,下拉才显示 -
页面主体区域
,用了显示 wxml 中布局
windown节点常用配置项:
-
navigationBarTitleText
导航栏标题
文字 字符串 -
navigationBarBackgroundColor 导航栏背景颜色 默认#000000,类型 HexColor
-
navigationBarTextStyle 导航栏颜色(标题、电池等颜色) 仅支持 black/white,默认 white
-
backgroundColor 窗口背景色 默认#ffffff,类型 H3xColor
-
backgroundTextStyle 下拉loading 的样式,仅支持 dark/light,默认 dark
-
enablePullDownRefresh 是否全局开启下拉刷新。默认 false。开启后会作用于小程序每个页面。
-
onReachBottomDistance 页面上拉触底时间触发时距离底部距离,单位 px,默认 50,若无特殊需求,不建议修改。
Tip:下拉刷新
,通常做法是在页面中单独开启,而非在这里全局开启。下拉刷新开启后,若要实现刷新,还得在 onPullDownRefresh 方法中处理下来刷新逻辑,这个方法会在用户触发下拉刷新操作时被调用。
注
:模拟器不能百分之百还原真机。例如下拉刷新,在模拟器中,下拉后,过了3秒,下拉自动合上;而在真机中,不会自动合上
tabBar
小程序中 tabBar 是导航组件
。特性有:
-
位置: 通常位于小程序界面的底部。
-
图标和文字: 每个 tab 都可以包含图标和文字。
-
选中状态: 可以配置选中和未选中状态下的图标和文字颜色。
-
页面映射: 每个 tab 对应一个页面路径,点击 tab 会切换到相应的页面。
以下是一个典型的 app.json 中 tabBar 配置示例
:
{
"tabBar": {
"color": "#999999",
"selectedColor": "#1c1c1b",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/home/index",
"text": "首页",
"iconPath": "/images/icon_home.png",
"selectedIconPath": "/images/icon_home_active.png"
},
{
"pagePath": "pages/search/index",
"text": "搜索",
"iconPath": "/images/icon_search.png",
"selectedIconPath": "/images/icon_search_active.png"
},
{
"pagePath": "pages/profile/index",
"text": "我的",
"iconPath": "/images/icon_profile.png",
"selectedIconPath": "/images/icon_profile_active.png"
}
]
}
}
注
:tabBar 只能配置最少2个,最多5个。当渲染顶部tabBar 时,不显示 icon
,只显示文本。说tabBar 中的页面要放在 pages 前面,否则显示不出。
tabBar 有6个组成部分:
-
color,tab上文字的颜色
-
selectedColor,tab文字选中时的颜色
-
backgroundColor,tabBar 背景色
-
borderStyle,tabBar 边框颜色
-
iconPath,未选中时图片路径
-
selectedIconPath,选中时图片路径
tabBar 节点配置项:
-
position,默认 bottom,可配置 top
-
borderStyle,默认 black,仅支持 black/white
-
color,hexColor 类型
-
selectedColor,hexColor 类型
-
backgroundColor,hexColor 类型
-
list,Array,必填,
最少2个,最多5个
每个 tab 项配置选项:
-
pagePath,必填,页面路径,页面必须在 pages 中预先定义
-
text,必填,tab上显示的文字
-
iconPath,未选中时图片路径;position 为top时不显示 icon
-
selectedIconPath,选中时图片路径;position 为top时不显示 icon
页面配置
在小程序中,全局配置和页面配置可以定义页面的外观和行为
。当全局配置和页面配置冲突时,确实遵循就近原则,最终效果通常以页面配置为准。这意味着页面特定的配置会覆盖全局配置。这样可以确保页面的定制化效果。
页面配置中常用配置项:
-
navigationBarTitleText 导航栏标题
-
navigationBarBackgroundColor 导航栏背景颜色
-
navigationBarTextStyle 导航栏文字颜色
-
backgroundColor 页面背景颜色
-
backgroundTextStyle 下拉loading 的样式
-
enablePullDownRefresh 是否全局开启下拉刷新
-
onReachBottomDistance 页面上拉触底时间触发时距离底部距离
-
disableScroll 禁止页面滚动
-
usingComponents 页面使用的自定义组件列表
小程序基本语法
wxml
微信小程序的 wxml 类似网页中的 html。支付宝小程序中是 axml。
wxml 和 html 区别
:
-
标签名称不同(比如用 view 代替 div):
-
HTML: div、span、img、a
-
wxml: view、text、image、navigator
-
-
属性节点不同
<a href="http://www.baidu.com">百度</a> <navigator url="http://www.baidu.com">百度</navigator>
-
提供了类似 vue 的模板语法:数据绑定、列表渲染、条件渲染
数据绑定
在 data 中定义数据,在 wxml 中使用。例如:
Page({
data: {
name: '张三',
age: 18,
url: 'http://....png',
randomNum: Math.random() * 10,
}
})
用Mustache语法({{}}
)将变量包起来即可:
<view>{{ name }}</view>
<view>{{ randomNum > 5 ? '大于5': '小于或等于5' }}</view>
动态绑定属性不同于 vue 的 v-bind,小程序的动态绑定属性是直接在标签上写(写法不同而已,死记即可
),例如:
<image src="{{ url }}"></image>
Tip: 数据在小程序开发工具控制台的 AppData tab中可以看到。
条件渲染
小程序和vue中条件渲染对比:
-
语法差异:微信小程序使用 wx:if、hidden、block wx:if,vue中使用 v-if,v-show。
-
wx:if 和 v-if 类似,是真正的条件渲染
-
hidden 和 v-hsow 类似,都是通过 css 控制显隐,元素始终存在
-
block 类似 template,一次控制多个组件的展示与隐藏,且都不会渲染成实际的 dom 元素
用法:在 wxml 中使用 wx:if、wx:elif、wx:else 标签,在 data 中定义变量,在 wx:if 中使用变量。
<view>
<view wx:if="{{ age > 18 }}">
你成年了
</view>
<view wx:elif="{{ age < 18 }}"> 你未成年
</view>
<view wx:else>
你很少年
</view>
</view>
列表渲染
小程序和vue中列表渲染对比:
-
语法差异:微信小程序使用 wx:for、wx:key,vue中使用 v-for和:key
-
都强调为列表渲染的每一项制定一个唯一的 key
-
vue 在列表渲染中提供了更丰富的功能
-
wx:for 和 v-for 类似,都是遍历数组,渲染成列表
用法:在 wxml 中使用 wx:for 标签,在 data 中定义数组,在 wx:for 中使用数组。
默认当前循环项索引是 index,当前循环项是 item:
<view class="container">
<block wx:for="{{items}}" wx:key="index">
<view>
<text>{{index}}: {{item}}</text>
</view>
</block>
</view>
Page({
data: {
items: ['Item 1', 'Item 2', 'Item 3']
}
});
wx:for-item 和 wx:for-index 用于自定义变量名,使得代码更加清晰和可读。
<view class="container">
<block wx:for="{{items}}" wx:for-item="user" wx:for-index="idx" wx:key="id">
<view>
<text>Index: {{idx}}</text>
<text>ID: {{user.id}}</text>
<text>Name: {{user.name}}</text>
</view>
</block>
</view>
Page({
data: {
items: [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
]
}
});
注
: 小程序的 key,直接是循环项中的属性,且不需要 {{}}
。如果是vue,得通过循环项找到
<template v-for="item in items" :key="item.id">
wxss
小程序的样式,类似网页的 css。
wxss 对比 css
wxss 具备 css 大部分特定,wxss 还对 css 进行了扩充和修改,以适应小程序的开发
wxss 和 css 区别:
-
新增rpx(responsive pixel,响应式像素)尺寸单位
-
css中实现响应式布局,需要手动进行像素转换(常用 rem)。比如设计师提供的是 750 稿子,我们可能会将 1rem 等于75,设计稿的75就是1rem
-
wxss 在底层支持新的尺寸单位 rpx,在不同屏幕上会自动进行换算,同样是 750 的稿子,75个大小直接写成 75rpx 即可。
-
-
提供全局样式和局部样式
-
微信小程序:项目根目录中 app.wxss 会作用于素有小程序页面;局部页面的 .wxss 样式仅对当前页面生效
-
web 中CSS是全局作用,除非使用CSS模块化工具
-
-
文件类型:微信小程序是 .wxss
-
媒体查询:微信小程序不支持传统CSS媒体查询,如
@media
-
css动画和过度:微信小程序支持部分 css 动画和过度,但有一些限制
-
wxss 仅支持部分常见的 css属性和选择器:.class和#id、element、并集选择器和后代选择器、::after和::before等伪类选择器
-
flex布局:微信小程序中的 flex 大部分与css一致,但具体表现有细微差异
-
引入样式:微信小程序通过
@import
引入其他 .wxss,不支持 @import url() 形式引入外部 css
rpx
rpx 原理非常简单,把所有设备的屏幕从宽度上等分 750 份
-
在375的设备,1rpx 等于 0.5px
-
在1500的设备,1rpx 等于 2px
Tip:rem和 rpx 在实现响应式布局中,主要关注的是宽度的自适应。高度需要自行处理,比如等比扩展,或者限制最高高度。
iphone 屏幕宽度是 375px(逻辑像素),共有 750个像素点(物理像素),1个逻辑像素等于2个物理像素,等分750rpx。则:
-
750rpx = 375px = 750 物理像素
-
1rpx = 0.5px = 1 物理像素
开发举例:根据设计稿来,有的要求是1:1,有的是1:2,宽100px200px的盒子,转成rpx 就是 200rpx400rpx。
@import
@import 后根需要导入的外联样式的相对路径,用;表示结束。示例:
@import "demo.wxss";
.box{
}
使用时是 class 而非 className。
Tip:微信小程序支持使用 less,不过需要进行一些配置。
全局样式和局部样式
定义在 app.wxss 中的样式是全局样式,作用于每一个页面
定义在页面的 .wxss 中的样式是局部样式,只作用于当前页面。
注
:当局部样式和全局样式冲突,和 css 中一样:哪个权重高用哪个,如果权重相同,则使用就近原则(采取局部样式)
Tip:把鼠标放到小程序工具中选择器上,会有选中提示,例如:Selector Specificity:(0, 1, 0)
js
Tip:小程序中的 js 分3大类
-
app.js:小程序入口文件,通过调用 App() 函数启动整个小程序
-
页面.js:页面的入口文件,通过调用 Page() 函数创建并运行页面
-
普通.js:普通功能模块文件,用来封装公共的函数或属性,供页面使用
wxs
wxs在微信小程序中的作用类似 Vue.js中的过滤器
(vue3 已废除过滤器)
小程序中的 wxs 和 javascript 是两种语言,区别有:
-
wxs 在视图层中运行,js运行在逻辑层
-
wxs 隔离性。不能调用 js 中定义的函数,不能调用小程序的API
-
wxs 设计初衷为了提高数据处理性能,特别是与界面渲染密切相关场景,减少和逻辑层的通信
Tip: 在 ios 中,小程序内的 wxs 比 js 块 2~20倍;在安卓上无差异。
wxs的语法基于JavaScript,这意味着如果你熟悉JavaScript,学习wxs会相对容易:
-
wxs 有自己的数据类型:number、string、boolean、array、object...
-
wxs 不支持类似es6+语法,不支持let、const、解构赋值、箭头函数;支持 var、function、es5语法
-
wxs 遵循 commonjs规范:module对象、require()函数、module.exports对象
-
wxs 可以编写在
<wxs>
标签中,就像js写在<script>
中,wxs 必须提供 module 属性,用来指定当前 wxs 模块名称
外联wxs用法(src必须是相对路径):
<!-- index.wxml -->
<wxs module="utils" src="../../utils/utils.wxs"/>
<view>
<text>{{utils.formatDate(new Date())}}</text>
</view>
// utils.wxs
module.exports = {
formatDate: function(date) {
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
return [year, month, day].map(this.formatNumber).join('-');
},
formatNumber: function(n) {
n = n.toString();
return n[1] ? n : '0' + n;
}
};
数据请求
小程序中网络数据,处于安全考虑,小程序官方对数据接口做了如下限制:
-
只能请求 https 类型接口
-
必须将接口的域名添加到信任列表中
假如希望在自己的微信小程序中,希望请求https://www.xxx.com/域名下的接口。配置步骤:登录微信小程序后台->开发->开发设置->服务器域名->修改request合法域名。注意:
-
域名只支持 https
-
域名不能是 ip 地址或 localhost
-
域名必须经过 ICP 备案
-
服务器域名一个月内最多可申请5次修改
Tip: 如果后端仅提供http协议接口,为不耽误开发进度,可以在微信开发者工具中,临时开启「开发环境不校验请求域名、TLS版本及HTTPS证书」,跳过 request 合法域名校验,仅限在开发和调试阶段使用。
get和post请求
在微信小程序中,您可以使用 wx.request
方法来发起 HTTP GET 和 POST 请求。这个方法提供了一种简单的方式来与服务器进行数据交互:
请看示例:
wx.request({
url: 'https://api.example.com/data',
method: 'GET',
data: {
key1: 'value1',
key2: 'value2'
},
header: {
'content-type': 'application/json'
},
success: function(res) {
},
fail: function(err) {
}
});
wx.request({
url: 'https://api.example.com/submit',
method: 'POST',
data: {
key1: 'value1',
key2: 'value2'
},
header: {
'content-type': 'application/json'
},
success: function(res) {
},
fail: function(err) {
}
});
小程序和跨域
小程序没有常规的跨域问题,但本质上还是涉及一些
。但是对于前端开发,则无需处理跨域。
跨域(Cross-Origin Resource Sharing,简称 CORS)是指一个域名下的文档或脚本尝试请求另一个域名下的资源时,由于浏览器的同源策略(Same-origin policy)限制而导致的请求被阻拦的行为。这里的“同源”指的是协议、域名和端口号完全相同。同源策略是一种安全措施,旨在防止恶意网站通过脚本读取另一个网站的敏感数据。
跨域的本质是指浏览器出于安全考虑,实施的一种同源策略(Same-origin policy)
小程序的主体不是浏览器,而是小程序平台,所以没有常规的跨域问题。
因为小程序需要配置受信任域名,其实也在一定程度上有了安全保障,小程序的服务端也会涉及到CORS的配置
小程序和Ajax
Ajax核心依赖浏览器中的 XMLHttpRequest 对象,而小程序的宿主环境是微信客户端,所以小程序不叫”发起ajax请求“,而叫”发起网络请求“
微信小程序没有直接使用 ajax 这个术语,但提供了类似异步HTTP请求能力,主要通过 wx.request 接口来完成 Get 或 Post 请求,这一过程和Ajax非常类似,都是异步获取数据并更新界面而不阻塞页面。所以小程序中不说”ajax“,但实际上具备异步获取数据的能力
wx.request 和 ajax 功能相似,运营环境和实现机制不同。
请看示例:
wx.request({
url: 'https://api.example.com/data',
method: 'GET',
data: {
key1: 'value1',
key2: 'value2'
}, // 请求参数
header: {
'content-type': 'application/json'
},
success: function(res) {
},
fail: function(err) {
}
});
wx.request 可以与 async/await 和 Promise.all 配合使用:
-
封装一个使用 wx.request 的 Promise 函数
const request = (options) => {
return new Promise((resolve, reject) => {
wx.request({
...options,
success: res => resolve(res),
fail: err => reject(err)
});
});
};
-
然后在 async/await 中使用它:
Page({
async onLoad() {
try {
const response = await request({
url: 'https://example.com/api/data',
method: 'GET'
});
console.log('Data:', response.data);
} catch (err) {
console.error('Error:', err);
}
}
});
小程序API的 Promise 化
在开发微信小程序时,许多原生 API 是基于回调函数
的,这在现代 JavaScript 编程中可能不太方便。为了更好地处理异步操作,我们可以将这些回调函数形式的 API 转换为 Promise
形式
一种是手动封装
一种是用库(例如miniprogram-api-promise)。例如: 安装,构建后,在你的项目中配置并使用:
// app.js
import wxp from 'miniprogram-api-promise';
App({
onLaunch() {
// 把所有 wx 函数 promise 化
wxp.init();
}
});
在页面或组件中使用:
// pages/index/index.js
Page({
data: {},
async onLoad() {
try {
const response = await wx.p.request({
url: 'https://api.example.com/data',
method: 'GET',
});
console.log(response.data);
} catch (error) {
console.error(error);
}
}
});
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!优秀是一种习惯,欢迎大家留言学习!