特点
触手可及,用完即走。就是微信里的原生APP。
小程序示例
微信搜索“小程序示例”,可以获得 组件 接口 云开发 的示例。
注册
搭建开发环境
下载“微信web开发者工具”即可。
项目结构
约定大于配置,页面放在pages文件夹下。
其中,
app.json
是全局的配置文件,project.config.json
是整个项目的描述文件,类似于node中的package.json
。
页面组织结构
新建页面:
- 在
app.json
中添加对应页面 - 添加完毕后,pages文件夹中会自动生成对应的页面
-
app.json
中第一个页面对应初始页面
页面文件说明:
-
demo.js
页面逻辑文件,创建页面对象,处理页面生命周期,处理页面数据 -
demo.wxml
-- Wei Xin Markup Language
定义页面元素结构,语法遵循XML -
demo.json
(可选)
设置当前页面工作时的window配置,会覆盖app.json
中的window设置 -
demo.wxss
-- Wei Xin Style Sheet(可选)
定义页面样式,遵循css语法,在css基础上有扩展,例如rpx响应式像素
配置文件
页面配置文件优先于项目配置文件,即
demo.json
优先于app.json
页面的配置只能配置app.json
中部分window配置项的内容
标签栏的配置
在小程序中,标签栏不是通过布局实现的,是通过配置实现的
app.json
中tabBar的配置内容
注意:
- pages配置中对应的第一个页面,必须在tabBar中配置
- iconPath中的配置,不能使用相对路径,只能使用绝对路径。可在项目的根目录中设置assets文件夹放置图片
"tabBar": {
"list": [{
"pagePath": "pages/foo/foo",
"text": "foo",
"iconPath": "assets/tabs/home.png",
"selectedIconPath": "assets/tabs/home-active.png"
},
{
"pagePath": "pages/demo/demo",
"text": "demo",
"iconPath": "assets/tabs/message.png",
"selectedIconPath": "assets/tabs/message-active.png"
}
逻辑与页面结构分离
视图层: WXML WXSS 展示逻辑层数据,接收用户输入
逻辑层:由js完成,处理生命周期事件
逻辑层的javaScript
应用的生命周期
应用的生命周期在app.js
文件中
// 用于去创建一个应用实例对象
App({
// 在整个应用启动时触发
// 只会触发一次
onLaunch: function () {
console.log('应用启动')
},
// 应用程序显示到屏幕上
// 每次成为焦点状态触发
onShow: function (options) {
console.log('应用前台显示')
console.log(options)
},
onHide: function () {
console.log('应用后台隐藏')
},
// 只能捕获到运行阶段的异常
onError: function (msg) {
console.log(msg)
},
// 除了生命周期的钩子函数,还可以定义其他成员
// 定义的成员在其他页面中可共享
foo: "bar",
say () {
console.log('hi~~~~')
}
})
index.js
可以使用app.js
中定义的成员
onLoad: function (options) {
// 获取全局唯一的应用程序实例对象
const app = getApp()
console.log(app.foo)
app.say()
},
页面的生命周期
页面的生命周期在页面对应的js文件中设置,例如index.js
// 创建一个页面实例对象
Page({
data: {},
// 页面加载
// 适用于数据初始化
onLoad () {
console.log('index page on load')
this.setData({ foo: 'hello yd'})
},
// 页面进入焦点状态(前台展示)
onShow () {
console.log('index page on show')
},
onHide () {
console.log('index page on hide')
},
// 当前页面渲染完成
onReady () {
console.log('index page on ready')
// 举例,只有页面加载完成,才可以设置标题
wx.setNavigationBarTitle({
title: 'foo',
})
},
// 页面卸载 当前页面被销毁
onUnload () {
console.log('index page on unload')
}
})
index.wxml
<text>{{ foo }}</text>
数据绑定 和 wxs
在小程序中,所有的数据都定义的逻辑文件,例如index.js
中的data中
index.wxml
<view class='container'>
<!-- mustache 小胡子语法 可用于输出逻辑层暴露的数据 -->
<text>{{message}}</text>
<!-- mustache 可以作用在元素的内容和属性上 -->
<input value='{{message}}'></input>
<!-- 字符串拼接 运算 逻辑判断 三元表达式 均可 -->
<input value='{{message}}~~~'></input>
<text>{{ 22 + 22 }}</text>
<!-- wxml中属性的值如果在引号内部 它永远是字符串 如下,第一个勾选了,第二个没勾选 -->
<checkbox checked='false'></checkbox>
<checkbox checked='{{false}}'></checkbox>
<text>{{foo.addFn(1)}}</text>
</view>
<!-- wxs 类似与html中的script标签 -->
<wxs module='foo'>
// 此处导出的对象可直接在界面上使用
// 此处代码必须遵循commonjs规范
// 报错 -- 暂未解决
module.exports = {
addFn: function (value) {
return value + '1'
}
</wxs>
index.js
Page({
data: {
// data对象里的所有属性都可以在界面中访问到
message: "hello goudaner~"
}
})
基本组件
小程序提供的常用标签组件
-
view
hover-class
属性,指定按下去的效果,当值为none
时,没有点击动态效果。
tag.wxml
<view hover-class="bg">
点我试试
</view>
tag.wxss
.bg {
background-color: yellow;
}
-
text
显示普通的文本,text
里面只能嵌套text
selectable
文本是否可选
decode
是否解码
tag.wxml
<text selectable="{{true}}">
长按我试试
</text>
<text decode="{{true}}">
冯 薪<朵
</text>
-
image
web中图片标签和背景图片的结合,不支持背景图片的写法
mode
裁切、缩放的模式
lazy-load
懒加载,只针对page
与scroll-view
下的image
有效 -
swiper
tag.wxml
<view>
轮播
<swiper indicator-dots="false" indicator-color="rgba(0,0,0,.3)" indicator-active-color="rgba(0,0,0,.8)" autoplay="true" interval="1000">
<swiper-item>
1
</swiper-item>
<swiper-item>
2
</swiper-item>
<swiper-item>
3
</swiper-item>
</swiper>
</view>
wxss
swiper-item {
background-color: pink;
}
-
navigator
tag.wxml
<!-- target self/miniProgram -->
<!-- open-type
navigate 保留当前页面,跳转到其他页面,不能跳转tabbar页面
redirect 关闭当前页面,跳转到其他页面,不能跳转tabbar页面
switchTap 跳转到tabbar页面,关闭其他页面
reLaunch 关闭所有页面,打开应用内的某个页面
navigateBack 返回上一页面
exit 退出小程序,target为miniProgram时生效
-->
<navigator target="self" url="../message/message" open-type="navigate">
点击跳转
</navigator>
自定义组件
创建自定义组件,创建位置/components/Mytext
控制属性
条件渲染
condition.wxml
<view wx:if="{{ isLoading }}">
<text>加载中……</text>
</view>
<!-- <view wx:elif=""></view> -->
<view wx:else>
<text>加载完毕!!!</text>
</view>
<!-- 对于频繁切换的元素 不应使用wx:if 应使用hidden -->
<view hidden="{{ !isLoading }}">
<text>加载中……</text>
</view>
<view hidden="{{ isLoading }}">
<text>加载完毕!!!</text>
</view>
<!-- block是包装元素 不会对界面的结构造成影响 -->
<view>
<block wx:if="{{ isLoading }}">
<text>加载中</text>
<text>……</text>
</block>
<text>嘤嘤嘤~别隐藏我~~~</text>
</view>
condition.js
Page({
data: {
isLoading: true
},
onReady () {
setTimeout( () => {
this.setData ({ isLoading: false})
}, 3000)
}
})
列表渲染
each.js
中,提供要渲染的数据,和视图层的事件处理函数
Page({
data: {
snh: [
{ id: 1, name: 'fxd', age: 18 },
{ id: 2, name: 'htt', age: 16 },
{ id: 3, name: 'fqy', age: 17 },
{ id: 4, name: 'qyw', age: 19 },
]
},
// 页面上除了生命周期钩子外,可定义其他函数
// 这些函数可作为视图层元素的事件处理函数
addItemHandle () {
const snh = [{ id: Math.floor(Math.random()), name: 'nc' + Math.floor(Math.random()), age: Math.floor(Math.random()) + 10}].concat(this.data.snh)
this.setData({ snh })
}
})
each.wxml
<view>
<!-- 写法1 -->
<!-- item index 是默认的 -->
<!-- key值必须要配 详见写法3中的说明 -->
<view wx:for="{{snh}}" wx:key="{{id}}">
<text>{{index}}</text>
<text>name: {{item.name}}</text>
</view>
<!-- 写法2 -->
<!-- item改变 -->
<view wx:for="{{snh}}" wx:for-item="jxl" wx:key="{{id}}">
<text>{{index}}</text>
<text>name: {{jxl.name}}</text>
</view>
<!-- 写法3 -->
<!-- wx:key 绑定的是单项属性名称,属性名前不必加item -->
<!-- 如果是纯数组,没有属性名称,那么可以使用*this去指定当前被遍历的元素 -->
<view wx:for="{{snh}}" wx:key="id">
<checkbox/>
<text>{{item.name}}</text>
</view>
<!-- key值,每个数据的唯一标识,确定数据和界面内容的一一对应关系 -->
<!-- 如果不加key值,这边新增内容后,勾选的项目会发生改变 -->
<button bindtap="addItemHandle">add</button>
<!-- 写法4 -->
<!-- 循环内容为字符串时,会拆开字符串 -->
<view wx:for="fxdd" wx:key="*this">--{{item}}--</view>
</view>
事件处理
dothings.js
中定义事件处理函数
Page({
// 定义应用于界面层的事件处理函数
tapHandle (e) {
console.log(e)
}
})
dotings.wxml
中调用事件处理函数
<button bindtap="tapHandle">点击</button>
当点击按钮时,控制台打印结果如下
- timeStamp -- 触发事件的时间,与页面加载完成的时间差
- target -- 拿到当前被点击的元素
- detail -- 以屏幕左上角为原点,触发事件时点击的坐标
事件冒泡
在小程序中,绑定事件时,将bind改成catch就能阻止事件冒泡。
dotings.js
Page({
// 定义应用于界面层的事件处理函数
tapHandle (e) {
console.log(e)
},
viewTapHandle (e) {
console.log('冒泡', e)
}
})
dothings.wxml
<view bindtap='viewTapHandle'>
<!-- 使用bindtap会冒泡 -->
<!-- <button bindtap="tapHandle">点击</button> -->
<!-- 使用catchtap不会冒泡 -->
<button catchtap="tapHandle">点击</button>
</view>
获取当前行的参数
可以通过data-xx属性,给事件处理函数传递额外的参数。
dothings.js
Page({
removeHandle (e) {
console.log(e)
}
})
dothings.wxml
<view>
<text>item 1</text>
<button bindtap='removeHandle' data-id='1'>移除</button>
</view>
<view>
<text>item 2</text>
<button bindtap='removeHandle' data-id='2'>移除</button>
</view>
<view>
<text>item 3</text>
<button bindtap='removeHandle' data-id='3'>移除</button>
</view>
当点击第二个移除按钮时,控制台数据如下
单项数据流
小程序和react相似,都是单项数据流
需求:输入框中值改变时,上方显示的文字也发生变化
代码:
index.js
Page({
data: {
content: 'fxd is fdd'
},
inputChangeHandle (e) {
// 1. 改变数据源
// 2. 通知框架,重新渲染页面
this.setData({content: e.detail.value})
}
})
index.wxml
<text>{{content}}</text>
<input value='{{content}}' bindinput='inputChangeHandle'></input>
index.wxss
input {
border: 1px solid pink;
margin: 20px;
padding: 10px;
}
小程序不同于vue,数据发生变化时,如果要在页面的其他位置展示变化后的数据,一定要在逻辑层使用setData
wxss和css的对比
- rpx
rpx(responsive pixel):可以根据屏幕宽度进行自适应,规定屏幕宽度为750rpx。
百分比的缺点:
margin padding使用百分比时非常混乱
百分比涉及到父子盒子之间的传递
- weui
微信小程序的ui框架,使用时可以在dist/example中找demo。