微信小程序(二)特点&语法介绍&demo获取用户授权信息
1. 小程序特点&小程序宽度适配方案
- 没有DOM
- 组件化开发:具有特定功能的代码集合
- 体积小:单个压缩包小于2M,否则无法上传。 另外体积小就下载比较快,第一次打开小程序会loading 快速的下载。
- 四个重要文件:
Json: 配置文件
wxml:页面元素,类似于html
wxss:类似于css
js:js用于交互
- 小程序适配方案:rpx(response pixel 响应式像素单位)
小程序适配单位:rpx,规定任何屏幕下宽度为750 rpx
小程序会根据屏幕的宽度不同计算rpx 值的大小
比如:iphone6 的宽度为375 * 667 px, 物理像素是750 * *1334。 所以iphone6下: 1rpx = 1物理像素 = 0.5px
2. 小程序文件介绍
1. 创建小程序
1. 创建
创建一个基础模板, 注意是JS 模板。 其他还有一些电商、报名等模板可以选择。 后续学习完之后可以用其他模板。创建完成后目录结构如下:
2. 查看编译后的wxml
可以看出默认每个页面会加一个page 标签,是全局的标签。 修改全局样式可以对page 进行修改。
2. 文件介绍
对主要文件进行介绍:
1. 配置文件
1. 全局配置: app.json
作用: 用来对微信小程序进行全局配置。文件内容为一个 JSON 对象。
文档:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html
主要属性:
pages string[] 页面路径列表(必填)
sitemapLocation string 指明 sitemap.json 的位置(必填)
entryPagePath string 小程序默认启动首页。 如果不填,将默认为 pages 列表的第一项。不支持带页面路径参数。
window object 用于设置小程序的状态栏、导航条、标题、窗口背景色。
也可以再JS内动态修改窗口标题
wx.setNavigationBarTitle({
title: this.data.song.name
})
上面默认生成的app.json 内容:
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
2. 配置: sitemap.json
解释:
微信现已开放小程序内搜索,开发者可以通过 sitemap.json 配置,或者管理后台页面收录开关来配置其小程序页面是否允许微信索引。当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索词条触发该索引时,小程序的页面将可能展示在搜索结果中。 爬虫访问小程序内页面时,会携带特定的 user-agent:mpcrawler 及场景值:1129。
内容:
rules Object[] 是 索引规则列表
对象包含的属性:
action string "allow"(默认值)、"disallow" 命中该规则的页面是否能被索引
page string "*"、页面的路径 * 表示所有页面,不能作为通配符使用
上面默认生成的sitemap.json 内容:
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
一般会开启允许爬虫,增加曝光率。
3. 项目配置Project.config.json
项目配置文件,包含appId、projectName 等信息。 一般可以从编辑器直接修改,也可以从导航栏的详情进行修改(也是改配置文件)。
4. 项目私有配置project.private.config.json
项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。
2. 小程序app
1. app.js 全局JS文件
注意:
全局app.js 执行App() 方法生成当前应用的实例对象,App() 必须在 app.js
中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
AppObject getApp(Object object) 用于获取到小程序全局唯一的 App
实例。
例如:
// other.js
var appInstance = getApp()
console.log(appInstance.globalData) // I am global data
注意:
不要在定义于 App() 内的函数中,或调用 App 前调用 getApp() ,使用 this 就可以拿到 app 实例。
通过 getApp() 获取实例之后,不要私自调用生命周期函数。
2. app.wxss 全局样式文件
用于控制样式,优先级低于页面控制
3. 页面以及相关文件
每个页面包含四个文件。 json、js、wxml、wxss。 而且都是以页面命名。 而且在pages 目录右击新建的时候有个选项是新建Page, 会自动生成四个文件。
1. wxml
类似于html, 里面是标签。 view 等价于div 标签。 text 等价于span 标签。
2. json
作用:为指定页面进行配置,优先级高于全局配置。比如可以定义页面的标题、背景色等。如果没有设置取全局app.json 的配置。
3. js
页面配置文件。
Page(Object object) 注册小程序中的一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
PageObject[] getCurrentPages() 获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。
4. wxss
页面样式控制文件,等价于css
4. utils 工具类
工具类类似于vue语法,暴露相关方法,其他模块引入。 比如:
util.js
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : `0${n}`
}
module.exports = {
formatTime
}
logs.js 引入
const util = require('../../utils/util.js')
// 使用
util.formatTime(new Date(log))
3. 手动创建项目完成第一个demo
将所有的项目都删掉,只保留上面的:project.config.json、project.private.config.json、sitemap.json
1. 新建第一个页面
根目录下新建pages目录,然后新建index目录,新建page-》index (会自动生成四个文件都是以index命名)
默认生成的文件信息如下:
index.wxml
<!--pages/index/index.wxml-->
<text>pages/index/index.wxml</text>
index.js
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
2. 根目录下新建app.json
内容如下: (可以看到只需要配置页面列表,默认数组的第一个为项目的首页)
{
"pages": [
"pages/index/index"
]
}
3. 根目录下新建 app.js 和 app.wxss
内容如下: (输入App tab 会自动补全函数)
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
},
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
}
})
app.wxss 先不编写样式
/* 放置全局样式 */
4. 编译预览即可看到index.wxml 的内容
5. 继续改造实现类似于模板项目的效果
实现如下目标:
1. 背景色改为#ddd,标题改为George
2. 内容区域增加头像和昵称,昵称是动态的数据,类似于vue 的数据绑定。
3. 下面显示hello world。 同时点击的时候弹出对话框。
4. 页面全局背景色也改为#ddd
调整:
- 目录下新增静态资源目录: 和pages 同级。 static/image/ 下面存自己的图片
- 修改app.json 修改默认打开的标题和背景色
{
"pages": [
"pages/index/index"
],
"window": {
"navigationBarBackgroundColor": "#ddd",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "Geogre"
}
}
注意这里的背景色只能用颜色码,不支持英语
- app.wxss 设置page 的页面高度为100%
/* 放置全局样式 */
page {
height: 100%;
}
- Index.html 调整
<view class="indexContainer">
<image src="/static/image/1.jpg" class="avataUrl"></image>
<text class="userName">{{username}}</text>
<view class="goStudy" bindtap="clickHelloworld"><text>hello world</text></view>
</view>
- index.wxss 设置样式
/* pages/index/index.wxss */
.indexContainer {
display: flex;
flex-direction: column;
align-items: center;
background-color: #ddd;
height: 100%;
}
.avataUrl {
width: 200rpx;
height: 200rpx;
border-radius: 50%;
margin: 100rpx 0;
}
.userName {
font-size: 32rpx;
margin: 100rpx 0;
}
.goStudy {
width: 300rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 28rpx;
border: 1rpx solid #333;
border-radius: 10rpx;
}
设置为flex 布局且是纵轴为主轴,且横轴上为居中对齐。
- index.js 设置username 数据以及定义点击函数
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
username: "Qiao-Zhi"
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
},
// 自定义函数
clickHelloworld() {
wx.showModal({
title: '提示',
content: '这是一个模态弹窗',
success (res) {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
})
- 效果预览
6. 继续改造完成获取当前用户信息,然后展示用户头像和昵称
原来应该是有两个API。但是新版本不提供使用了。 只能单独获取头像和昵称,然后自己维护账号体系。
参考: https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/userProfile.html
- 修改wxml
<view class="indexContainer">
<!--helloworld 学习区域-->
<view class="goStudy" bindtap="clickHelloworld"><text>hello world</text></view>
<!--微信头像区域-->
<image wx:if="{{avatarUrl}}" class="avataUrl" src="{{avatarUrl}}"></image>
<button wx:else class="avatar-wrapper goStudy" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
点击上传头像
</button>
<!--昵称区域-->
<view class="page-section">
<view class="weui-cells__title">昵称 </view>
<view class="weui-cells weui-cells_after-title">
<view class="weui-cell weui-cell_input">
<input type="nickname" class="weui-input" placeholder="请输入昵称" />
</view>
</view>
</view>
</view>
- 修改js
// const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
avatarUrl: ''
},
/** S 自定义函数 */
clickHelloworld() {
wx.showModal({
title: '提示',
content: '这是一个模态弹窗',
success (res) {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
},
onChooseAvatar(e) {
console.log("onChooseAvatar ", e)
const { avatarUrl } = e.detail
this.setData({
avatarUrl,
})
},
/** E 自定义函数 */
})
- 修改wxss
/* pages/index/index.wxss */
.indexContainer {
display: flex;
flex-direction: column;
align-items: center;
background-color: #ddd;
height: 100%;
}
.avataUrl {
width: 200rpx;
height: 200rpx;
border-radius: 50%;
margin: 100rpx 0;
}
.userName {
font-size: 32rpx;
margin: 100rpx 0;
}
.getCurrentUserInfoBtn {
font-size: 28rpx;
border: 1rpx solid #333;
border-radius: 10rpx;
margin: 100rpx 0;
background-color: #ddd;
}
.goStudy {
width: 300rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 28rpx;
border: 1rpx solid #333;
border-radius: 10rpx;
margin: 100rpx 0;
}
- 效果