小程序的页面放在pages文件夹下,在app.json文件中指定哪些page是页面
在小程序中,一般一个pages由4个文件组成:
wxml:页面骨架内容,比如按钮
waxes:页面样式
js:页面逻辑,如跳转
json:页面配置
app.js、app.json(入口文件,必须有,没有项目运行不起来)、app.wxss不能改名,是应用程序级别的文件,在这里面写的代码全局生效,page里面的那4个文件是页面级别的,在里面写的代码只在当前页面生效,page里面写的代码是针对页面的,所以会覆盖全局的配置
project.config.json:当前项目的配置
视图容器view组件及属性和快捷布局技巧
官方文档
view标签相当于div标签,都是块级元素,独占一行,属性有:
index.wxml的内容:
<view
class="box"
hover-class="boxhover"
>
手指按下去后,hover-class属性的值会被添加到这个view标签上来
<view
class="inner"
hover-class="innerhover"
hover-stop-propagation>
等同于hover-stop-propagation = "true",用于阻止冒泡。点击这个view后,只有这个view变色,因为冒泡行为被阻止了
</view>
</view>
index.wxss的内容:
.boxhover{
background: palegreen;
}
.box .inner{
width: 80px;
height: 80px;
background: pink;
}
.box .innerhover{
background: red;
}
输入
.name>.box
并按下回车,会出现
<view class="name">
<view class="box"></view>
</view>
基础内容组件text、icon、progress组件属性
text标签
text标签的属性值如下:
<view>
<text decode>< decode用于解码特殊字符 > </text>
<text user-select>user-select:用户可以点击选择,该属性会使文本节点显示为inline-block。</text>
<text space="nbsp"> space 的属性值用于指定空格的大小</text>
</view>
样式如下:
注意:
- decode可以解析的有
< > & '    
- 各个操作系统的空格标准并不一致。
- text 组件内只支持 text 嵌套。
除了文本节点以外的其他节点都无法长按选中
icon标签(了解)
官方提供的一些图标,属性值如下:
<view>
<icon type="success"/>
<icon type="search" size="50px" color="pink"/>
</view>
progress标签(了解)
用于展示进度条的标签,属性值如下:
<view>
<progress percent="77" show-info border-radius="10" stroke-width="3"/>
</view>
注意:属性的长度单位默认为px
响应式自适应单位rpx与px的差异
rpx:可以根据屏幕宽度进行自适应
px:固定大小
建议以iPhone6为基准,iPhone像素为750px,此时1px=2rpx,即375px,微信小程序开发工具的机型就是375rpx,那么此时设计稿上是多少px,你代码里就写多少rpx
scroll-view可滚动视图区域组件
本节只示范以下两个属性值:
允许纵向滚动:
<scroll-view class="myScroll" scroll-y>
<view class="row">1</view>
<view class="row">2</view>
<view class="row">3</view>
<view class="row">4</view>
<view class="row">5</view>
<view class="row">6</view>
<view class="row">7</view>
<view class="row">8</view>
</scroll-view >
样式如下:
.myScroll{
width: 100%;
height: 220rpx;
background: #eeeeee;
}
.myScroll .row{
width: 220rpx;
height: 220rpx;
background: palegoldenrod;
margin-right: 20rpx;
}
允许横向滚动:
.myScroll{
width: 100%;
height: 220rpx;
background: #eeeeee;
white-space: nowrap;/*让子元素在一行展示*/
}
.myScroll .row{
width: 220rpx;
height: 220rpx;
background: palegoldenrod;
margin-right: 20rpx;
display: inline-block;/*让块级元素在一行展示*/
}
/*清除最后一个元素的右边距,不然最后一个元素右边会有空格*/
.myScroll .row:last-child{
margin-right: 0;
}
如果不清除最后一个元素的右边距,那么最后一个元素的右边到屏幕会有一些空白,如下图最右边的白边
movable-area自由移动
movable-area与movable- view结合使用可以实现在某个区域内随意移动。movable-area用于设置可移动区域,属性如下:
movable-view是可移动的视图容器,在页面中可以拖拽滑动,该标签必须在movable-area标签中,并且必须是直接子节点,否则不能移动。部分属性如下:
<movable-area style="width:400rpx;height:400rpx;background:#ccc;overflow:hidden;">
<movable-view direction="all" inertia out-of-bounds x="20rpx" y="20rpx">
<view>demo</view>
</movable-view>
</movable-area>
注意:
- movable-view必须设置width和height属性,不设置默认为10px
- movable-view 默认为绝对定位,top和left属性为0px
- movable-area 必须设置width和height属性,不设置默认为10px
- 当movable-view小于movable-area时,movable-view的移动范围是在movable-area内;
- 当movable-view大于movable-area时,movable-view的移动范围必须包含movable-area(x轴方向和y轴方向分开考虑)
match- media响应
满足指定的media query规则时,这个节点才会被展示。通过这个节点可以实现“页面宽高在某个范围时才展示某个区域”这样的效果。属性值如下:
<match-media min-width="300" max-width="600">
<view>当页面宽度在 300 ~ 500 px 之间时展示这里</view>
</match-media>
<match-media min-height="400" orientation="landscape">
<view>当页面高度不小于 400 px 且屏幕方向为纵向时展示这里</view>
</match-media>
root- portal子树从页面中脱离出来
使整个子树从页面中脱离出来,类似于在 CSS 中使用 fixed position 的效果。主要用于制作弹窗、弹出层等。现在我们有4个view,box1的z-index的值假如为10,box2的z-index的值假如为9,那么box2的子元素mask的z-index无论多大都不能遮盖box1,实例代码:
<view class="out">
<view class="box1"></view>
<view class="box2">
<view class="mask">mask的父级元素box2不如box2上面那个元素bo1的层级(z-index的值)高,那mask的层级再大也无法遮盖住box1</view>
</view>
</view>
.out .box1{
position: relative;
z-index: 10;
width: 300rpx;
height: 300rpx;
background: #77c1fc;/*蓝色*/
}
.out .box2{
position: relative;
width: 350rpx;
height: 350rpx;
background: palegoldenred;
z-index: 9;
left: 100px;
top: -100px;
}
.out .box2 .mask{
width: 100%;
height: 100%;
background: #000;
position: fixed;/*固定定位*/
top: 0;
left: 0;
z-index: 11;
}
如何解决这个问题:
- 不要把mask放在层级较低的box2里面
- mask使用root- portal标签包裹,root- portal会将mask从页面中脱离出来,所以mask的样式代码应该写在app.wxss中作为全局样式:
.mask{
width: 100%;
height: 100%;
background: #000;
position: fixed;/*固定定位*/
top: 0;
left: 0;
z-index: 11;
}
页面的样式文件index.wxss代码如下:
.out .box1{
position: relative;
z-index: 10;
width: 300rpx;
height: 300rpx;
background: #77c1fc;/*蓝色*/
}
.out .box2{
position: relative;
width: 350rpx;
height: 350rpx;
background: palegoldenred;
z-index: 9;
left: 100px;
top: -100px;
}
页面代码如下:
<view class="out">
<view class="box1"></view>
<view class="box2">
<view class="mask">mask的父级元素box2不如box2上面那个元素bo1的层级(z-index的值)高,那mask的层级再大也无法遮盖住box1</view>
</view>
</view>
app.json全局及页面设置
一、app.json全局配置的官方文档
二、如果想新建一个页面,那么在app.json的pages中添加一个路径并保存,会自动创建文件夹及所需的四个文件。默认普通编译的情况下,页面的渲染是按照app.json中pages中的顺序来渲染的,也就是说app.json中pages的第一个文件会最先渲染,所以如果你想让某个页面最先渲染可以把他放在app.json中pages的第一位,还可以【添加编译模式】,点击【普通编译】,选择【添加编译模式】,启动页面选择你想第一个显示的页面即可
三、windows属性用于指定全局的默认窗口表现
四、页面配置index.json的官方文档
媒体组件image的src的三种引入方式
/miniprogram表示在根目录下的miniprogram文件夹
<image src="../../images/database.png" mode=""/>
<image src="/miniprogram/images/deploy_step1.png" mode=""/>
<!-- 如果图片比较大或者比较多,建议把图片放在服务器上,然后通过下面的方式引入服务器上的图片地址 -->
<image src="https://image.baidu.com/search/albumsdetail?tn=albumsdetail&word=航拍地球系列&fr=albumslist&album_tab=设计素材&album_id=312&rn=30" mode=""/>
mode图片裁剪模式及其他属性
一、图片的默认宽高是320px*240px,所以我们上传的图片可能会被压缩变形,通过image标签的mode属性可以指定图片裁剪、缩放的模式,mde部分属性值如下所示,重点关注前5个缩放模式,其余属性值详见官方文档
二、image标签其他重要属性:
video视频组件及uniclound云存储网络地址的用法
navigator页面链接导航
app.js中的生命周期函数与globalData
app.js中的默认代码:
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
console.log("校验登录信息,与服务器的交互在这里处理")
this.globalData.message = "在App对象里通过this操作全局数据"// this指向当前对象
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log("进入小程序会触发,该方法会被多次触发。一般在这里读取缓存信息")
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
console.log("离开小程序触发")
},
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
},
globalData:{
message:"globalData中存放全局数据"
}
})
在其他page的js文件中获取全局数据:
const app = getApp()// 获取app.js中整个App()对象
console.log(app.globalData.message)// 获取全局数据并使用
page内的onload及data差值表达式
page内的index.js默认代码如下:
Page({
/**
* 页面的初始数据
*/
data: {
name:"cara",// 页面的局部变量
age:18,
bool:false,
num:3,
books:["孙子兵法","红楼梦"],
user:{
name:"高启强",
age:50,
gender:"男"
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log("index内的onload")
setTimeout(() => {
this.setData({
name:"77"
})
}, 2000);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
页面会先执行app的onlaunch,再执行app的onshow,然后执行index.js的onlaunch
data中不同数据类型渲染及if条件渲染
使用{{}}
在当前page的.wxml中使用数据(.js文件同上一节):
<view>my name is:{{name}}</view>
<!-- 数组类型数据展示: -->
<view>书籍:{{books}}</view>
<!-- 对象类型数据展示: -->
<view>{{user.name}} - {{user.age}} - {{user.gender}}</view>
<view>
<text wx:if="{{bool}}">1</text>
<text wx:elif="{{false}}">2</text>
<text wx:elif="{{num == 3}}">3</text>
<text wx:else>error</text>
</view>
在小程序开发中,不管是表达式、布尔值、变量、常量、都要写在{{}}
中
for循环列表渲染的用法
官方文档
上一节我们使用{{books}}
直接展示数组,得到的是数组中所有的内容:孙子兵法、红楼梦,我们可以使用 wx:for="{{数组名}}"
遍历展示数组:
<view wx:for="{{books}}" wx:key="index">
{{index}}: {{item}}
</view>
<!--
0:孙子兵法
1:红楼梦
-->
默认情况下,index是下标索引,item是数据,使用wx:for-item
可以指定数组当前元素的变量名,使用wx:for-index
可以指定数组当前下标的变量名:
<view wx:for="{{books}}" wx:for-index="idx" wx:for-item="itemName" wx:key="index">
{{idx}}: {{itemName}}
</view>
<!--
0:孙子兵法
1:红楼梦
-->
和vue一样,需要为每个遍历项指定key,如不提供wx:key,会报一个warning,如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
bindtap小程序中的事件触发
在组件中绑定一个事件处理函数。如bindtap
,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。使用data-参数名="参数值"
向方法传参。
<view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
在相应的Page定义中写上相应的事件处理函数,参数是event。
Page({
tapName: function(event) {
console.log(event);
console.log(event.currentTarget.dataset.hi);// Weixin
}
})
可以看到log出来的信息大致如下:
{
"type":"tap",
"timeStamp":895,
"target": {
"id": "tapTest",
"dataset": {
"hi":"Weixin"
}
},
"currentTarget": {
"id": "tapTest",
"dataset": {
"hi":"Weixin"// 传过来的参数
}
},
"detail": {
"x":53,
"y":14
},
"touches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}],
"changedTouches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}]
}
表单组件button
官方文档
给button添加一些属性即可,属性详见上述官方文档,部分属性如下:
<button type="primary" disabled="true" plain="true">不可点击的按钮</button>
<button class="mini-btn" type="default" size="mini">按钮</button>
size="mini"时按钮是行内元素
size="default"时按钮是块级元素
input、textarea输入框组件
官方文档
一、给input添加一些属性即可,属性详见上述官方文档,部分属性如下:
- type属性用于指定调用的键盘类型
- 调用的键盘的enter键的名称由
confirm-type
属性控制,取值如下:
- 其余部分属性如下:
<input class="weui-input" auto-focus placeholder="将会获取焦点"/>
<input class="weui-input" maxlength="10" placeholder="最大输入长度为10" />
<input class="weui-input" type="number" placeholder="这是一个数字输入框" />
<input class="weui-input" password type="text" placeholder="这是一个密码输入框" />
<input class="weui-input" placeholder-style="color:#F76260" placeholder="占位符字体是红色的" />
二、事件
- 实时获取输入框的值:
<view class="page-section">
<view class="weui-cells__title">实时获取输入值:{{inputValue}}</view>
<view class="weui-cells weui-cells_after-title">
<input class="weui-input" maxlength="10" bindinput="bindKeyInput" placeholder="输入同步到view中"/>
<!-- 输入框没有内容,按钮为禁用状态,输入框有内容,按钮为可点击状态 -->
<button type="primary" disabled="{{!inputValue.length}}" plain="true">不可点击的按钮</button>
</view>
</view>
Page({
data: {
inputValue: ''
},
bindKeyInput: function (e) {
this.setData({
inputValue: e.detail.value
})
}
})
- 输入框聚焦和失去焦点的方法、点击确定按钮触发的事件:
<view class="page-section">
<view class="weui-cells__title">实时获取输入值:{{inputValue}}</view>
<view class="weui-cells weui-cells_after-title">
<input class="weui-input" maxlength="10" bindinput="bindKeyInput" placeholder="输入同步到view中"/>
</view>
</view>
Page({
data: {
inputValue: ''
},
bindfocus: function (e) {
console.log(e)
},
bindblur: function (e) {
console.log(e)
},
bindconfirm: function (e) {
console.log(e)
}
})
三、textarea组件同input组件
checkbox-group、checkbox多选按钮及label组件
一、checkbox-group多项选择器,内部由多个checkbox组成,也就是说checkbox包裹在checkbox-group中。checkbox-group只有一个属性bindchange,当内部的checkbox选项改变时会触发
二、checkbox属性有以下4个:
<checkbox-group bindchange="checkboxChange">
<view style="padding-bottom: 20rpx">
<label>
<checkbox value="0" checked/>
<text>钓鱼</text>
</label>
</view>
<view style="padding-bottom: 20rpx">
<label>
<checkbox value="1"/>
<text>读书</text>
</label>
</view>
<view style="padding-bottom: 20rpx">
<label>
<checkbox value="2"/>
<text>打游戏</text>
</label>
</view>
</checkbox-group>
每次选项改变时都会调用:
Page({
bindchange: function (e) {
console.log(e)
}
})
使用label标签包裹checkbox和text可以实现:点击text的内容也能选中该选项
原生API:showToast提示框
接口所有属性
<button type="primary" bindtap="clickBtn">按钮</button>
Page({
clickBtn() {
wx.showToast({
title: '成功',
icon: 'success',
duration: 2000,
mask: true,
success:res=>{
console.log(res)
}
})
}
})
注意:
- img优先级高于icon
- 弹窗出现时就会调用
success
回调函数
原生API:showModal模态对话框
该API属性如下:
<button type="primary" bindtap="clickBtn">按钮</button>
Page({
clickBtn() {
wx.showModal({
title: '提示',
content: '这是一个模态弹窗',
success (res) {
console.log(res)
}
})
}
})
回调函数及回调函数的参数如下
原生API:showLoading、hideLoading加载中提示框
一、showLoading显示loading提示框。需主动调用wx.hideLoading
才能关闭提示框
二、showLoading的属性:
三、hideLoading的属性:
<button type="primary" bindtap="clickBtn">按钮</button>
Page({
clickBtn() {
wx.showLoading({
title: '加载中',
mask:true
})
},
setTimeout(() => {
wx.hideLoading()
}, 2000);
})
原生API:showActionSheet显示操作菜单
属性如下:
回调函数的参数如下:
<button type="primary" bindtap="clickBtn">按钮</button>
Page({
clickBtn() {
wx.showActionSheet({
itemList: ['A', 'B', 'C'],
success (res) {
console.log(res.tapIndex)// 打印用户点击的按钮序号,从上到下的顺序,从0开始
},
fail (res) {
console.log(res.errMsg)
}
})
}
})
常见的导航API接口
wx.showNavigationBarLoading
:上方导航栏显示loading
wx.setNavigationBarTitle
:设置当前页面的标题
wx.setNavigationBarColor
:设置页面导航条颜色
wx.hideNavigationBarLoading
:在当前页面隐藏导航条加载动画
wx.hideHomeButton
:隐藏上方导航栏返回首页按钮
全局与页面配置中关于window窗口UI设置
官方文档
一、app.json中有个参数entryPagePath
用于指定小程序的默认启动路径(首页),常见情景是从微信聊天列表页下拉启动、小程序列表启动等。如果不填,将默认为 pages 列表的第一项。不支持带页面路径参数。
{
"entryPagePath": "pages/index/index"
}
二、window对象用于设置小程序的状态栏、导航条、标题、窗口背景色。常用属性如下:
没有交互的页面不需要下拉刷新功能
tabBar底部tab栏的配置用法
如果小程序是一个多tab应用(客户端窗口的底部或顶部有tab栏可以切换页面),可以通过tabBar配置项指定tab栏的表现,以及tab切换时显示的对应页面。有如下属性:
各属性含义如下:
代码如下:
另外,list接受一个数组,只能配置最少2个、最多5个 tab。tab按数组的顺序排序,每个项都是一个对象,其属性值如下:
API中navigate路由接口与组件的关系
官方文档
一、可以通过navigator组件进行跳转,部分属性如下:
其余属性详见官方文档
<view class="btn-area">
<navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>
<navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator>
</view>
wx.navigateTo
:保留当前页面,跳转到应用内的某个页面。但是不能跳到tabbar页面。使用wx.navigateBack
可以返回到原页面。使用该方法跳转到下一个页面后,可以点击左上角<返回上一个页面
wx.redirectTo
:关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到tabbar页面
wx.switchTab
:跳转到tabBar页面,并关闭其他所有非tabBar页面,允许跳转到tabbar页面,可以携带参数
wx.reLaunch
:关闭所有页面,打开到应用内的某个页面,允许跳转到tabbar页面,不可以携带参数
wx.navigateBack
:关闭当前页面,返回上一页面或多级页面。可通过getCurrentPages
获取当前的页面栈,决定需要返回几层
<view bindtap="geDemo">点我</view>
Page({
onLoad(options){
setTimeout(()=>{
wx.navigateBack({
delta: 2;// 返回几层,默认为1
})
},2000)
},
geDemo() {
wx.reLaunch({
url:'page/demo/demo'
})
}
})
初识wx.request获取网络请求并渲染并渲染至页面
wx.request
用于发起网络请求,参数详见官方文档
.wxml代码如下:
窗口配置.json如下:
Page({
data: {
listArr: []
},
// 生命周期函数:监听页面加载
onLoad(option){
// 设置加载中图标
wx.showLoading({
title:'加载中...',
mask:true
}),
// 页面一加载就请求数据
this.getData();
},
// 获取随机猫咪的网络请求
getData(){
wx.request({
url:'https://api.thecatapi.com/v1/images/search?limit=2',
success:res=>{
let oldData = this.data.listArr
let newData = oldData.concat(res.data)
this.setData({
listArr:newData
})
// 接口请求成功,停止本次监听下拉刷新
wx.stopPullDownRefresh()
},
complete:err=>{
// 接口调用结束后关闭加载中图标
wx.hideLoading()
wx.hideNavigationBarLoading()
}
})
},
// 页面相关事件处理函数——监听用户下拉动作
onPullDownRefresh(){
// 下次请求数据前先清空上次请求的数据
this.setData({
listArr:[]
})
this.getData();
},
// 页面上拉触底事件的处理函数
onReachBottom() {
wx.showNavigationBarLoading()
this.getData()
}
})
wx.request其他参数:
自定义组件component的用法
官方文档
在component文件夹下,新增一个文件夹,这个文件夹就是你组件的文件夹,本文为myComponent,创建好了之后会自动生产4个文件,然后在你想引入的page页面的json文件或者app.json里面的usingComponents中引入组件:
{
"usingComponents":{
"MyHeader":"/components/MyHeader/MyHeader"// "组件名":"组件地址"
}
}
然后在使用的.wxml文件里通过标签使用:<MyHeader></MyHeader>
。如果你想要组件展示外界传进来的值,而不是写死自己的值,比如MyHeader组件在首页显示首页,在详情页显示详情,可以使用组件的properties属性,该属性是个对象,里面的属性有:
MyHeader.js代码如下:
Component({
properties: {
min: {// 定义的字段
type: Number,
value: 0
},
name: {
type: String,
value: 0,
observer: function(newVal, oldVal) {
// 属性值变化时执行
}
},
lastLeaf: {
// 这个属性可以是 Number 、 String 、 Boolean 三种类型中的一种
type: Boolean,
optionalTypes: [String, Object],
value: 0
}
}
})
其他页面直接传值即可,MyHeader.wxml:
<MyHeader min="1" name="首页" />