前言 微信小程序,小程序的一种,英文名Wechat Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。(百度百科 )
注册
开发者工具
初始化项目 下载脚手架 1 npm install -g @wechat-miniprogram/miniprogram-cli
初始化项目 1 2 3 4 mkdir demo cd demo miniprogram init
构建项目 下载依赖
构建项目
构建完成后会在项目根目录生成miniprogram_dist目录
页面 目录结构 1 2 3 4 5 6 + pages + page - page.wxml - page.wxss - page.js - page.json
组件 内置组件
容器组件
区块组件
类似于Vue的<template></template>组件
文本组件
图片组件
src="":图片路径,小程序发布不允许超过2M,所以不建议图片本地化,最好使用URLmode="":图片裁剪缩放模式
scaleToFill:填充aspectFit:等比例缩放,同时保证长边完全显示,超出部分进行截取(谁先缩放到设定的值,谁就是长边)aspectFill:等比例缩放,同时保证短边完全显示,超出部分进行截取(谁后缩放到设定的值,谁就是短边)widthFix:等比例缩放,在保证不超出宽度的同时,高度自动变化heightFix:等比例缩放,在保证不超出高度的同时,宽度自动变化
按钮组件
size="":按钮尺寸
default:缺省值,默认尺寸mini:小尺寸
type="":按钮类型
default:缺省值,白色primarg:绿色warn:红色
disabled="false":按钮是否禁用form=type="":触发表单事件
submit:提交表单reset:重置表单
open-type="":微信开放能力
contact:打开客服对话share:触发转发功能,不能转发朋友圈getPhoneNumber:获取用户手机号(回调函数获取)getUserInfo:获取用户信息(回调函数获取)openSetting:打开授权设置页(只能管理已询问的授权)feedback:打开意见反馈
获取用户手机号
只有企业开发者才能使用
需要在回调函数getPhoneNumber()中获取
1 <button open-type="getPhoneNumber"></button>
1 2 3 4 5 Page ({ getPhoneNumber : function (event ) { console .log (event); } });
输入框组件
双向绑定 1 <input type="text" model:value="{{ key }}" />
1 2 3 4 5 Page ({ data : { key : "value" } });
单选框组件 1 2 3 <redio-group bind:change=""> <redio/> </redio-group>
多选框组件 1 2 3 <checkbox-group bind:change=""> <checkbox></checkbox> </checkbox-group>
轮播图组件 1 2 3 4 5 6 7 8 9 <swiper bind:change=""> <swiper-item> <image></image> </swiper-item> <swiper-item> <image></image> </swiper-item> </swiper>
自定义模版
旧版微信小程序没有自定义组件,组件化开发时只能使用自定义模板,新版微信小程序有自定义组件,组件化开发时可以使用自定义组件,自定义模板不再被需要
定义自定义模版
name="":定义模版时指定的名字
pages/page/page.wxml 1 2 3 <template name=""> ... </template>
使用自定义模版
is="":调用模版,指定对应的模版名。也可以通过三目运算,判定使用哪个模版data="":指定需要传入的数据
pages/page/page.wxml 1 2 3 <template is="" data=""> ... </template>
pages/page/page.wxml 1 <template is="" data="" />
自定义组件 目录结构 1 2 3 4 5 6 + components + component - component.wxml - component.wxss - component.js - component.json
定义自定义组件
component:定义是否是组件
true:组件
usingComponents:定义依赖的其他组件
compomemts/compomemt/component.json 1 2 3 4 { "component" : true , "usingComponents" : { } }
compomemts/compomemt/component.js 1 2 3 4 5 Component ({ properties : {}, data : {}, methods : {} });
使用自定义组件 pages/page/page.json 1 2 3 4 5 { "usingComponents" : { "component" : "../components/component/component" } }
pages/page/page.wxml
pages/page/page.wxml
组件样式隔离
styleIsolation:定义样式隔离
isolation:使用class定义的样式,页面与组件样式不会相互影响apply-shared:使用class定义的样式,页面样式会影响组件样式shared:使用class定义的样式,页面与组件样式会相互影响
compomemts/compomemt/component.js 1 2 3 4 5 Component ({ options : { styleIsolation : "isolation" } });
父子组件数据传递 父页面传递数据给子组件
子组件接收父组件可能传递的数据
compomemts/son/son.json
compomemts/son/son.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Component ({ properties : { key : { type : String , value : "default" }, key2 : { type : Number }, key3 : { type : Boolean }, key4 : { type : Object }, key5 : { type : Array }, key6 : { type : null } } });
compomemts/son/son.wxml
父组件引入子组件时传递数据
pages/father/father.json 1 2 3 4 5 { "usingComponents" : { "son" : "../components/son/son" } }
pages/father/father.wxml
父页面传递样式给子组件
父页面传递class给子组件,并在父页面定义对应class的样式
子组件接收父组件可能传递的类名
compomemts/son/son.json
compomemts/son/son.js 1 2 3 Component ({ externalClasses : ["k" ] });
compomemts/son/son.wxml
父组件引入子组件时传递类名,并在父组件中定义样式
pages/father/father.json 1 2 3 4 5 { "usingComponents" : { "son" : "../components/son/son" } }
pages/father/father.wxml
pages/father/father.wxss
子组件传递事件给父页面
子组件发送事件给父组件
compomemts/son/son.json
compomemts/son/son.js 1 2 3 4 5 6 7 Component ({ methods : { fn : function ( ) { this .triggerEvent ("sonFn" , "value" ); } } });
compomemts/son/son.wxml 1 <view bind:tap="fn"></view>
父组件监听子组件发送的事件
pages/father/father.json 1 2 3 4 5 { "usingComponents" : { "son" : "../components/son/son" } }
pages/father/father.js 1 2 3 4 5 Page ({ onSonFn : function (event ) { console .log (event.detail ); } });
pages/father/father.wxml 1 <son bind:sonFn="onSonFn" />
父页面直接调用子组件的函数
子组件定义函数
compomemts/son/son.json
compomemts/son/son.js 1 2 3 4 5 6 7 Component ({ methods : { sonFn : function ( ) { ... } } });
父组件引入子组件,并通过选择器得到子组件对象,然后通过子组件对象调用子组件定义的函数
pages/father/father.json 1 2 3 4 5 { "usingComponents" : { "son" : "../components/son/son" } }
pages/father/father.js 1 2 3 4 5 6 Page ({ fn : function ( ) { const son = this .selectComponent (".son" ); son.sonFn (); } });
pages/father/father.wxml
插槽
子组件预留插槽插入位置
compomemts/son/son.json
compomemts/son/son.wxml 1 2 3 4 <view> <!-- 预留插槽插入位置 --> <slot></slot> </view>
父组件引入子组件时向插槽插入元素
pages/father/father.json 1 2 3 4 5 { "usingComponents" : { "son" : "../components/son/son" } }
pages/father/father.wxml 1 2 3 4 <son> <!-- 引入子组件时向指定名称的插槽插入元素 --> <view></view> </son>
多插槽
子组件启用多插槽,并预留多个插槽位置,通过name属性区分
compomemts/son/son.json
compomemts/son/son.wxml 1 2 3 4 5 <view> <!-- 预留多个插槽插入位置 --> <slot name="slotName1"></slot> <slot name="slotName2"></slot> </view>
父组件引入子组件时向指定名称的插槽插入元素
pages/father/father.json 1 2 3 4 5 { "usingComponents" : { "son" : "../components/son/son" } }
pages/father/father.wxml 1 2 3 4 5 <son> <!-- 引入子组件时向指定名称的插槽插入元素 --> <view solt="slotName1"></view> <view solt="slotName2"></view> </son>
混入 定义被混入的对象 behaviors/main.js 1 2 3 4 5 6 7 8 9 10 export const main = { data : { key : "value" }, methods : { fn : function ( ) { console .log (this .data .key ); } } }
在其他组件中混入对象 components/component/component.js 1 2 3 4 5 import { main } from "../../behaviors/main" Component ({ behaviors : [main], });
生命周期 组件的生命周期函数
组件的生命周期函数全部需要在lefetimes属性中定义
components/component/component.js 1 2 3 4 5 6 7 8 9 Component ({ lefetimes : { created : function ( ) {}, attached : function ( ) {}, ready : function ( ) {}, moved : function ( ) {}, detached : function ( ) {} } });
组件所在的页面的生命周期函数 components/component/component.js 1 2 3 4 5 6 Component ({ pageLifetimes : { show : function ( ) {}, hide : function ( ) {} } });
JSON 全局配置和页面配置 全局配置
pages:页面路由,第一行默认为首页
app.json 1 2 3 4 5 6 7 8 { "pages" : [ "pages/index/index" , "pages/logs/logs" ] , "style" : "v2" , "sitemapLocation" : "sitemap.json" }
页面配置
pages/page/page.json
WXML
内置指令 wx:if
1 2 3 <view wx:if="{{ 布尔表达式 }}"></view> <view wx:elif="{{ 布尔表达式 }}"></view> <view wx:else></view>
hidden
不论是否符合条件,组件都会渲染
不符合条件时,组件会被设置为`style=”display: none;”
1 <view hidden="{{ true }}"></view>
所有指令的缺省值都为true
wx:for
wx:for指令通常在<block></block>组件中使用
wx:for-index="index":定义当前遍历的索引,缺省值为indexwx:for-item="item":定义当前遍历的元素,缺省值为itemwx:key="":定义当前遍历的元素的唯一标识符,用于加速渲染
*this:指代当前遍历的对象
1 2 3 <block wx:for="{{ 可迭代对象 }}" wx:key="*this"> {{ index }} {{ item }} </block>
遍历数字
1 2 3 <block wx:for="{{ 10 }}" wx:key="*this"> {{ index }} {{ item }} </block>
遍历字符串
1 2 3 <block wx:for="文本内容" wx:key="*this"> {{ index }} {{ item }} </block>
WXSS
单位
rpx是微信小程序特有的尺寸单位,1rpx表示在屏幕为iPhone6(750px * 375px)的环境下的1px,当屏幕不为iPhone6时1rpx实际显示尺寸会跟随屏幕尺寸的改变而改变
JS
用于定义回调函数,回调函数由微信小程序引擎调用,不能直接在视图层调用
全局对象和页面对象
全局对象 app.js 1 2 3 4 5 6 7 8 9 10 App ({ data : {}, fn : function ( ) {}, onLaunch : function (options ) {}, onShow : function (options ) {}, onHide : function ( ) {}, });
页面对象 pages/page/page.js 1 2 3 4 5 6 7 8 Page ({ data : {}, fn : function ( ) {}, onLoad : function ( ) {}, });
在页面对象中获取全局对象定义的数据 app.js 1 2 3 4 5 App ({ globalData : { key : "value" }, });
pages/page/page.js 1 2 3 4 5 6 7 Page ({ onLoad : function ( ) { const app = getApp (); console .log (app.globalData .key ); }, });
WXS
WXS用于定义可以在视图层中直接调用的函数
WXS中必须通过module=""定义模块名
WXS中必须通过CommonJS语法将函数导出才可以在WXML中使用
在WXML中通过模块名.函数名的方式调用WXS中定义的函数
WXS中不能使用ES6语法
WXS中不能调用其他JS文件定义的回调函数
WXS中不能调用微信小程序内置API
官方文档
通过内联标签引入WXS 1 2 3 4 5 6 7 8 9 10 11 <wxs module="utils"> function sum(a, b) { return a + b; } module.exports = { sum: sum } </wxs> <view> {{ utils.sum(1, 2) }} </view>
通过外部文件引入WXS utils/utils.wxs 1 2 3 4 5 6 7 function sum(a, b) { return a + b; } module.exports = { sum: sum }
1 2 3 <wxs module="utils" src="/utils/utils.wxs"></wxs> <view>{{ utils.sum(1, 2) }}</view>
响应式数据 1 2 3 4 5 6 7 8 9 10 11 12 Page ({ data : { key : "value" }, fn : function ( ) { console .log (this .data .key ); this .setData ({ key : "" }); } });
pages/page/page.wxml 1 2 <!-- 渲染数据 --> <view>{{ key }}</view>
事件
在JS中定义回调函数 1 2 3 4 5 Page ({ fn : function (event ) { console .log (event); } });
在WXML中指定事件的回调函数 在捕获阶段执行回调函数 允许冒泡 1 <view capture-bind:tap="fn"></view>
阻止冒泡 1 <view capture-catch:tap="fn"></view>
在冒泡阶段执行回调函数 允许冒泡 1 <view bind:tap="fn"></view>
1 <view bindtap="fn"></view>
阻止冒泡 1 <view bind:catch="fn"></view>
1 <view bindcatch="fn"></view>
事件的参数传递 通过dataset传递参数
当前事件回调函数只能拿到当前组件的dataset参数
在WXML中定义参数
1 <view bind:tap="fn" data-key="value"></view>
在JS中接收参数 1 2 3 4 5 Page ({ fn : function (event ) { console .log (event.currentTarget .dataset .key ); } });
通过mark传递参数
当前事件回调函数可以拿到当前页面所有组件的mark参数
在WXML中定义参数
1 <view bind:tap="fn" mark:key="value"></view>
在JS中接收参数 1 2 3 4 5 Page ({ fn : function (event ) { console .log (event.mark .key ); } });
微信小程序内置API 弹窗 1 2 3 4 wx.showToast ({ title : "标题" , icon : "loading" , });
1 2 3 wx.showLoading ({ title : "标题" , });
1 2 3 4 5 6 7 8 9 10 11 12 wx.showModal ({ title : "标题" , content : "描述" , success : function (res ) { if (res.confirm ) { console .log ("用户点击确定" ); } if (res.cancel ) { console .log ("用户点击取消" ); } } });
1 2 3 wx.showActionSheet ({ itemList : [], });
分享 1 2 3 4 5 6 7 8 9 Page ({ onShareAppMessage : function ( ) { return { title : "标题" , path : "/pages/page/page" , imageUrl : "/assets/logo.png" , } } });
获取用户信息 1 2 3 4 5 wx.getSystemInfo ({ success : function (res ) { console .log (res); } });
获取当前位置信息 app.json 1 2 3 4 5 6 7 { "permission" : { "scope.userLocation" : { "desc" : "请求授权位置信息" } } }
1 2 3 4 5 wx.getLocation ({ success : function (res ) { console .log (res); } });
缓存 同步缓存 添加缓存 1 wx.setStorageSync ("key" , "value" );
微信小程序的缓存可以直接存储JS对象,而无需序列化
1 wx.setStorageSync ("obj" , {});
获取缓存 1 const value = wx.getStorageSync ("key" );
删除缓存 1 wx.removeStorageSync ("key" );
清空缓存
异步缓存 添加缓存
encrtpt:是否加密
false:缺省值,不加密true:加密
1 2 3 4 5 6 7 8 wx.setStorage ({ key : "key" , data : "value" , encrtpt : false , success : function (res ) { console .log (res); } });
获取缓存 1 2 3 4 5 6 7 wx.getStorage ({ key : "key" , encrtpt : false , success : function (res ) { console .log (res); } });
请求 1 2 3 4 5 6 wx.request ({ url : "<url>" , success : function (res ) { const body = res.data ; } });
获取用户信息 1 2 3 4 5 6 wx.getUserProfile ({ desc : "文本内容" , success : function (res ) { console .log (res); } });
获取媒体文件 1 2 3 4 5 6 wx.choseMedia ({ mediaType : ["image" , "video" ], success : function (res ) { console .log (res.tempFiles [0 ].tempFilePath ); } });
登录 1 2 3 4 5 wx.login ({ success : function (res ) { console .log (res.code ); } });
路由 WXML
open-type="":页面跳转方式
exit:关闭小程序navigateTo:打开新页面。只可以跳转非tabBar页面(新页面进栈)navigateBack:返回上一页。(将当前页面移出页面栈)switchTab:打开新页面。只可以跳转tabBar页面(将所有页面移出页面栈,新页面进页面栈)reLaunch:打开新页面。可以跳转任意页面(将所有页面移出页面栈,新页面进页面栈)rediirect:页面重定向。(当前页面出栈,新页面进栈)
url="":跳转页面的路径,只能是相对路径name="":携带自定义参数,可以在onLoad()通过options属性调用
pages/page/page.wxml 1 <navigator open-type="navigateTo" url="/pages/logs/logs?key=value"></navigator>
JS 获取所有路由 1 const pages = getCurrenPages ();
页面导航
1 2 3 wx.navigateTo ({ url : "/pages/page/page" , });
传递参数 pages/page/page.js 1 2 3 4 5 6 7 Page ({ fn : function ( ) { wx.navigateTo ({ url : "/pages/logs/logs?key=value" , }); } });
pages/logs/logs.js 1 2 3 4 5 Page ({ onLoad : function (options ) { console .log (options.key ); } });
页面返回
delta:返回层级,缺省值为1
1 2 3 wx.navigateBack ({ delta : 1 });
传递参数 直接为上一页设置数据
pages/logs/logs.js 1 2 3 4 5 6 7 Page ({ onUnload : function ( ) { const pages = getCurrenPages (); const prevPage = pages[pages.length - 2 ]; prevPage.setData ({ key : "value" }); } });
在前一页定义回调函数
pages/page/page.js 1 2 3 4 5 6 7 8 9 10 11 12 Page ({ fn : function ( ) { wx.navigateTo ({ url : "/pages/logs/logs" , events : { callBack : function (data ) { console .log (data); } } }); } });
pages/logs/logs.js 1 2 3 4 5 6 7 Page ({ onUnload : function ( ) { const eventChannel = this .getOpenerEventChannel (); const data = { key : "value" }; eventChannel.emit ("callBack" , data); } });
完成 参考文献 哔哩哔哩——Python小清风 哔哩哔哩——黑马程序员