一、绪论
微信小程序命题微信小程序命题哔哩哔哩bilibili
拖曳式可视化微信小程序
DIY官网专注做拖拽式可视化微信小程序、Bootstrap、单页动画、Html5 WebApp设计工具 (diygw.com)
微信开发文档
微信小程序设计指南
微信小程序开发黑马程序员
黑马程序员微信小程序开发前端教程零基础玩转微信小程序哔哩哔哩_bilibili
二、微信小程序
触手可及
2.1、为什么是微信小程序
-
微信有海量用户,而且粘性很高,在微信里开发产品更容易触达用户;
-
推广app或公众号的成本太高;
-
开发适配成本高;
-
容易小规模试错,然后快速迭代;
-
跨平台。
2.2、环境准备
开发微信小程序之前,必须要准备好
2.2.1、注册账号
建议使用全新的邮箱,没有注册过其他小程序或者公众号的。
访问注册页面,耐心完成注册即可
2.2.2、获取APPID
由于后期调用微信小程序的接口等功能,需要索取开发者的小程序中的APPID
,所以在注册成功后,可登录,然后获取APPID。
登录,成功后可看到如下页面。
然后复制你的APPID,悄悄的保存起来,不要给别人看到。
2.3.3、开发工具
下载地址:稳定版 Stable Build | 微信开放文档 (qq.com)
微信小程序自带开发者工具,集 开发 预览 调试 发布 于一身的完整环境
但由于编码的体验不算好, 因此建议使用 vs code
+微信小程序编辑工具
来实现编码
vs code
负责敲代码,微信编辑器
负责预览
3、第一个微信小程序
3.1、使用APPID时,选择小程序以及JavaScript
3.2、不使用APPID时
4、小程序结构目录
小程序框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生APP体验的服务。
小程序框架提供了自己的视图层描述语言WXHML和WXSS,以及JavaScript,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。‘
4.1、小程序文件结构和传统web对比
结构 | 传统web | 微信小程序 |
---|---|---|
结构 | html | wxml |
样式 | css | wxss |
逻辑 | JavaScript | JavaScript |
配置 | 无 | json |
通过以上对比得出,传统web 是三层结构。而微信小程序是四层结构,多了一层配置.json
4.2、基本的项目目录
4.3.1、了解项目的基本组成结构
-
pages:用来存放小程序的页面
-
utils:用来存放工具性质的模块(例如:格式化时间的自定义模块)
-
app.js:小程序项目的入口文件
-
app.json:小程序项目的全局配置文件
-
app.wxss:小程序项目的全局样式文件
-
project.config.json:项目的配置文件
-
sitemap.json: 用来配置小程序及其页面是否允许被微信索引
开发目录为: ├── app.js ├── app.json ├── app.wxss ├── pages │ │── index │ │ ├── index.wxml │ │ ├── index.js │ │ ├── index.json │ │ └── index.wxss │ └── logs │ ├── logs.wxml │ └── logs.js └── utils
4.3.2、小程序页面的组成部分
4.3.1、json配置文件的作用
json是一种数据格式,在实际开发中,json总是以 配置文件的形式出现。小程序项目中也不例外:通过不同的.json配置文件,可以对小程序项目进行不同级别的配置。
小程序项目中有4种json配置文件,分别是:
-
项目根目录的app.json配置文件;
-
项目根目录中的project.config.json配置文件;
-
项目根目录中的sitemap.json配置文件;
-
每个页面文件夹中的.json配置文件
"backgroundTextStyle": "dark", //加载小圆圈的颜色
"navigationBarBackgroundColor": "#0094ff",//导航栏背景颜色
"navigationBarTitleText": "我的应用",//导航栏的文本内容
"navigationBarTextStyle": "black",//导航栏标题颜色,仅支持 black / white
"enablePullDownRefresh": true,//是否开启全局的下拉刷新
"backgroundColor": "#0088ff"//加载部分的背景颜色
4.3.2、全局配置文件app.json
4.3.2.1、全局配置文件-pages字段
用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径(含文件名) 信息。文件名不需要写文件后缀,框架会自动去寻找对应位置的 .json
, .js
, .wxml
, .wxss
四个文件进行处理。
未指定 entryPagePath
时,数组的第一项代表小程序的初始页面(首页)。
小程序中新增/减少页面,都需要对 pages 数组进行修改。
小程序官方建议把所有小程序的页面,都存放在pages目录里,以单独的文件夹存在,其中,每个页面由4个基本文件组成,他们分别是:
-
.js文件(页面的脚本文件,存放在页面的数据、事件处理函数等)
-
.json文件(当前的页面的配置文件,配置窗口的外边、表现等)
-
.wxml 文件(页面的模板结构文件)
-
.wxss文件(当前页面的样式表文件)
4.3.2.1、全局配置文件-window字段
用于设置小程序的状态栏、导航条、标题、窗口背景色
4.3.2.2、全局配置文件-tabbar字段
在全局配置文件app.json中配置
"tabBar": {
"list": [{
"pagePath": "pagePath",//路径
"text": "text",//文本内容
"iconPath": "iconPath",//未选中图标路径
"selectedIconPath": "selectedIconPath"//已选中图标路径
}]
}
当position选择top之后,图标将不再显示。
position与list是平级的
4.3.3、页面配置文件
app.json 中的部分配置,也支持对单个页面进行配置,可以在页面对应的 .json
文件来对本页面的表现进行配置。
页面中配置项在当前页面会覆盖 app.json
中相同的配置项(样式相关的配置项属于 app.json
中的 window
属性,但这里不需要额外指定 window
字段),具体的取值和含义可参考全局配置文档中说明。
4.3.4、sitemap配置-了解即可
小程序根目录下的 sitemap.json
文件用于配置小程序及其页面是否允许被微信索引,文件内容为一个 JSON 对象,如果没有 sitemap.json
,则默认为所有页面都允许被索引;
注:没有 sitemap.json 则默认所有页面都能被索引
注:{"action": "allow", "page": "\*"}
是优先级最低的默认规则,未显式指明 "disallow" 的都默认被索引
5、模块语法
记得在vscode里安装小程序开发助手
5.1、wxml
1、text 相当于以前web中的 span标签 行内元素 不会换行
2、view 相当于以前web中的 div标签 块级元素 会换行
5.2、数据绑定
WXML中的动态数据均来自对应的Page的data
数据绑定使用Mustangtache语法(双大括号)将变量包起来。
特别注意:不要直接写 checked="false"
,其计算结果是一个字符串,转成 boolean 类型后代表真值。
<view>{{person}}</view>
显示是:[object Object]
<!-- 5 在标签的属性值中使用 -->
<view data-num="{{num}}">自定义属性</view>
<!-- 6 使用bool类型充当属性,checkbox复选框
checked -->
<view>
<checkbox checked="{{false}}"> </checkbox>
或者<checkbox checked="{{isChecked}}"> </checkbox>
/!-- 字符串和花括号之间一定不要存在空格,否则会导致识别失败。
以下写法是错误的:<checkbox checked=" {{isChecked}}"></checkbox>--/
</view>
5.3、运算
“>=表达式”
可以在花括号中 加入 表达式 --“语句”
表达式:指的是一些简单 运算 数字运算 字符串 拼接 逻辑运算
1.数字的加减
2.字符串拼接
3.三元表达式
3.语句
复杂的代码段
if else
switch
do while … …
for… …
可以在 {{}}
内进行简单的运算,支持的有如下几种方式:
5.3.1、三元运算
<view hidden="{{flag ? true : false}}"> Hidden </view>
5.3.2、算数运算
<view> {{a + b}} + {{c}} + d </view>
Page({
data: {
a: 1,
b: 2,
c: 3
}
})
3+3+d
5.3.3、逻辑判断
<view wx:if="{{length > 5}}"> </view>
5.3.4、字符串运算
<view>{{"hello" + name}}</view> Page({ data:{ name: 'MINA' } })
5.3.5、数据路径运算
<view>{{object.key}} {{array[0]}}</view> Page({ data: { object: { key: 'Hello ' }, array: ['MINA'] } })
5.4、组合
也可以在Mustache内直接进行组合,构成新的对象或者数组
5.4.1、数组
5.4.2、对象
注意: 花括号和引号之间如果有空格,将最终被解析成为字符串
5.5、列表渲染
5.5.1、wx:for
在组件上使用 wx:for
控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
默认数组的当前项的下标变量名默认为 index
,数组当前项的变量名默认为 item
wx:for="{{数组或对象}}"
wx:for-item=“循环项的名称”
wx:for-index=“循环项的索引”
Page:({ data: {
list:[
{ id:0,
• name:"猪八戒"
},{
• id:1,
• name:"天蓬元帅"
},{
• id:2,
• name:"沙增"
}
]
},
wxml中
<view>
<view wx:for="{{list}}"
wx:for-item="item"
wx:for-index="index">
索引:{{index}}
--
值:{{item.name}}
</view>
</view>
5.5.2、wx:key
wx:key="唯一的值"用来提高列表渲染的性能
-
wx:key 绑定一个普通的字符串的时候,那么这个字符串 名称肯定是循环数组中的对象的唯一属性
-
wx:key =“*this” 就表示 你的数组是一个普通的数组 *this表示是循环项 [1,2,3,4,5]或者[“1”,”abc”,”sylvia”]
-
当出现 数组的嵌套循环的时候,尤其要注意 以下绑定的名称不要重名
-
默认情况下,我们不写 wx:for-item=“item” wx:for-index=“index” 小程序也会把 循环项的名称 和索引的名称 item 和 index 只有一层循环的话(wx:for-item=“item” wx:for-index=“index”)可以省略
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key
来指定列表中项目的唯一的标识符。
wx:key
的值以两种形式提供
-
字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
-
保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
如不提供 wx:key
,会报一个 warning
, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
示例代码
<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
<button bindtap="switch"> Switch </button>
<button bindtap="addToFront"> Add to the front </button>
<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch>
<button bindtap="addNumberToFront"> Add to the front </button>
Page({
data: {
objectArray: [
{id: 5, unique: 'unique_5'},
{id: 4, unique: 'unique_4'},
{id: 3, unique: 'unique_3'},
{id: 2, unique: 'unique_2'},
{id: 1, unique: 'unique_1'},
{id: 0, unique: 'unique_0'},
],
numberArray: [1, 2, 3, 4]
},
switch: function(e) {
const length = this.data.objectArray.length
for (let i = 0; i < length; ++i) {
const x = Math.floor(Math.random() * length)
const y = Math.floor(Math.random() * length)
const temp = this.data.objectArray[x]
this.data.objectArray[x] = this.data.objectArray[y]
this.data.objectArray[y] = temp
}
this.setData({
objectArray: this.data.objectArray
})
},
addToFront: function(e) {
const length = this.data.objectArray.length
this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
this.setData({
objectArray: this.data.objectArray
})
},
addNumberToFront: function(e){
this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
this.setData({
numberArray: this.data.numberArray
})
}
})
push 遇到数组参数时,把整个数组参数作为一个元素;而 concat 则是拆开数组参数,一个元素一个元素地加进去。
push 直接改变当前数组;concat 不改变当前数组。
5.5.3、对象循环
-
wx:for=“{{对象}}” wx:for-item=“对象的值” wx:for-index=“对象的属性”
-
循环对象的时候,最好把item和index的名称都修改一下
wx:for-item=“value” wx:for-index=“key”
5.6、条件渲染
5.6.1、wx:if
wx:if="{{true/flase}}"
wx:if
wx:elif
wx:else
5.6.2、hidden
1在标签上直接加入属性 hidden
2 hidden="{{true}}"
5.6.3、什么场景下使用哪个
1 当标签不是频繁的切换显示 优先使用 wx:if
直接把标签从页面结构给移除掉
2 当标签频繁的切换显示的时候 优先使用hidden
通过添加样式的方式来
再加入 <view hidden style="display:flex;">hidden</view>就覆盖了原来的样式
6、小程序中的事件绑定
6.1、
1、需要给input标签绑定 input事件,绑定关键字 bindinput
2、如何获取 输入框的值?
通过事件源对象来获取即通过e.detail.vlaue
3、把输入框的值 赋值到data中
两个错误写法:
this.data.num=e.detail.value
this.num=e.detail.value
正确的写法:
this.setData({
num:e.detail.value
})
4、需要加入一个点击事件,在之前做网页时,用bindonclick,现在,我们就就用bindtap
bindtap
无法在小程序当中的事件中直接传参;即不能够写<button bindtap="handletap(-1)"></button>
通过自定义属性的方法传递参数
事件源中获取 自定义属性
通过以上三步,在界面中输入的数据下面会由一行跟着变化的数字。在右下角菜单栏中的AppData 中num的值也会跟着改变。
1中存在的问题:
-
我们写到了e,这里会有警告,记得手动编译。
-
如何获取输入框中的值,通过事件源对象来获取,可以参照下图:
-
每次输入一位数字,他都组合成一个新的数,例如先输入1,再输入2,控制台就会有两个数,一个是1,一个是12。具体可参照下图:
那让我们看一下效果图吧!
需要实现的页面如下图:
代码参考:
<!--pages/demo03/demo03.wxml-->
<input type="text" bindinput="handleInput"/>
<button bindtap="handletap"data-operation="{{1}}">+</button>
<button bindtap="handletap"data-operation="{{-1}}">-</button>
<view>{{num}}</view>
// pages/demo03/demo03.ts
Page({
data: {
num:100
},
// 输入框的input事件的执行逻辑
handleInput(e){
// console.log(e.detail.value);
this.setData({
num:e.detail.value
})
},
// 加减按钮的事件
handletap(e){
// console.log(e);
// 1 获取自定义属性 operation
const operation = e.currentTarget.dataset.operation;
this.setData({
num:this.data.num+operation
})
}
,......
6.2、特别注意:(对于6.1的总结)
-
绑定事件时不能带参数,不能带括号 以下是错误的写法
<input bindinput="handleinput(100)"/>
-
事件传值,通过标签自定义属性的方式和
value
<input bindinput="handleinput" data-item="100"/>
-
事件触发时获取数据
handleinput:function(e){ //{item:100} console.log(e.currentTarget.dataset) //输入框的值 console.log(e.detail.value); }
解析:以上界面是由在page.ts中写 以下代码展现出来的
//加减按钮的事件
handletap(e){
console.log(e)
}
我们可以看这个currentTarget属性,里面有dataset,则属性名就是dataset.operation