1、app.json文件中页面路径前不要加/
2、图片尽量不要存储在小程序的目录中。(因为小程序的大小不能超过1MB,超过则无法真机运行和发布项目。应该将图片都存放在服务器上,让小程序通过网络来加载图片)
3、设置display:flex是应用一切弹性布局属性的先决条件,如果不设置display:flex,那么后续的其他相关弹性布局属性都将无效
4、使用rpx单位可以使组件自适应屏幕的高度和宽度(px不会自适应);建议以iphone6的宽度750个物理像素作为标准做设计图。转换比例为 1物理像素=1rpx=0.5px
5、border属性不需要动态变化,如果动态变化,会在屏幕尺寸较大的手机上变得很粗。建议在iPhone6尺寸下做设计图。模拟器机型的分辨率是逻辑分辨率pt,而非物理分辨率。375X667;Dpr:2,代表iphone6的水平方向有375个逻辑像素点,垂直方向有667个逻辑像素点,每个逻辑像素点包含2个物理像素点。(通常PS里的像素指物理像素)
(e.g. 一张图片750像素,水平充满页面,设置750rpx或375px)
6、需要同时设置swiper组件和image组件的高宽。
7、页面生命周期:
- 加载 onLoad:一个页面只会调用一次
- 显示 onShow:每次打开页面都会调用
- 渲染 onReady:监听初次渲染完成,一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互
- 隐藏 onHide:监听页面隐藏
- 卸载 onUnload:监听页面卸载
一个页面要正常显示,必须经历“加载、显示、渲染”三个生命周期。onShow的执行时刻是在onReady之前的。
除了First Render第一次渲染,页面还有可能会Rerender再次渲染多次。
数据更新会造成页面的重新渲染。onReady只监听“第一渲染”的完成
8、在真实的项目中,业务数据通常都放置在自己的服务器中,然后通过HTTP请求来访问服务器提供的RESTFUL API,从而实现数据获取。
9、小程序的脚本逻辑是运行在JScore中,JScore是一个没有DOM的环境,完全抛弃了DOM结构,只能通过数据绑定来做数据的相关操作
10、小程序仅实现了单向数据绑定,即只支持从逻辑层传递到渲染层的数据绑定,反之则不可以
11、小程序使用Page方法参数里的data变量作为数据绑定的桥梁
12、数据绑定有两种:
- 一种是初始化数据的数据绑定。通常将这些数据直接写在Page方法参数的data对象下面
- 另一种是使用setData方法来做数据绑定,这种方式也可以理解为数据更新。这样的数据更新将引起页面的Rerender(重新渲染)
13、小程序使用Mustache语法{{}}在wxml组件里进行数据绑定
14、初始化数据绑定过程:
当页面执行了onShow函数后,逻辑层会收到一个通知(Notify);随后逻辑层会将data对象以json的形式发送到View视图层(Send Initial Data),视图层接收初始化数据后,开始渲染并显示初始化数据(First Render),最终将数据呈现在开发者眼前。
15、数据绑定更新:setdata
setData方法位于Page对象的原型链上:Page.prototype.setData。使用this.setData的方式调用
setData的参数接收一个对象,以key和value的形式将this.data中的key对应的值设置成value.
注意:
- setData会改变this.data变量里相同key的值
- setData执行后会通知逻辑层执行Rerender,并立刻重新渲染视图。
16、关于数据绑定的错误,小程序目前不会给出任何错误提醒。如果发现整个页面是空白的又没有错误消息,多半是数据绑定出了问题。(此时,AppData面板是最好的调试工具)
17、列表渲染:
<block wx:for="{{postList}}" wx:for-item="item" wx:for-index="idx">
<view class='post-container'>
<view class='post-author-date'>
<image src='{{item.avatar}}'></image>
<text>{{item.object.date}}</text>
</view>
<text class='post-title'>{{item.title}}</text>
<image class='post-image' src='{{item.postImg}}'></image>
<text class='post-content'>{{item.content}}
</text>
</view>
</block>
<block>标签并没有实质意义,它并不是组件,所以称作“标签”。(它仅仅是一个包装,可以理解为常见编程语言里的括号,不会再页面内被渲染,在block标签中被包裹的元素将被重复渲染。)
block标签中的wx:for属性,值为{{postList}},对应post.js文件中setData的数组数据。wx:for并不是一定要作用在block标签上。把block标签换成view一样可以运行,但我们希望标签或组件的语义是明确地。view组件通常被用来做容器或区域分隔,不不应该被滥用。
如果不定义item,小程序默认的子元素变量名即为item。也可以将它替换为其他变量名,如:wx:for-item="element".
18、页面的json文件只能配置和window相关属性;app.json除了可以配置window,还可以配置pages、tabBar等选项
(页面json配置不需要加window对象,直接编写window配置项即可)
19、事件:事件是视图层(wxml)到逻辑层(js)的通信方式。
可以让我们在js里处理用户在界面上的一些操作并作出反馈。如点击按钮后,需要在js里调用MINA框架的API,是页面从welcome跳转到post.
20、实现事件机制:
step1:在组件上注册事件。(注册事件将告诉小程序,我们要监听哪个组件的什么事件。本例是button组件的tap事件)
step2:在js中编写事件处理函数响应事件。(监听到事件后的处理业务)
21、小程序共提供了3个导航API:
- wx.redirectTo:关闭当前页面,跳转到指定页面
- wx.navigateTo:保留当前页面,跳转到指定页面
- wx.switchTap(122100新增版本):跳转到带tabbar的页面,并关闭其他所有非tabbar页面
url是页面路径,不要加扩展名。
redirectTo和navigateTo在使用方式上完全相同,都接受一个Object对象作为参数。
Object参数还可以接收3个方法:
- success:跳转页面成功时调用
- fail:跳转失败时调用
- complete:无论成功或失败,都会调用
(在小程序中,几乎所有异步类型的API都配备有这3个方法)
22、redirectTo:将卸载welcome页面,并执行onUnload事件函数。
navigateTo:隐藏当前页面,还可以再次返回到被隐藏页面
再次从post页面返回到welcome页面时,会执行post页面的onUnload函数(130400版本,即子页面返回父页面时,子页面会被卸载。页面是否被卸载是非常重要的行为,不卸载页面将使全局性的一些行为,比如音乐播放的处理变得非常复杂)
23、当我们使用navigateTo从父页面跳转到子页面后,就形成了2个页面层级。
小程序强制规定只允许有最多五层父子页面。(建议不超过3层)
24、冒泡事件
冒泡事件:某组件上的事件被触发后,事件还会向父级元素传递;父级元素还会继续向父级元素传递,直到页面顶级元素。
(非冒泡事件不会向上传递)
常见的冒泡事件:
- touchstart:手指触摸动作开始
- touchmove:手指触摸后移动
- touchcancel:手指触摸动作被打断,如来电提醒、弹窗
- touchend:手指触摸动作结束
- tap:手指触摸后马上离开
- longtap:手指触摸后,超过350ms再离开
在wxml组件里注册事件时,不可直接使用tap="function"或touchmove="function",需要在事件名前添加前缀catch或bind
(catch将阻止事件继续向父节点传播;bind不阻止)
welcom.js
Page({
onUnload: function (event) {
console.log("page is unload")
},
onHide: function (event) {
console.log("page is hide")
},
onTapJump: function (event) {
wx.navigateTo({
url: '/pages/post/post',
success: function () {
console.log("jump success")
},
fail: function () {
console.log("jump fail")
},
complete: function () {
console.log("complete")
}
});
},
onTapJumpFather:function(event){
console.log("tap事件传递!")
}
})
welcome.wxml:
<view catchtap='onTapJumpFather' class='container'>
<image class='avatar' src='/images/avatar/1.png'></image>
<text class='motto'>Hello,桔子罐头</text>
<view bindtap='onTapJump' class='journey-container'>
<text class='journey'>开启小程序之旅</text>
</view>
</view>
result:
若改为:
<view catchtap='onTapJump' class='journey-container'>
<text class='journey'>开启小程序之旅</text>
</view>
result:
无特殊申明都是非冒泡事件。非冒泡事件大多不是通用事件,是某些组件特有事件。如<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件。
常见的冒泡事件:
- touchstart:手指触摸动作开始
- touchmove:手指触摸后移动
- touchcancel:手指触摸动作被打断,如来电提醒、弹窗
- touchend:手指触摸动作结束
- tap:手指触摸后马上离开
- longtap:手指触摸后,超过350ms再离开
25、模块化:
所有文章数据都被强行写在post.js里,污染业务层,尝试将这些数据分离到一个单独的js文件中。
其他文件访问模块:
STEP1:data.js 暴露接口:module.exports={postList:postList}
STEP2: post.js引入模块:
不同于页面路径,被引用文件一定要带有扩展名js
path路径不可以使用绝对路径,否则会报错。
在js中声明的变量和函数只在该文件中有效,不同的文件可以声明相同名字的变量和函数,不会互相影响。
在输出模块时,我们是将postList作为一个object属性赋值给module.exports,所以require时,得到的也是一个object而非postList,需要使用dataObj.postList才能获取到真实的文章数据
object不仅可以包含postList,还可以在data.js文件中定义除了postList外的其他数据,并作为object的属性一起输出。
require只会模块化的一种方式,还可以使用ES6的Module来编写模块,开发工具默认使用label将开发者的ES6代码转化成ES5代码。
26、模板化
使用列表渲染展现文章列表并不是最好的办法,因为如果其他页面同样需要显示文章列表,总不能吧wxml代码到处拷贝啊~~~
借助函数思想,将一些公共的、经常使用的业务逻辑提取成一个公共的函数,调用即可。