微信小程序
一、相关概念
1 基础知识
微信的前端语言类似于网站开发的前端语言:
- HTML(wxml)
- CSS(wxss)
- JavaScript(js)
微信小程序开发IDE:微信小程序开发者工具。
本地开发环境:
线上部署环境:
- 开发者工具,提交至微信(进行体验、发布)
- API同时也需要部署到线上环境
2 工作流程
- 下载开发者工具:official::概览 | 微信开放文档 (qq.com)
- 注册小程序(ID):official::小程序 (qq.com)
- 个人版小程序:主要是没有支付功能
- 企业版小程序:可以结合自己的商户平台,管理支付数据。
- 登录账号:official::微信公众平台 (qq.com)
- 开发前端
- 开发后端
二、基本知识
1 初始界面
新建项目:绑定ID,然后后台服务不要选择云开发,云开发废钱。然后可以选择语言模版,一开始选JavaScript模板。
查看ID:Web上进行登录,登录后在开发——开发管理处查看。
初始配置:
- 微信小程序默认是https模式。在本地测试时,需要将其修改成http模式,防止数据包无法发送到后端。修改方式:界面右上角——详细——本地设置——不校验合法域名、web-view…….HTTPS证书。
修改页面入口:最上方——普通编译——修改编译模式——修改掉启动页面
2 文件相关
文件结构:
pages:存放页面文件:
index:首页
- index.js:当前页面js文件
- index.json:当前页面配置文件
- index.wxml:当前页面微信html文件
- index.wxss:当前页面微信css文件
xxx:其他页面同理
utils:组件:
.eslintrc.js:eslint,语法检查
app.js:全局js文件
app.json:全局页面配置文件
app.wxss:全局css
project.config.json:全局默认配置文件
project.private.config.json:全局配置文件(优先级更高)
sitemap.json:被微信索引的配置,一般不修改,official::配置小程序 / sitemap 配置 (qq.com)
文件夹新增:
文件操作:
- 新建page:在pages中——右键新建文件夹——在新文件夹中——右键新建page(名字要一样)
3 wxml
组件:official::视图容器 | 微信开放文档 (qq.com)
<icon></icon>
:系统自带的图标。
<text></text> == <span></span> <view></view> == <div></div> <image></image> == <img></img> <navigator></navigator> == <a></a>
<navigator url='/pages/mine/mine'></navigator>
<navigator url='/pages/mine/mine' open-type='switchTab'></navigator>
<text bindtap="func"></text>
<text bindtap="func" data-nid='999' data-name='Bob'></text>
|
4 wxss
几乎和css一样,不同地方如下:
- 微信小程序宽度最大是750rpx。rpx不同于px,rpx会自动根据手机分辨率进行缩放。
其他建议:
5 js
API:official::基础 | 微信开放文档 (qq.com)
Page({ data: { }, func(e){ console.log(e.target.dataset.nid); console.log(e.target.dataset.name); } onLoad(options){}, })
|
wx.naviagteTo({ url: '/pages/xxx/xxx' })
wx.naviagteTab({ url: '/pages/xxx/xxx' })
|
6 获取数据
可以用js中动态获取数据,不用在wxml写死。语法类似vue。
wx:key
:通过key来确定唯一。official::WXML 语法参考 / 列表渲染 (qq.com)
<block></block>
:相当于是<template></template>
。在渲染时,该标签不会被实际渲染出来。
<tag hidden="true">
:hidden,是否隐藏。当hidden为true时,标签就会被隐藏,否则会显示。注意,这个和if是由区别的。当if不成立时,标签根本不会被渲染到页面中。而当hidden为true时,标签一样会渲染到页面上,只是相当于加了一个display: none;
。类似于vue中的v-if
和v-show
的区别。在开发中,如果有些数据有时候要展示有时候又不展示,建议使用hidden
,效率更高。
<view> <text>{{city}}</text> </view>
<view> <view>{{nameList[0]}}</view> <view>{{nameList}}</view> <view wx:for="{{nameList}}" wx:key="index">{{index}} -- {{item}}</view> <view wx:for="{{nameList}}" wx:for-index='idx' wx:for-item='ele' wx:key='idx'>{{idx}} -- {{ele}}</view> </view>
<view> <text wx:if="{{city=='Beijing'}}">北京</text> <text wx:elif="{{city=='Shanghai'}}">北京</text> <text wx:else>其他</text> </view>
<view> <text hidden="{{ifHidden}}">发现我了</text> </view>
|
Page({ data: { city: "Beijing", nameList: ["mugi", "mio", "uyi"], ifHidden: false }, })
|
<view> <view wx:if="{{city=='Beijing'}}"> <text>China</text> <text>Beijing</text> </view> </view>
<view> <block wx:if="{{city=='Beijing'}}"> <text>China</text> <text>Beijing</text> </block> </view>
|
7 修改数据
可以通过js相关API对数据进行修改。
在此处,数据并不是双向绑定的。也就是说当用户在input
输入框中输入值后,js中的值并不会立刻同步发生改变,需要执行一次this.setData({})
才会发生改变。
如果要实现双向绑定,可以给input
绑定上bindinput
事件,然后事件每次更新数据,这样就可以手动实现双向绑定。
当然现在微信也新增了双向绑定,只需要model:value="{{name}}"
即可实现双向绑定。(老版本微信可能使用后会报警告,需要再加上一个bindinput="func"
警告才会消除。绑定的函数可以没有任何内容,但是必须绑定一个函数)
input
的数据和之前的data-
绑定的数据获取方式有些不同。用data-
的数据会存在e.target.dataset
中,然后通过e.target.dataset.xxx
获取。而input
的数据是存在e.detail.value
中,通过e.detail.value
进行获取。如果是一个form
,里面的input
就需要定义名称,然后通过e.detail.value.xxx
进行获取
<view> <text>显示:{{name}}</text> <button bindtap="setName">点击后修改名字为Tom</button> </view>
<view> <form bindsubmit='setOneWayName'> <text>显示:{{oneWayName}}</text> <input type="text" name="inputValue" value="{{oneWayName}}" placeholder="单向绑定案例"/> <button formType="submit">点击后修改名字</button> </form> </view>
<view> <text>显示:{{twoWayName}}</text> <input type="text" value="{{twoWayName}}" placeholder="双向绑定案例" bindinput="setTwoWayName"/> </view>
<view> <text>显示:{{modelName}}</text> <input type="text" model:value="{{modelName}}" />
</view>
<view> <text>显示:{{addList}}</text> <button bindtap="addOne">加一个</button> </view>
|
Page({ data: { name: 'Bob', oneWayName: 'One', twoWayName: 'Two', modelName: 'Model', addList: ['我'] },
setName() { this.setData({ name: 'Tom' }) },
setOneWayName(e) { this.setData({ oneWayName: e.detail.value.inputValue }) },
setTwoWayName(e) { this.setData({ twoWayName: e.detail.value }) },
emptyFunc() {},
addOne() { let arr = this.data.addList arr = arr.concat('我') this.setData({ addList: arr }) } })
|
8 tabBar
文档:official::小程序配置 / 全局配置 (qq.com)
tabBar需要在全局配置中进行配置。只能配置最少 2 个、最多 5 个 tab。
{ "pages": [], "tabBar":{ "position": "bottom", "selectedColor": "#b4282d", "list": [ { "pagePath": "pages/index/index", "text": "首页", "iconPath": "images/index.png", "iconPath": "images/index_select.png", }, { "pagePath": "pages/my/my", "text": "我的" } ] }, }
|
9 json常见配置
{ "usingComponents": {}, "navigationBarBackgroundColor": "#01ccb6", "navigationBarTitleText": "", "enablePullDownRefresh": true, "navigationBarTextStyle": "white", "backgroundColor": "#01ccb6" }
|
10 导入图标
本导入图标的方式为阿里巴巴矢量库。
还有别的不同的方式:
阿里巴巴导入:
- 找到图标,加入到库。
- 在右边找到购物车,将图标加入到项目,没有就随便新建一个。
- 在顶端栏找到资源管理——我的项目——我发起的项目。
- 点击项目,点击Font class,点击查看在线链接,点击生成代码。
- 点击css链接,然后复制代码,在微信小程序的根目录下新建一个styles,然后新建一个iconfont.wxss,然后把代码放进去。
- 使用时,可以选择全局引入,也可以选择局部引入。
@font-face { font-family: "iconfont"; src: url('//at.alicdn.com/t/c/font_4582307_x7qu0xxxh4g.woff2?t=1718165133495') format('woff2'), url('//at.alicdn.com/t/c/font_4582307_x7qu0xxxh4g.woff?t=1718165133495') format('woff'), url('//at.alicdn.com/t/c/font_4582307_x7qu0xxxh4g.ttf?t=1718165133495') format('truetype'); }
.iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
.icon-renlianshibie_o:before { content: "\eb67"; }
.icon-xuanfeng:before { content: "\e607"; }
|
@import"./styles/iconfont.wxss";
|
三、常用API
1 界面API
相关API:official::界面 / 交互 / wx.showToast (qq.com)
wx.showToast
:中间的弹窗。
wx.showLoading
:加载中。
wx.showModel
:可确认和取消的弹窗。
wx.showActionSheet
:多选弹窗。
<view bindtap="myAlert">点我微信到账</view> <view bindtap="myModal">点我确认微信到账</view> <view bindtap="myActionSheet">点我选择微信到账金额</view>
|
Page({ data: { moneyList: ['1000', '2000', '3000'] },
myAlert() { wx.showLoading({ title: '等待到账' })
setTimeout(() => { wx.hideLoading()
successInfo() }, 2000) },
myModal() { wx.showModal({ title: '打钱', content: '要我给你打钱吗', success: (res) => { if (res.confirm) { successInfo() } else if (res.cancel) { errorInfo() } } }) },
myActionSheet() { wx.showActionSheet({ itemList: this.data.moneyList, success: (res) => { successInfo(this.data.moneyList[res.tapIndex]) }, fail: () => { errorInfo() } }) } })
function successInfo(money = 2000) { wx.showToast({ title: `微信到账${money}元`, icon: 'success', duration: 2000 }) }
function errorInfo() { wx.showToast({ title: '微信没有到账', icon: 'error', duration: 2000 }) }
|
2 网络API
通讯规则:official::基础能力 / 网络 / 使用说明 (qq.com)
相关API:official::网络 / 发起请求 / wx.request (qq.com)
wx.request
:向后端发送请求
wx.chooseImage
:选择图片(已放弃维护,新版本要用wx.chooseMedia
)
wx.chooseMedia
:选择媒体资源
wx.uploadFile
:上传图片
<view bindtap="submitData">点我发送网络包</view> <view bindtap="uploadFile">点我上传图片</view>
|
Page({ data: {},
submitData() { wx.request({ method: 'POST', url: 'http://127.0.0.1:8000/v1/info', data: { name: ['张三', '李四'], age: 18 }, header: { 'content-type': 'application/json' }, success: (res) => { console.log(res) }, fail: (err) => { console.log(err) } }) },
uploadFile() { wx.chooseMedia({ count: 1, mediaType: ['image'], sourceType: ['album', 'camera'], success(res) { const tempFilePaths = res.tempFilePaths wx.uploadFile({ url: 'http://127.0.0.1:8000/v1/upload', filePath: tempFilePaths[0], name: 'file', formData: { user: '张三' }, success: (res) => { console.log(res) }, fail: (err) => { console.log(err) } }) } }) } })
|