小程序前言
想要开发小程序,必须要先注册一个微信小程序,用过的邮箱(比如注册过公众号)就不可以再拿来注册小程序了。
然后需要下载一个微信开发者工具,作为小程序的集成开发环境。
小程序目录结构
配置介绍
配置介绍
一个小程序应用程序会包括最基本的两种配置文件。一种是全局的 app.json 和 页面自己的 page.json
注意:配置文件中不能出现注释1.1. 全局配置app.json
app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。 普通快速启动项目
里边的 app.json 配置
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
字段的含义:
pages 字段 —— 用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。
window 字段 —— 定义小程序所有页面的顶部背景颜色,文字颜色定义等。
完整的配置信息请参考 app.json配置
1.2. page.json
这里的 page.json 其实用来表示页面目录下的 page.json 这类和小程序页面相关的配置。
开发者可以独立定义每个页面的一些属性,如顶部颜色、是否允许下拉刷新等等。
页面的配置只能设置 app.json 中部分 window 配置项的内容,页面中配置项会覆盖 app.json 的 window 中相同的配置项。
小程序基础语法
数据绑定:
<view>{{message}}</view>
这里的message需要在js文件里的data里面声明。
Page({
/**
* 页面的初始数据
*/
data: {
message:1
},
如果是布尔类型
不可以直接写 checked ="false",他的结果会变成一个字符串,应该像下面一样
<checkbox checked="{{false}}"></checkbox>
运算:
三元运算:
<view hidden="{{flag ? true : false}}" Hidden </view>
算术运算:
<view><{{a + b}}/view> //这才是把a和b相加
<view><{{a}} + {{b}}</view> //这个会是字符串拼接 a的值“+”b的值
逻辑判断:
<view wx:if="{{length > 5}}"></view>
字符串运算
<view>{{"hello" + name}}</view> //name是一个字符串变量
wx:for
<view wx:for="{{array}}">
{{index}}: {{item.message}}
</view>
array:[{
message:'foo',
},{
message:'bar'
}]
wx:for
<block wx:for="{{[1,2,3]}}">
<view>{{index}}:</view>
<view>{{item}}</view>
</block>
渲染一个包含多节点的结构块,block最终不会变成真正的dom元素。
wx:if
<view wx:if="{{condition}}"> True </view>
hidden:
<view hidden="{{condition}}"> True </view>
类似于 wx:if
频繁切换用 hidden
不常使用 用wx:if
小程序的双线程模型
上图为官方文档给出的双线程模型
小程序的宿主环境
微信客户端 微信客户端提供双线程去执行wxml,wxss,js文件。
双线程模型
1.上述的 渲染层 上面运行这wxml文件已经wxss文件,渲染层使用是的webview线程进行渲染(一个程序会有多个页面,也就会有多
个view线程进行运作)
2.js文件是运行在逻辑层,逻辑层的js是通过jscore进行运行的。
通过双线程界面的渲染过程是怎样的?
双线程中的一个线程生成dom,另一个线程生成变量和逻辑等,渲染到dom上。
当数据发生变化的时候
1如果通过setDat把hell改成dsb,则js对象的的节点会发生改变.
2 这时会用diff算法对比两个对象的变化,
3 然后将变化的部分应用到DOM树上
4 从而达到更新页面的目的,这也就是数据驱动的原理
总结
界面渲染的整体流程
1在渲染层将wxml文件与wxss文件转化成js对象也就是虚拟DOM
2 在逻辑成将虚拟的DOM对象配合生成,真实的DOM树,在交给渲染层渲染
3 当数据变化是,逻辑层提供更新数据,js对象发生改变,用diff算法进行比较
4 将更新的内容,反馈到真实的DOM树中,更新页面
小程序的启动流程
在app生命周期中执行了什么??
执行App()函数也就是注册一个APP
- 在注册app的时候,可以判断小程序的进入场景
- 我们可以在执行通过生命周期函数,做一些数据请求
- 可以在app中设置一个全局对象,让所有页面都能够使用
在页面的生命周期中执行了什么
1 在生命周期函数中发送网络请求,从服务端获取数据
2 初始化一些数据,在data里面,以方便wxml引用
3 监听wxml的事件,绑定对应的事件函数
4 还有页面滚动,上拉,下拉等
页面的生命周期
事件
小程序的常见事件
事件捕获与事件冒泡
现在有三个view,嵌套存在。点击最里面的view,就相当于点击了三个。
这时候事件是怎么捕获的?
<view class='container1' id='container' capture-bind:tap='outer_ca' bindtap='onContainerTap'>我是外层
<view class='middle' capture-bind:tap='middle_ca' bindtap='middle'>我是中间
<view class='inner1' id='inner' capture-bind:tap='inner_ca' catch:tap='onInnerTap'>我是内层</view>
</view>
</view>
<view>{{start}}</view>
<button bindtap='jia'>jia</button>
结果是,事件的捕获是从外到内的。
冒泡是从内到外的。
阻止事件捕获
用catch阻止事件捕获
只需要把capture-bind改成capture-catch就可以捕获
阻止事件冒泡
只需要把bindtap改成catch:tap就可以阻止了。
自定义组件
自定义组件就像是vue的子组件。
先自己建立一个根文件夹,命名为components,然后在文件夹下建一个自定义组件文件夹,随意命名,在这个文件夹里新建page就可以了,一定要把js文件里的component改成true,这样就表示他是一个自定义组件。
{
"component": true,
"usingComponents": {}
}
然后在别的组件中的json文件里这样写
{
"usingComponents": {
//t1就代表自定义组件的名字,后面写的是这个自定义组件的决定路径。
"t1":"/components/t1/t1"
}
}
完成上面的步骤之后,就可以在别的组件中直接用这个自定义组件了。
<!--t1这个组件的页面中写了什么,这里就会显示什么-->
<t1></t1>
页面像自定义组件传递数据
#页面中,这里把bing赋值给了sb,注意,这里的sb并不是这个页面中声明的变量,而是自定义组建的变量。
<t1 sb="bing"></t1>
properties: {
sb:{
//sb这个变量的类型为字符串
type:String,
//默认值为tank,当有传递过来的值时,就改变成那个值。
value:"tank"
}
},
组件将事件传给页面
类似于vue的子传父
页面
<!--通过传来的jia点击事件,来触发tt1点击事件-->
<t1 bind:tt1="jia"></t1>
页面中的js
jia:function(e){
console.log(e)
this.setData({
num: this.data.num + 1
})
}
组件中的wxml
<button bind:tap="jia" data-age='11'>jia</button>
组件中的js
jia:function(e){
console.log(e)
//triggerEvent,用这个可以传递给页面点击事件,后面的括号是参数。
this.triggerEvent("tt1",{age:e.currentTarget.dataset.age},{})
}
wx:request
这个用来和后端服务器做交互
wx.request({
url: 'www.aaaa.com', // 后端url
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
console.log(res.data)
}
})
小程序路由跳转
wx.switchTab(Object object)
这里的tabBar是地下的导航栏指定的页面,跳转到tabBar页面,并关闭其他所有非tabBar页面。
实例代码:
//app.json中写的的tabBar
{
"tabBar": {
"list": [
{
"pagePath": "index",
"text": "首页"
},
{
"pagePath": "other",
"text": "其他"
}
]
}
}
wx.switchTab({
url: '/index'
})
wx.reLaunch(Object object)
关闭所有页面,打开到应用内的某个页面
示例代码
wx.reLaunch({
url: 'test?id=1'
})
wx.redirectTo(Object object)
关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
wx.navigateTo(Object object)
保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈,最多十层。
示例代码
wx.navigateTo({
url: 'test?id=1'
})
// test.js
Page({
onLoad(option) {
console.log(option.query)
}
})
wx.redirectTo与wx.navigateTo的区别
1.利用wx.navigateTo跳转到下一个页面的时候(这时候会执行onHide方法),下一个页面头部会有返回按钮
2.如果不想有返回按钮,可以用wx.redirectTo进行页面跳转(这时候关闭此页面,会执行onUnload生命周期,这样下一个页面就
不会有返回按钮了,因为上一个页面已经被关闭了,没有页面可以返回)
wx.navigateBack(Object object)
关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。
示例代码
wx.navigateTo({
url: 'B?id=1'
})
// 此处是B页面
wx.navigateTo({
url: 'C?id=1'
})
// 在C页面内 navigateBack,将返回A页面
wx.navigateBack({
delta:2
})
wx存储数据到本地及本地获取数据
存到本地就是存在手机上。
wx.setStorageSync(string key, any data)(同步)
参数:
string key: 本地缓存中指定的 key
any data: 需要存储的内容。只支持原生类型、Date、及能够通过 JSON.stringify 序列化的对象。
示例代码
wx.setStorage({
key:'key',
data:'value'
})
try{
wx.setStorageSync('key', 'value')
} catch(e){ }
wx.setStorage(Object object)(异步)
将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容。数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则数据都一直可用。单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
示例代码
wx.setStorage({
key: 'key',
data: 'value'
})
try {
wx.setStorageSync('key', 'value')
} catch (e) { }
上面的两个就是一个是同步的一个是异步的,还是有区别的,想用哪一个看你的业务来定
wx.getStorageSync(string key)(同步)
参数
string key: 本地缓存中指定的 key
返回值: any data,key对应的内容
示例代码
wx.getStrage({
key:'key',
success(res){
console.log(res.data)
}
})
try{
const value = wx.getStorageSync('key')
if(value){
console.log('yes')
}
}catch(e){
console.log('no')
}
wx.getStorage(Object object)(异步)
示例代码
wx.getStorage({
key: 'key',
success(res) {
console.log(res.data)
}
})
try {
const value = wx.getStorageSync('key')
if (value) {
// Do something with return value
}
} catch (e) {
// Do something when catch error
}