微信小程序,简称小程序,英文名Mini Program
,是一种无需下载安装即可直接使用的应用,实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。
在开发小程序之前,我们需要进行如下操作:
访问微信公众平台进行账号注册,建议使用一个新的邮箱进行注册。
APPID是小程序开发者的“身份证”,当我们需要上线小程序或者使用小程序的高级功能的时候,必须提供APPID.获取步骤如下:
访问下载地址下载微信开发者工具,无脑安装,使劲下一步即可。第一次打开软件需要扫码登录,界面如下所示:
不过这个工具编码体验不好,我们一般使用vscode
进行编码,使用该工具进行预览。
打开微信开发者工具,点击加号创建项目,填写相关信息即可创建:
小程序框架提供了自己的视图层描述语言wxml
和wxss
,以及javascript
,并在视图层和逻辑层中提供了数据传输和事件系统,让开发者能够专注于数据和逻辑。
对比项 | 传统 | 小程序 |
---|---|---|
结构 | html | wxml |
样式 | css | wxss |
逻辑 | js | js |
配置 | 无 | json |
小程序配置文件有两种:第一种是全局配置文件app.json
,第二种是页面专属配置文件页面名.json
.
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"dark",
"navigationBarBackgroundColor": "#0094ff",
"navigationBarTitleText": "我的小程序",
"navigationBarTextStyle":"white",
"enablePullDownRefresh": true,
"backgroundColor":"#0094ff"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "icon/_home.png",
"selectedIconPath": "icon/home.png"
},
{
"pagePath": "pages/img/img",
"text": "图片",
"iconPath": "icon/_img.png",
"selectedIconPath": "icon/img.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的",
"iconPath": "icon/_my.png",
"selectedIconPath": "icon/my.png"
},
{
"pagePath": "pages/search/search",
"text": "搜索",
"iconPath": "icon/_search.png",
"selectedIconPath": "icon/search.png"
}
],
"color": "#ff9400"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
pages
里面是用来配置页面路径的,注意不需要加后缀。我们可以手动在里面输入一个页面路径,然后保存(注意是在微信开发者工具保存才会立即生效),然后会自动生成xxx.wxml
、wxss
、js
和json
文件;windows
是用来设置默认窗口表现的,比如导航栏的背景颜色、文字等;
tabbar
用于设置类似于手机淘宝的底部的tab栏,tabbar
里的list
属性是一个数组,用于配置最少两个tab,每个tab包含如下属性:
tabbar
还有其它的属性比如color
用于设置文字颜色等请参考官网。
页面配置文件xxx.json
用于单独配置某个页面,打开pages下的每个页面目录下的xxx.json
即可进行编辑,很多属性和全局配置文件一样,可参考官网
我们可以在xxx.js
文件中的Page方法中的data
中定义初始化数据,并且可以在xxx.wxml
中使用Mustache
语法(双大括号)进行使用。具体如下:
首先我们在demo01.js
文件中定义数据:
Page({
/**
* 页面的初始数据
*/
data: {
"msg":"hello everybody",
"num":10000,
"isGirl":true,
"person":{
"name":"张三",
"age":23
},
"isChecked":true
}
})
接着在demo01.wxml
中使用:
{{msg}}
{{num}}
你是一个女孩吗:{{isGirl}}
{{person.name}}--{{person.age}}
我们可以在双大括号内进行简单的数值运算、字符串拼接和逻辑运算:
{{1+1}}
{{'1'+'1'}}
{{1+1 === 3 ? "是的":"不是"}}
遍历分为数组遍历
和对象遍历
,首先需要在data
里面添加一个数组和对象
"person":{
"name":"张三",
"age":23
},
"list":[
{
"id":1,
"name":"张三"
},
{
"id":2,
"name":"里斯"
},
{
"id":3,
"name":"王五"
}
]
接着我们在wxml中使用wx:for
来进行遍历:
索引:{{index}}
---
名称:{{item.name}}
{{key}}:{{value}}
1
2
3
隐藏
显示
在微信小程序中,事件绑定通过bind
关键字来实现,比如:bindinput、bindtap等。
需求:在data
里面定义num
,当输入值改变时,num也会同步改变:
/**
* 页面的初始数据
*/
data: {
num:0
},
//处理输入
handleInput(e){
this.setData({
num: e.detail.value
})
},
{{num}}
需求:当点击+
,num会加1,当点击-
,num也会减1
//处理点击
handleTap(e){
const operation = e.target.dataset.operation
this.setData({
num: this.data.num + parseInt(operation)
})
}
{{num}}
wxss
是微信小程序定义样式的文件,相当于css
.
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。现在我们在wxml
中创建一个view
,我们希望它的宽度可以根据屏幕宽度的变化而变化,那我们就需要将它在设计稿上的宽度换算为rpx
:
haha
/* 小程序当中不需要主动引入样式文件 */
/*
假设设计稿宽度为 750px,元素宽度为200 px,那么
750 px = 750 rpx
1 px = 1 rpx
*/
/* view{
width: 200rpx;
height: 200rpx;
background-color: aqua;
} */
/*
假设设计稿宽度为 未知 page,元素宽度为 200px,那么
page px = 750 rpx
1 px = 750 rpx / page
200 px = 750 rpx * 200 / page
假设page为414px
*/
view{
width: calc(750rpx * 200 / 414);
height: calc(750rpx * 200 / 414);
background-color: aqua;
}
在微信小程序中,如果需要导入外部样式表,需要通过@import
进行导入。现在我们项目根路径下新建一个文件夹style
,下面有一个common.wxss
:
view{
color: aqua;
font-size: 18px;
}
接着我们在xxx.wxss
中进行引入:
/*
注意引入只能是相对路径
*/
@import '../../style/common.wxss'
只需要注意一点,小程序中不支持*
通配符,也就是说下面的代码是无法生效的:
*{
margin:0;
padding:0;
}
原生的微信小程序是不支持less
,如果希望在小程序中使用less
,可以按如下步骤进行:
vscode
安装插件的位置;Easy Less
进行安装;ctrl+shift+p
搜索settings
,打开settings.json
加入如下代码: "less.compile": {
"outExt": ".wxss"
}
less
文件并进行编辑了我们新建一个界面,将里面的xxx.wxss
的后缀改为less
,然后就可以在里面写less
代码了:
// 1、定义变量(注意:分号不可省略)
@color: green;
//2、使用变量
view {
color:@color;
}
我们在编写完保存后会在目录下生成xxx.wxss
,这个文件由上面的less文件编译而来:
view {
color: green;
}
前面已经说过,这个组件就相当于html中的div
text
是文本标签,它里面也只能嵌套文本标签:
text 111
image
是图片组件,和html
的图片标签类似:
src
:图片链接mode
:图片裁剪和缩放的模式,可选值参考官网
swiper
是微信小程序提供的轮播图组件。swiper
的常用属性如下:
autoplay
:是否开启自动切换;circular
:是否衔接滑动(在轮播项较少时不会看着别扭)interval
:设置轮播时间indicator-dots
:是否显示面板指示点,也就是那些小圆点
swiper{
width: 100%;
height: calc(750rpx * 400 / 990);
}
image{
width: 100%;
}
navigator
导航类似超链接标签。
跳转到轮播图
跳转到tabbar
redirect 轮播图
redirect tabbar
switchTab tabbar
switchTab 轮播图
rich-text
是富文本组件。
Page({
/**
* 页面的初始数据
*/
data: {
// html:'hahah',
html:[
{
name:'div',//标签名
attrs:{//属性
style:'color:red;'
},
children:[//子节点
{
name:'p',
attrs:{},
children:[
{
type: 'text',
text: 'hahaha'
}
]
}
]
}
]
}
})
男
女
{{gender}}
Page({
/**
* 页面的初始数据
*/
data: {
gender: ''
},
//处理change事件
handleChange(e){
//获取选择的单选框的值
let gender = e.detail.value
//赋值给gender
this.setData({
//gender: gender
gender
})
}
})
小程序的复选框checkbox
同样需要配合父元素checkbox-group
一起使用
{{item.name}}
{{checkedList}}
Page({
/**
* 页面的初始数据
*/
data: {
list: [
{
id: 0,
name: '苹果',
value: 'apple'
},
{
id: 1,
name: '香蕉',
value: 'banana'
},
{
id: 2,
name: '鸭梨',
value: 'yali'
}
],
checkedList: []
},
//处理change
handleChange(e){
//获取选择的值
const checkedList = e.detail.value;
//赋值
this.setData({
checkedList
})
}
})
前面所讲都是小程序给我们定义好的组件,在实际开发的时候,会出现两个页面代码十分相似的情况,这个时候我们就可以将这段代码抽取为一个组件。需求:我们肯定在很多app上见过导航栏,当我们点击导航栏上不同项时下方会显示不同的内容,我们接下来就要去做一个这样的自定义组件.
首先,我们在项目下创建一个components
文件夹,用于存放组件,然后在该目录下创建Tabs
文件夹,文件夹名称一般是要创建的自定义组件的名称,然后在该目录上右键选择创建组件,名字是Tabs
,这个创建工作需要在微信开发者工具内进行,然后,我们就可以看到Tabs下出现了类似页面的js
、wxss
、wxml
和json
文件。
我们打开Tabs.js
文件,会发现和页面的有所不同,里面不是Page
而是Component
:
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
接下来,我们如何在页面中使用这个自定义组件呢?我们打开某个页面的json
文件:
{
"usingComponents": {
//左边是组件名,右边是组件的相对路径
"Tabs":"../../components/Tabs/Tabs"
}
}
而后,我们打开wxml
,在里面使用自定义组件:
首先,我们先在组件的js文件中定义导航栏上的列表项数组:
data: {
tabs: [
{
id:"0",
name: '首页',
isActive: true
},
{
id: "1",
name: '分类',
isActive: false
},
{
id: "2",
name: '联系',
isActive: false
},
{
id: "3",
name: '关于',
isActive: false
}
]
}
接着在wxml
上搭建基本的结构:
{{item.name}}
上述中涉及的样式如下:
.tabs{
}
.title{
display: flex;
padding: 10rpx;
}
.title-item{
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.active{
color: red;
border-bottom: 10rpx solid currentColor;
}
.content{
}
接下来,我们需要,给item项添加激活选中。首先,我们给所有item添加一个自定义属性,值是循环项的索引,并绑定tap
事件:
{{item.name}}
接下来,我们需要在js
文件中定义一个handleTap
方法,注意:组件的方法不是和data
同级的,而是需要放在methods
里面:
handleTap(e){
//1 获取点击的item的索引
//等价于=》const index = e.currentTarget.dataset.index
const {index} = e.currentTarget.dataset;
//2 获取遍历的数组
//等价于=》const tabs = this.data.tabs
const {tabs} = this.data;
//3 遍历数组,将点击项设为激活状态,其它都是非激活状态
tabs.forEach((v,i) => i === index ? v.isActive = true : v.isActive = false)
this.setData({
tabs
})
}
首先,父组件(页面)是通过标签属性
的方式向子组件传递数据的。我们先将自定义组件的item项列表移动到使用父组件的页面的js文件的data中:
/**
* 页面的初始数据
*/
data: {
tabs: [
{
id: "0",
name: '首页',
isActive: true
},
{
id: "1",
name: '分类',
isActive: false
},
{
id: "2",
name: '联系',
isActive: false
},
{
id: "3",
name: '关于',
isActive: false
}
]
}
接着,我们在该页面的wxml
中通过标签属性
的方式传递给子组件:
接着,我们需要在子组件也就是自定义组件的js
文件的properties
中通过这个tabs
属性去接收父组件的数据:
properties: {
tabs:{
//type表示属性的类型
type:Array,
//value默认值
value:[]
}
}
我们可以和使用data
里面的数据一样使用properties
内的数据:
{{item.name}}
子组件向父组件传递数据一般通过自定义事件的方式传递。我们在handleTap
里面获取点击的item的索引,并将其传递给父组件:
handleTap(e){
//1 获取索引
const {index} = e.currentTarget.dataset;
//2 通过自定义事件传递给父组件
//itemChange是自定义事件的名称,第二参数是我们要传递的数据,这里使用了简写,等价于{index:index}
this.triggerEvent("itemChange",{index});
}
接着,我们需要在使用子组件的地方使用bind+自定义事件名
来接收子组件传递的数据:
//处理itemChange
handleItemChange(e){
//拿到子组件传递的index
const {index} = e.detail;
//获取数组
const {tabs} = this.data;
//遍历数组
tabs.forEach((v,i) => i === index ? v.isActive = true : v.isActive = false)
this.setData({
tabs
})
}
slot
是插槽的意思,它实际上是一个占位符,当我们的父组件调用子组件时,会传递内容来替换这个占位符。首先我们在子组件内加入插槽:
接着,在使用子组件的内部加入要替换插槽的内容:
0
1
2
3
小程序的生命周期分为应用的生命周期
和页面的生命周期
:
应用的生命周期,我们需要通过app.js
来了解:
App({
//小程序第一次启动触发的事件
onLaunch(){
console.log("onLaunch");
// aaxasxa
},
//小程序页面出现在用户面前的时候触发的事件,比如说:
//我先切换到其它应用,然后这个时候再切回来,这个时候就会执行这个方法
onShow(){
console.log("onShow");
},
//小程序页面隐藏的时候,和onShow相对
onHide(){
console.log("onHide");
},
//小程序出现代码错误的时候触发
onError(err){
console.log("onError");
},
//小程序页面找不到时触发,只会在应用第一次启动时触发
onPageNotFound(){
console.log("onPageNotFound");
}
})
页面的生命周期函数在xxx.js
中使用:
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log("onLoad");
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
console.log("onReady");
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log("onShow");
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
console.log("onHide");
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
//页面卸载指的是当前页面被关闭(无法回退到该页面)
console.log("onUnload");
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
//一般用于刷新当前页面的数据
console.log("onPullDownRefresh");
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
//一般用于加载下一页的数据
console.log("onReachBottom");
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
console.log("onShareAppMessage");
},
/**
* 页面发生滚动时触发
*/
onPageScroll: function (){
console.log("onPageScroll");
},
/**
* 页面尺寸发生变化时触发,手机上一般指的是横屏和竖屏之间的切换
*/
onResize: function(){
console.log("onResize");
},
/**
* 当前页是tab页时点击tab触发
*/
onTabItemTap: function(){
console.log("onTabItemTap");
}
})