前言
这篇文章是我之前学习小程序时做的笔记,最近拿出来整理了一下,适合刚学习小程序的小白,如果有不正确的地方请评论区留言,以便于及时改正错误
注册微信小程序账号
- 打开官网地址:mp.weixin.qq.com/
- 点击立即注册 注册账号
- 点击小程序
- 填写基本资料
- 获取AppID(点击开发管理,切换到开发设置就能看见AppID)
下载微信开发者工具
- 打开下载链接:developers.weixin.qq.com/miniprogram…
- 根据自己的系统下载相对应的
微信开发者工具基本设置
- 扫码登录
- 点击设置
3. 用于更换主题
4.代理方式选择不适用使用任何代理
然后就可以创建自己的微信小程序项目了
1.点击加号创建
2.appID是在微信公众号平台获取(也可以使用测试账号)
初步认识下小程序的基本页面结构
全局
app.js:设置一些项目的全局变量app.json:每一个新页面都必须在这个地方注册,项目的导航栏和窗口界面设置app.wxss:项目全局样式project.config.json:项目配置文件
页面局部
xxx.wxml:页面的结构xxx.wxss:页面的样式xxx.json:页面的配置文件xxx.js:页面的脚本文件
认识配置文件
小程序项目中有四种配置文件
- 项目根目录中的
app.json配置文件 - 项目根目录中的
project.config.json配置文件 - 项目根目录中的
sitemap.json配置文件 - 每个页面文件夹中的
json配置文件 下面咱就细说说每个配置文件的作用
app.json
是用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。先来了解app.json下几个基本配置项
pages:用于配置当前小程序所有页面的路径,如下图所示,pages是个数组,如果我们需要添加页面,就可以在pages数组下配置相对应的路径,开发工具会自动帮我们生成对应的文件夹,而写在pages字段的第一个页面就是这个小程序的首页(打开小程序看到的第一个页面)
-
window:用于全局定义小程序所有页面的背景颜色、文字颜色等,下图只是简单的几个配置,详细配置可点击官方文档参考来进行配置 -
style:用于全局定义小程序使用的样式版本,新版就是v2,如果不配置就会用老的样式,下图进行比较,左图v2版本,右图默认老版本
tabBar:用于配置底部标签栏(最少两个,最多五个),基本配置如下,详细配置可点击官方文档参考来进行配置
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"navigationBarBackgroundColor": "#07c160",
"navigationBarTitleText": "导航栏标题文字内容",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json",
"lazyCodeLoading": "requiredComponents",
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/logs/logs",
"text": "日志"
}
]
}
}
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| pagePath | string | 是 | 页面路径,必须在 pages 中先定义 |
| text | string | 是 | tab 上按钮文字 |
| iconPath | string | 否 | 图片路径 |
| selectedIconPath | string | 否 | 选中时的图片路径 |
sitemapLocation:用于指明sitemap.json的路径
project.config.json
project.config.json项目配置文件,用来记录对小程序开发工具所做的个性化配置
setting编辑相关的配置appid小程序IDprojectname项目名称setting对应的设置还可以在本地设置里面配置,会在setting配置里面进行同步
"setting": {
"urlCheck": true, //是否检查安全域名和TLS版本
"es6": true, //是否启用es5转es6
"postcss": true, //上传代码时样式是否自动补全
"minified": true, //上传代码时是否自动压缩
"checkSiteMap": true // 是否能被微信索引
},
sitemap.json
sitemap.json是用来配置小程序页面是否能被微信索引,类似于pc网页的SEO,详细配置可点击官方文档配置
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow", // allow(允许所有页面被索引),disallow(不允许被索引),
"page": "*"
}]
}
| 属性 | 类型 | 必填 | 默认值 | 取值 | 取值说明 |
|---|---|---|---|---|---|
| action | string | 否 | "allow" | "allow"、"disallow" | 命中该规则的页面是否能被索引 |
| page | string | 是 | "*"、页面的路径 | “*” 表示所有页面,不能作为通配符使用 | |
| params | string | 否 | [] | 当 page 字段指定的页面在被本规则匹配时可能使用的页面参数名称的列表(不含参数值) | |
| matching | string | 否 | "inclusive" | "exact","inclusive","exclusive","partial" | 当 page 字段指定的页面在被本规则匹配时,此参数说明 params 匹配方式 |
| priority | Number | 否 | 优先级,值越大则规则越早被匹配,否则默认从上到下匹配 |
json
json用来配置当前页面的外观,会覆盖全局app.json里面相同的配置项,配置与上述配置差不多,详细可点击官方文档进行查看
样式相关
rpx
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
样式导入
使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。
// 样式一
/* common.wxss */
view {
width:100rpx
}
// 导入样式一
@import "common.wxss"
view {
width:100rpx
}
语法相关
模板语法
小程序的模板语法适合vue里的Mustache语法是一样使用的,先在js里声明变量,用{{}}包裹变量在wxml使用就可以了
// wxml
<view class="container">
// 模板语法
<view>{{msg}}</view>
// 三元表达式 true
<view>{{num > 9}}</view>
// 算数运算 19
<view>{{num + 9}}</view>
</view>
// js
data: {
msg:'小程序',
num:10
},
条件渲染
wx:if
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
hidden
<view class="container">
<view hidden="{{true}}">表达式为true的时候隐藏</view>
<view hidden="{{fasle}}">表达式为false的时候显示</view>
</view>
wx:if和hidden的区别
wx:if是以动态的创建和销毁元素的方式来控制对元素的显示与隐藏的,当初始条件为false的时候不会做任何操作,有为true的时候才会创建元素,控制条件复杂和不频繁的切换的时候使用wx:ifhidden是基于display:block/none来控制元素的显示与隐藏的,不管初始条件为true或者是false,都会创建该元素,当切换非常频繁的时候使用hidden
列表渲染
wx:for用于循环列表,需要绑定key值,建议是谓唯一值,可以提高渲染效率,如果没有唯一值可以绑定index,当我们不手动指定索引和当前项的变量的时候,默认是index和item
// 默认
<view wx:for="{{list}}" wx:key="id">
id:{{item.id}} --- 姓名:{{item.name}} --- 索引:{{index}}
</view>
// 手动指定
<view wx:for="{{list}}" wx:key="id" wx:for-item="cur" wx:for-index="i">
id:{{cur.id}} --- 姓名:{{cur.name}} --- 索引:{{i}}
</view>
事件绑定
事件类型
| 事件类型 | 触发条件 |
|---|---|
| bindtap/bind:tap | 手指触摸后马上离开,类似HTML点击事件 |
| bindinputinput/bind:input | 文本框输入触发 |
| bindchange/bind:change | 状态改变的时候触发 |
| touchstart | 手指触摸动作开始 |
| touchmove | 手指触摸后移动 |
| touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 |
| touchend | 手指触摸动作结束 |
<!--logs.wxml-->
<view class="container">
<view bindtap="say">打招呼</view>
</view>
// logs.js 自定义函数与data平级
say() {
console.log('你好');
}
事件对象的属性
| 属性 | 备注 |
|---|---|
| type | 触发的时间类型 |
| target | 触发事件的组件里的属性集合 |
| currentTarget | 当前组件里的属性集合 |
| detail | 获取信息 |
| timeStamp | 页面从打开到触发事件经过的时间(毫秒) |
| touches | 触摸事件,获取停留在触摸点的信息 |
| changedTouches | 触摸事件,获取当前变化触摸点的信息 |
更改data里面的数据
this.setData({
num: this.data.num + 1
})
事件传参
通过data-来进行传参,后面跟着自定义参数的名字,使用e.target.dataset来进行接收
<view data-info="{{'你好'}}" bindtap="changeQuery">获取参数</view>
changeQuery(e) {
console.log(e.target.dataset.info);
}
请求资源
使用wx.request()发送请求,具体配置点击官方文档进行查看
wx.request({
//请求接口地址
url: 'url',
// 请求方式
method: 'GET',
// 请求数据
data: {
name: '旺仔',
age: 18
},
// 成功后的回调函数
success: (res) => {
console.log(res);
}
})
wxs
wxs是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构,其作用场景一般用于过滤器,
wxs遵循的是commonJs规范
- 过滤一个时间戳
// 声明处理事件戳的函数
function formatTime(times) {
if (times) {
var time = getDate(times);
var year = time.getFullYear();
var month = time.getMonth() + 1;
var date = time.getDate();
var hour = time.getHours();
var minute = time.getMinutes();
var second = time.getSeconds();
return year + "-" + add0(month) + "-" + add0(date) + " " + add0(hour) + ":" +
add0(minute) + ":" + add0(second);
} else {
return times
}
}
// 补零
function add0(m) {
return m < 10 ? '0' + m : m;
}
// 暴露formatTime函数
module.exports = {
formatTime: formatTime
}
// index.js
Page({
/**
* 页面的初始数据
*/
data: {
date: Date.now()
},
})
index.wxml
// 使用wxs
<view>{{ m1.formatTime(date) }}</view>
// src="wxs的路径" module="自定义名称"
<wxs src="../../utils/formatTime.wxs" module="m1"></wxs>
导航相关
url: 跳转页面的地址target: 跳转目标open-type: 跳转方式delta: 当open-type为navigateBack时有效,表示回退的层数 导航部分详细配置请点击官方文档查看
声明式导航
导航跳转
使用<navigator />进行页面,跳转方式默认是navigate,如果是跳转到tabBar页面,跳转方式必须先为switchTab
- 跳转到非tabBar页面
<navigator url="/pages/list/list" open-type="navigate">导航到非tabBar页面</navigator>
- 跳转到tabBar页面
<navigator url="/pages/index/index" open-type="switchTab">导航到tabBar页面</navigator>
后退导航
返回到上个页面,可指定open-type为navigateBack即可,如果需要返回多级页面则可以加上delta,值为要后退的步数,默认是1
<navigator open-type="navigateBack">后退一步</navigator>
<navigator open-type="navigateBack" delta="1">后退一步</navigator>
<navigator open-type="navigateBack" delta="3">后退三步</navigator>
导航传参
在url路径后面拼接即可
<navigator url="/pages/index/index?name=zs&age=13" />
编程式导航
导航跳转
- 跳转到非tabBar页面,使用
wx.navigateTo()
wx.navigateTo({
url: '跳转的url路径',
// 成功后的回调函数
success: (res) => {
console.log(res);
},
// 失败后的回调函数
fail: (err) => {
console.log(err);
},
// 成功和失败都会触发的回调函数
complete: (e) => {
console.log(e);
},
})
- 跳转到tabBar页面,使用
wx.switchTab()
wx.switchTab({
url: '跳转的url路径',
// 成功后的回调函数
success: (res) => {
console.log(res);
},
// 失败后的回调函数
fail: (err) => {
console.log(err);
},
// 成功和失败都会触发的回调函数
complete: (e) => {
console.log(e);
},
})
后退导航
wx.navigateBack({
delta: 1 // 后退的的步数,默认为1
})
导航传参
wx.navigateTo({
url:'/pages/index/index?name=zs&age=13'
})
生命周期
应用生命周期
- onLaunch:小程序初始化完成时触发,全局只触发一次。参数也可以使用 wx.getLaunchOptionsSync 获取
- onShow:小程序启动,或从后台进入前台显示时触发。也可以使用 wx.onAppShow 绑定监听。
- onHide:小程序从前台进入后台时触发。也可以使用 wx.onAppHide 绑定监听。
- onError:小程序发生脚本错误或 API 调用报错时触发。也可以使用 wx.onError 绑定监听。
- onPageNotFound:小程序要打开的页面不存在时触发。也可以使用 wx.onPageNotFound 绑定监听。注意事项请参考 wx.onPageNotFound。
App({
onLaunch (options) {
// 做一些初始化的事情
},
onShow (options) {
// 在展示的时候触发
},
onHide () {
// 在隐藏的时候触发
},
onError (msg) {
// 报错的时候触发
},
onPageNotFound(res) {
// 在跳转的时候找不到页面的时候触发
wx.redirectTo({
url: 'pages/...'
}) // 如果是 tabbar 页面,请使用 wx.switchTab
}
})
页面生命周期
- onLoad:页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
- onShow:页面显示/切入前台时触发。
- onHide:页面隐藏/切入后台时触发。 如
wx.navigateTo或底部tab切换到其他页面,小程序切入后台等。 - onUnload:页面卸载时触发。如
wx.redirectTo或wx.navigateBack到其他页面时触发。 页面事件处理函数 - onPullDownRefresh:监听用户下拉刷新事件。
- onReachBottom:监听用户上拉触底事件。
- onPageScroll:监听用户滑动页面事件。
- onAddToFavorites:监听用户点击右上角菜单“收藏”按钮的行为,并自定义收藏内容。
- onResize:页面尺寸发生变化或者屏幕翻转的时候触发。
- onTabItemTap:点击
tab时触发 - onShareTimeline:监听右上角菜单“分享到朋友圈”按钮的行为,并自定义分享内容(注:只有定义了此事件处理函数,右上角菜单才会显示“分享到朋友圈”按钮)
//index.js
Page({
data: {
text: "学习小程序之《从入门到入土篇》"
},
onLoad: function(options) {
// 当页面加载时做一些初始化。
},
onShow: function() {
// 在展示的时候触发
},
onReady: function() {
// 当页面渲染好后触发
},
onHide: function() {
// 在隐藏的时候触发
},
onUnload: function() {
// 页面卸载时触发
},
onPullDownRefresh: function() {
// 下拉刷新的时候触发
},
onReachBottom: function() {
// 上拉触底的时候触发
},
onShareAppMessage: function () {
// 点击分享的时候触发
},
onPageScroll: function() {
// 页面滚动的时候触发
},
onResize: function() {
// 页面尺寸发生变化的时候触发
},
onTabItemTap(item) {
//点击tab的时候触发
},
})
自定义组件相关
组件是项目中必不可少的,可以有利于复用和代码的结构简化,在小程序中使用组件需要注意,先要在当前组件的json文件中声明自己是个组件,如果全局引用的话就在app.json里面引入,局部引用的话需要用到该组件的json文件中引用
- 声明组件
{
"component": true
}
- 引用组件
"usingComponents": {
//"组件名":"组件路径"
"my-component":"../component/index/index"
}
组件属性
// component/test1/test1.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 数据监听器
*/
observers: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
- properties 用于接收外界传递过来的数据,用于组件传值,学过vue的同学应该知道这个属性相当于
props用于接收传递过来的数据,
// test1 用于引用组件
<test2 money="100"></test2 >
// component/test1/test1.js
Component({
/**
* 组件的属性列表
*/
properties: {
money:{
type:number // 定义属性值的类型
value:1 // 属性的默认值
}
},
})
- observers:数据监听器,用于监听属性和数据的变化来执行操作,类似于vue的watch侦听器,可以监听多个
Component({
/**
* 组件的初始数据
*/
data: {
obj:{
name:'小明',
age:18
}
},
/**
* 数据监听器
*/
observers: {
// 监听obj.name属性
'obj.name':function(newValue){
// 执行操作
}
},
})
组件的隔离特性
在自定义组件中具有样式隔离的特性,每个组件都有自己的样式,引用组件的页面样式不会影响组件的样式,组件的样式也是不会影响页面的样式,全局样式也是对组件不能生效,注:只有class类名选择器才有隔离特性,其他的选择器没有隔离特性,当然也可以通过组件内的stylelsolation属性解除样式隔离
- isolated:启用样式隔离,使用
class类名选择器的样式不会互相影响 - apply-shared:页面中的样式会影响到自定义组件,自定义组件的样式不能影响页面
- shared:页面和自定义组件的样式可以互相影响
Component({
options:{
styleIsolation:'apply-shared' // 解除样式隔离
},
})
组件传值
- 属性绑定:用属性绑定实现父向子传值,只能传递普通类型数据,无法进行方法传递,在父组件中使用事件绑定传递参数,子组件使用
properties进行接收 父组件:father
// component/father/father.js
Component({
// 父组件内定义数据
data: {
name:'海绵宝宝'
}
})
{
"component": true,
"usingComponents": {
// 引入子组件
"son":"/component/son/son"
}
}
<!--component/father/father.wxml-->
<view>
<view>父组件:{{name}}</view>
------------------------------
<!-- 在父组件中使用子组件 name(子组件中用于接收的变量)="name"(父组件中定义的数据) -->
<son name="{{name}}" ></son>
</view>
son
// component/son/son.js
Component({
/**
* 组件的属性列表
*/
// 接收父组件中传递的值
properties: {
// 接收的变量名
name: {
// 类型
type: String,
// 默认值
value: "辛迪"
}
}
})
<!--component/son/son.wxml-->
<view>
<view>子组件:{{name}}</view>
</view>
- 事件绑定:用事件绑定绑定实现子向父传值,可以传递任何类型的数据,在父组件中定义一个函数,传递给子组件,子组件使用
this.triggerEvent('自定义事件名称',{参数对象}),将数据传送到父组件,父组件使用e.detail获取子组件传递来的数据 father
// component/father/father.js
Component({
// 父组件内定义数据
data: {
name: '海绵宝宝'
},
/**
* 组件的方法列表
*/
methods: {
updateName(e) {
console.log(e.detail);
this.setData({
name: e.detail
})
}
}
})
<!--component/father/father.wxml-->
<view>
<view>父组件:{{name}}</view>
------------------------------
<!-- 在父组件中使用子组件 name(子组件中用于接收的变量)="name"(父组件中定义的数据) -->
<son name="{{name}}" bind:fatherUpdateName="updateName"></son>
<!-- bind:fatherUpdateName(传递给子组件用于触发的方法名)="updateName"父组件中定义的方法 -->
</view>
son
// component/son/son.js
Component({
/**
* 组件的属性列表
*/
// 接收父组件中传递的值
properties: {
// 接收的变量名
name: {
// 类型
type: String,
// 默认值
value: "辛迪"
}
},
/**
* 组件的方法列表
*/
methods: {
// 更改姓名
updateName() {
this.setData({
name: '派大星'
})
// 此时只能更改子组件的数据,不能更改该父组件的数据,需要使用this.triggerEvent调用父组件的方法来进行头部更新
this.triggerEvent('fatherUpdateName','派大星')
}
}
})
<!--component/son/son.wxml-->
<view>
<view>子组件:{{name}}</view>
<button bindtap="updateName">点击更换名字</button>
</view>
- 组件实例:通过
this.selectComponent("id/class"),获取组件实例的方法直接访问子组件的方法和数据,只能使用id或class选择器 father
// component/father/father.js
Component({
// 父组件内定义数据
data: {
name: '海绵宝宝'
},
/**
* 组件的方法列表
*/
methods: {
updateName(e) {
console.log(e.detail);
this.setData({
name: e.detail
})
},
// 获取子组件实例
getComponent(){
const son = this.selectComponent('#son')
console.log(son);
}
}
})
<!--component/father/father.wxml-->
<view>
<view>父组件:{{name}}</view>
<button bindtap="getComponent">this.selectComponent获取子组件实例</button>
------------------------------
<!-- 在父组件中使用子组件 name(子组件中用于接收的变量)="name"(父组件中定义的数据) -->
<son name="{{name}}" bind:fatherUpdateName="updateName" id="son"></son>
<!-- bind:fatherUpdateName(传递给子组件用于触发的方法名)="updateName"父组件中定义的方法 -->
</view>