微信小程序
1.文件结构与配置
1.1页面结构
- wxml :结构,写标签代码
- wxss: 样式
- JS:ES 💥 没有DOM、BOM
- json: 配置
1.2最精简的结构
- appjs: 全删
- app.json:pages字段必须有;pages数组中,至少有一个页面
- pages/index:.json 保留json的{} ;.js 保留Page({})入口函数 ;wxml 全删 ;wxss 全删
1.3全局/页面配置
-
app.json文件中 ,更多配置参考
,💥默认情况下json文件不允许有注释,以下注释为笔记用
{ // pages 每个页面都要在此注册,默认情况下数组的第一个页面就是默认启动页,当配置的页面不存在相应文件时会自动创建 "pages": ["pages/lifeCycle/index","pages/test/test"], "window": { "navigationBarBackgroundColor": "#ff7043", //页面头部背景颜色 "navigationBarTitleText": "测试页面标题", //页面头部标题 "navigationBarTextStyle": "white", //头部标题文字颜色 black/white "navigationStyle": "default", //头部导航栏的 显示与隐藏 :default / custom "enablePullDownRefresh": true, //是否允许下拉刷新 "backgroundColor": "#00b26a" //下拉刷新的背景色 }, // 底部 tabBar导航栏配置 "tabBar": { //所有tabBar的页面都要在list中注册,且tabBar页面数量为 2~5 个 "list": [ { "pagePath": "pages/testone/index", //页面路径 "text": "启动页", //栏目名 "iconPath": "assets/icons/category.png", //栏目未被选中时的icon图标 "selectedIconPath": "assets/icons/category-o.png" //栏目被选中时的icon图标 }, { "pagePath": "pages/index/index", "text": "首页", "iconPath": "assets/icons/home.png", "selectedIconPath": "assets/icons/home-o.png" } ], "color": "#1d82fe", //栏目未被选中时的字体颜色 "selectedColor": "#ff7043" //栏目被选中时的字体颜色 } } -
页面.json文件中,可以配置一些app.json中window内的部分属性(直接配置,不用写window),不能配置tabBar,对当前页面而言,页面配置的代码优先级会高于全局配置
{ "navigationBarBackgroundColor": "#636aeb", "enablePullDownRefresh": true, "backgroundColor": "#636aeb", "navigationBarTitleText": "单页面配置", "navigationBarTextStyle": "black" }
2.模板语法
2.1插值表达式
-
变量声明在对应的
页面.js文件中Page({ data: { dataList: ["阿尼亚", "黄昏", "约尔", "次子"], inpValue: "", }, addFn() { // this.setData() 才能更新视图 //可同时更新多个变量 this.data.dataList.push(this.data.inpValue); this.setData({dataList:this.data.dataList,inpValue:''}) } }, }); -
在
页面.wxml中使用,<!-- 在属性中,当值为布尔型,数字,变量时,都要使用 {{}} 否则会被编译成字符串 --> <view class="content"> <input bindinput="changeFn" value="{{inpValue}}" type="text" placeholder="请输入添加词" style="border: 2px solid orange;" /> <button bindtap="addFn">点击添加</button> </view>
2.2wx:if和hidden
-
wx:if与v-if类似,条件为真才会创建渲染标签,通过创建与销毁标签来控制标签的显示隐藏
<!-- wx:if wx:elif wx:else => 类同 if elseif else 的逻辑线--> <view wx:if="{{true}}">标签未创建</view> -
hidden与v-show类似,不同点在于控制条件为真时,hidden会隐藏标签,原理是通过控制标签的CSS属性=>display:none控制标签的显示隐藏
<view hidden="{{true}}">标签隐藏</view>
2.3wx:for
-
wx:for与v-for类似,都是用于标签的循环渲染
-
wx:for依赖的数据变量定义在
页面.js文件中,数据变量可以是数组/对象/字符串 -
使用wx:for循环渲染的同时也要有wx:key ,目的也是按需更新
- 数据变量为简单数组或字符串时,一般 wx:key=" *this ",*this代指数组的每项元素
- 数组变量为对象数组时, wx:key ="对象中值唯一且不重复的键名",如: [{id:1,name:'张三'},{id:2,name:'李四'}] ,使用该数据渲染时,wx:key="id" ,💥不要用{{}}包裹键名
<!-- item和index为小程序默认的 每项元素 和 下标 的变量名 -->
<!-- 当要修改 每项元素 和 下标 的默认变量名,可通过 wx:for-item="value" wx:for-index="curIndex" 的模式修改变量名-->
<view wx:for="{{list}}" wx:key="*this">{{item}}=>{{index}}</view>
2.4事件绑定
-
语法:bind+事件名,如 bindtap(点击事件) / bindblur(失焦事件)等
-
事件绑定在标签上,事件函数声明在
页面.js文件中,与data同级,不用写在methods内 -
必须通过标签的自定义属性传参, tapFn(100) 此种写法编译时,小程序会判定tapFn(100)为函数名,而非tapFn()为函数名,自定义属性传递的参数可通过事件对象在函数中获取:event.target.dataset.自定义属性名
-
演示如下
<view bindtap="tapFn" data-index="1"></view>Page({ data:{}, clickFn(event){ //event.target.dataset.index 获取传递的参数 console.log(event.target.dataset.index) } })
2.5关于CSS样式的说明
- 小程序的CSS写法与原生CSS用法几乎一致,但以下两点须知:
- 小程序不支持通配符* ,因为小程序底层已对标签进行了样式默认值处理,如仍有标签样式要重置,可用并集选择器处理
- 新增相对单位rpx,视口宽度=750rpx=100vw,
3.小程序的标签
3.1view 和 text
-
view类似div标签,块级元素
-
text类似span标签,行内元素,具有以下特点:
- text标签提供user-select属性,允许用户长按选中复制文本
- text只能嵌套text
<view>块级元素</view> <text user-select>文本可被选中</text>
3.2image
-
类似img标签,用于显示图片,盒子具有默认宽高,320rpx*240rpx
-
src属性,支持绝对路径和在线链接
-
mode属性,用于设置图片的显示模式,常用如下:
- 默认值,用于缩略图,占满整个容器,图片可能变形
- aspectFit,等比例缩放,直到宽或高触碰到盒子边界,不会截断图片,可能有留白
- widthFix,需指定宽度,高度自适应
- heightFix,需指定高度,宽度自适应
-
lazy-load属性,长列表下图片的懒加载,以便提高加载速度
<image style="width: 750rpx;" mode="widthFix" src="{{image_src}}"></image>
3.3swiper轮播图
-
swiper只能放置, swiper-item组件
-
默认有高度,往往需要调整高度
-
默认滚动间隔为5秒,通常需要调整
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}"> <swiper-item> <view class="swiper-item {{item}}"></view> </swiper-item> </swiper>
3.4navigator
-
作用:跳转到小程序内部的页面和其它小程序中
-
url跳转注意点
- 以 / 开头
- 没有文件后缀
- 只有在pages中指定过路径列表的才能跳转
- 默认不能调到tabBar的list列表中
-
跳转模式open-type
- switchTab :可以允许跳转到tab页面,会清除掉历史记录,没有回退按钮
- redirect:不产生一条跳转的历史记录
- navigatorBack:回退一步,通常配置自定义导航栏、自定返回按钮,不需要写url,无效
- reLaunch:会清除掉所有的历史记录,重新打开某个页面,不常用, 小程序希望尽量缓存页面
-
url也可以传递参数,在跳转后的页面的onLoad函数的形参option中接收传递的参数
<view class="btn-area"> <navigator url="/page/navigate/navigate?title=navigate">跳转到新页面</navigator> <navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect">在当前页打开</navigator> <navigator url="/page/index/index" open-type="switchTab">切换 Tab</navigator> <navigator target="miniProgram" open-type="navigate" app-id="" path="" extra-data="" version="release">打开绑定的小程序</navigator> </view>
3.5button
-
open-type属性
- share 分享小程序
- feedback 反馈 💥慎用,用户投诉可能导致小程序被封禁
- contact 联系客服
- openSetting 打开设置=>向用户申请过的权限才能再次打开、关闭
- getPhoneNumber 获取手机号码
<button open-type="share" class="mini-btn" type="primary" size="mini">按钮</button>
3.6rich-text
-
nodes属性绑定要解析的html字符串
-
style 和 class 可以控制样式
-
id 和 标签不能控制样式
<!-- htmlSnip需在js文件中的data属性中定义 --> <rich-text nodes="{{htmlSnip}}"></rich-text>
4.自定义组件与组件通信
4.1自定义组件
-
创建组件=>文件结构必须有文件名: components/文件夹名/文件名
<!-- 组件文件名:ShopSubmitBar --> <view>子组件的内容</view> -
注册组件=> 哪个页面用,哪个页面的json文件: usingComponents: { "组件名": "绝对组件路径" }
{
"navigationBarTitleText": "商品详情页",
"enablePullDownRefresh": true,
"usingComponents": {
"shop-submit-bar": "/components/ShopSubmitBar/ShopSubmitBar"
}
}
- 使用与注意点=>区分大小写,文件夹名称、文件名称、 组件注册名称保持一致
<!-- 商品详情页页面文件中使用自定义组件 -->
<view>
<shop-submit-bar></shop-submit-bar>
</view>
4.2组件通信
4.2.1父传子
-
父组件-传 => 组件标签上,写:属性=“值”,值变量定义在
父组件.js文件中<shop-submit-bar goodsText="{{goodsText}}"></shop-submit-bar> -
子组件-接 => 语法
子组件.js文件中
Component({
properties: {
goodsText: {
type: String,
value: "默认值",
},
}
});
4.2.2子传父
-
给子组件绑定一个事件处理函数,并在组件中,定义方法: 在methods中定义
<view bindtap="handlerClick" class="box">被传递的值是{{title}}</view> -
子组件触发自定义事件:this.triggerEvent(“自定义事件名”, 参数)
Component({
properties: {
title: {
type: Object,
value: "默认值",
},
},
methods: {
handlerClick() {
this.triggerEvent("testEvent", this.data.title);
},
},
});
-
父组件监听自定义事件:bind自定义事件名 = "父组件中的处理函数"
<MyButton bindtestEvent="handevent" title="被传递的"></MyButton> -
父组件处理函数中, 获取形参 => 形参.detail
Page({
handevent(e) {
console.log(4, e);
console.log(5, e.detail);
},
});
5.生命周期函数
5.1应用级别
-
写在
app.js文件中 -
函数分类
App({ // 启动小程序,全局执行一次 获取初始数据, 如获取地理位置 onLaunch (e) { // console.log(e); }, // 小程序从后台切到前台会触发,启动时也会触发一次 收集一些需要统计的数据, 比如: 使用时长、时间段 onShow() { // console.log("切到前台了"); }, // 小程序从前台切到后台会触发, onHide() { // console.log("切到后台了"); }, //任何一处代码,有错误时自动触发,配合后台接口,上报异常(埋点) onError(e) {}, //切换日间、黑夜模式时;跟随系统,切换样式 onThemege(){} });
5.2页面级别
-
写在对应的
页面.js中 -
函数分类
// pages/testIndex.js Page({ //生命周期函数--监听页面加载 形参options可以接收页面跳转过来时候的url上的参数 //发送请求获取数据 onLoad(options) {}, // 生命周期函数--监听页面初次渲染完成 开启定时器、 获取标签等 onReady() {}, // 生命周期函数--监听页面显示 onShow() {}, //生命周期函数--监听页面隐藏 收集用于统计的数据, 💥某个页面的统计数据,可能要重新获取最新数据, 💥如购物车 onHide() {}, // 生命周期函数--监听页面卸载 做清除的动作,如清除定时器、缓存等 onUnload() {}, //页面相关事件处理函数--监听用户下拉动作 onPullDownRefresh() {}, //切换横竖屏幕时 响应对应UI尺寸 onResize(){}, //页面上拉触底事件的处理函数 上拉请求下一页数据 onReachBottom() {}, // 用户点击右上角分享 onShareAppMessage() {}, //用户转发朋友圈 onShareTimeline(){}, //用户收藏时 onAddToFavorites(){} })
5.3组件级别
-
写在
组件.js中 -
函数分类
Component({ //组件挂载时 发请求、开定时器 attached(){}, //组件卸载时 清除的动作、如清除定时器、缓存等 detached(){}, //别的方法函数 methods: {} })