文章目录
- 一. 项目基本配置
- 1. 项目组成
- 2. 常见的配置文件解析
- 3. app.json全局的五大配置
- 4.单个页面中的page配置
- 5. App函数
- 6.tabBar配置
- 二. 基本语法,事件,单位
- 1. 语法
- 2. 事件
- 3. 单位
- 三. 数据响应式修改
- 四 . 内置组件
- 1. button
- 2. image
- 3. input
- 4. 组件共有属性
- 五 . WXS使用
- 六,组件
- 6.1 全局与局部组件注册使用
- 6.2 组件样式
- 6.3 组件之间的通信
- 6.4 单个插槽的使用
- 6.5 多个插槽的使用
- 6.6 混入
- 6.7 组件生命周期
- 6.8 数据侦听
- 七 .生命周期
- 7.1.应用生命周期
- 7.2 页面生命周期
- 7.3.组件生命周期
- 八 . API解析
- 8.1网络请求
- 8.2 展示弹窗效果
- 8.3 获取设备|位置信息
- 8.4 Storage存储
- 8.5 页面跳转
- 8.6 回退页面传参
- 九 .登录流程
一. 项目基本配置
1. 项目组成
2. 常见的配置文件解析
project.config.json
:项目配置文件, 比如项目名称、appid等 ; 配置详情sitemap.json
:小程序搜索相关的;配置详情app.json:
全局配置page.json
:页面配置;app.js
可共享全局属性值
3. app.json全局的五大配置
pages:
页面路径列表- 用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径(含文件名) 信息。
- 小程序中所有的页面都是必须在pages中进行注册的。
window:
全局的默认窗口展示- 用户指定窗口如何展示, 其中还包含了很多其他的属性
tabBar:
顶部tab栏的展示- 详情配置参考
{
"pages": [
"pages/home/home"
],
"window": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#f6f866",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
"tabBar": {
"color": "#777",
"selectedColor": "#1cb9ce",
"list": [{
"pagePath": "pages/home/home",
"text": "主页面”},
{
"pagePath": "pages/day02/day02",
"text": "home"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
4.单个页面中的page配置
-
可直接
新建page 并回车,自动添加到pages中
或者在pages中直接指定
-
同时每一个小程序页面也可以使用
.json
文件来对本页面的窗口表现进行配置。- 页面中配置项在当前页面会覆盖
app.json 的 window
中相同的配置项 - 具体配置参考官网
- 页面中配置项在当前页面会覆盖
{
"usingComponents": {},
"navigationBarTitleText": "主页面",
"backgroundTextStyle": "dark", 背景文字颜色
"enablePullDownRefresh": true, 允许下拉刷新
"backgroundColor":"#f70", 背景颜色
"onReachBottomDistance": 100 距离底部多少触发事件
}
// 下拉刷新, 获取最新的数据
onPullDownRefresh() {
console.log('监听下拉刷新');
// 停止下拉刷新
setTimeout(() => {
// 异步请求
wx.stopPullDownRefresh({
success: (res) => {
console.log('停止', res)
},
})
}, 1000)
},
// 监听页面滚动到底部
onReachBottom() {
console.log('滚动到底部多少距离时加载更多~~ 100px');
this.setData({
listCounter: this.data.listCounter + 30
})
}
5. App函数
- App()实例可以全局共享的(单例对象),所以可以将一些共享数据放在这里;
- App函数的参数
作用一:
- 判断群聊会话中打开、小程序列表中打开、微信扫一扫打开、另一个小程序打开
- 在onLaunch和onShow生命周期回调函数中的options参数,判断
scene
值 - 文档参考
- 在onLaunch和onShow生命周期回调函数中的options参数,判断
作用二:定义全局App的数据
app.js
// app实例可以共享全局数据
globalData: {
userInfo: null,
token: 'Afjwt-12mandak-45'
}
home.js
onLoad() {
const {
globalData
} = getApp() // 全局的app实例
console.log(globalData.token);
// 拿到token发送网络请求-页面初始化
this.setData({
globalData
})
},
作用三:生命周期函数
- 在生命周期函数中,完成应用程序启动后的初始化操作
- 完成登录操作,获取token
- 完成登录操作,获取token
6.tabBar配置
- tabBar中只能配置
最少 2 个、最多 5 个 tab
页签 - 当渲染顶部 tabBar 时,不显示 icon,只显示文本
- 更多配置参考官网
{
"pages": [
"pages/hone/hone",
"pages/Profile/Profile",
"pages/experience/experience",
"pages/skill/skill",
"pages/index/index",
"pages/logs/logs"
],
"tabBar":{
"color": "#777",
"selectedColor": "#1cb9ce",
"list":[
{"pagePath": "pages/hone/hone","text":"简历信息","iconPath": "/pages/img/icon08.png","selectedIconPath": "/pages/img/icon08.png"},
{"pagePath": "pages/skill/skill","text":"个人技能","iconPath": "/pages/img/icon04.png","selectedIconPath": "/pages/img/icon04.png"},
{"pagePath": "pages/experience/experience","text":"项目经历","iconPath": "/pages/img/icon02.png","selectedIconPath": "/pages/img/icon02.png"},
{"pagePath": "pages/Profile/Profile","text":"自我评价","iconPath": "/pages/img/icon06.png","selectedIconPath": "/pages/img/icon06.png"}
]
},
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
二. 基本语法,事件,单位
1. 语法
参考官网基本语法解释
- 文本渲染
{{ msg}}可以执行简单的js表达式
{{2+3}}
{{msg.length}}
- 条件渲染
wx:if=""
wx:elif=""
wx:else
hidden // true 隐藏
- 列表渲染
- wx:key 针对不同的数组类型有不同的写法
- 普通数组
wx:key="*this"
- 数组对象
wx:key="字符串"
表示对象唯一属性
- 普通数组
// 默认item就是数据 ,index是下标
wx:for="{{list}}"
wx:key="index"
{{item}}
{{index}}
- 自定义列表渲染
定义item与index的名称
wx:for="{{list}}}"
wx:for-item="myitem"
wx:for-index="myidx"
{{myidx}}
{{myitem}}
2. 事件
格式:<元素 bind事件名= “回调”>
- 示例:
<view bindtap="fn1"></view>
<switch bindchange="fn2"></switch>
- 小程序中绑定事件,通过bind和capture关键字来实现。如 bindtap 和 capture-bind:tap,
- bind 是事件冒泡
外传
,capture 是事件捕获里传
。capture-bind只能用冒号形式。 - 如果想阻止事件冒泡或捕获可通过
catch来绑定事件
。如catchtap,capture-catch:tap。
bindInput 表单输入时
bindconfirm 表单输入确认
bindtap 点击时候
-
事件传参
- 自定义参数
data-*
注意点
:<view bindtap="handleTap(100)"></view>
小程序会以为 事件函数名称就是 “handleTap(100)” ,那么它就会去找“handleTap(100)” 这个函数 而不是 “handleTap”
- 自定义参数
-
mask传参
-
表单绑定
<input value="{{s1}}" bindinput="inputHd">
// js.js
inputHd(e){
this.setData({s1:e.detail.value}) // 表单的值获取:e.detail.value
}
- 事件对象属性
属性 | 类型 | 说明 |
---|---|---|
type | String | 事件类型 |
timeStamp | Integer | 页面打开到触发事件所经过的毫秒数 |
target | Object | 触发事件的组件的一些属性值集合 |
currentTarget | Object | 当前组件的一些属性值集合 |
detail | Object | 额外的信息 |
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 |
- target和currentTarget事件对象属性
属性 | 类型 | 说明 |
---|---|---|
id | String | 当前组件的id |
dataset | Object | 当前组件上由data-开头的自定义属性组成的集合 |
- 区别
taget
点击inter不能拿到dataset数据currentTarget
可以拿到
3. 单位
- rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
- 具体参考官网
三. 数据响应式修改
- WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层
- 小程序的渲染层和逻辑层分别由2个线程管理,两个线程的通信会经由微信客户端做中转
- 数据修改必须调用
this.setData
同react一样 - setData优化
四 . 内置组件
- 内置组件参考
1. button
- button组件中的
open-type
属性- open-type用户获取一些特殊性的权限,可以绑定一些特殊的事件
- 老旧版本获取用户信息
<button type="primary" bindgetuserinfo="getUserInfo" size="mini" open-type="getUserInfo">getUserInfo</button>
getUserInfo(e) {
// 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
- 新版本获取用户头像等信息
<button bindtap="getUserProfile"> 获取头像昵称 </button>
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
// 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
- 具体解析参考官网
2. image
- image组件默认宽度320px、高度240px
- image支持懒加载
- mode 配置如下
模式 | 值 | 说明 |
---|---|---|
缩放 | scaleToFill | 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 |
缩放 | aspectFit | 保持纵横比缩放图片,直到图片某一边碰到边界。 |
缩放 | aspectFill | 保持纵横比缩放图片,直到图片完全铺满边界。 |
缩放 | widthFix | 宽度不变,高度自动变化,保持原图宽高比不变 |
- wx.chooseMedia获取本地图像展示
<button bindtap="hyImageUpload">选择图片上传</button>
<!-- 选择本地图片 -->
<image src="{{imageUrl}}"></image>
hyImageUpload(){
wx.chooseMedia({
camera: 'image',
}).then(res=>{
this.setData({
imageUrl:res.tempFiles[0].tempFilePath
})
})
}
3. input
- 支持双向绑定
<input type="text" model:value=" {{message}}"/>
4. 组件共有属性
- 公共属性 :参考官网
-
属性名 类型 描述 注解 id String 组件的唯一标示 保持整个页面唯一 class String 组件的样式类 在对应的 WXSS 中定义的样式类 style String 组件的内联样式 可以动态设置的内联样式 hidden Boolean 组件是否显示 所有组件默认显示 data-* Any 自定义属性 组件上触发的事件时,会发送给事件处理函数 bind* / catch* EventHandler 组件的事件 详见事件
-
五 . WXS使用
- WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
- 在WXML中是不能直接调用
Page/Component中定义的函数
的. - 但是某些情况, 可以使用函数来处理WXML中的数据(类似于Vue中的过滤器),这个时候就使用WXS了
- 必须利用es5语法
//
<wxs module="format">
function joinTgether(num) {
return '¥' + num
}
// 必须模块化导出
module.exports={
joinTgether:joinTgether
}
</wxs>
<block wx:for="{{wxs}}" wx:key="*this">
<button size="mini" type="warn">{{item}}-{{format.joinTgether(item)}}</button>
</block>
- 模块抽离
utils
必须放在.wxs结尾的文件
<button>模块抽离wxs</button>
<wxs module="format" src="/utils_wxs/format.wxs"></wxs>
<block wx:for="{{wxs}}" wx:key="*this">
<button size="mini" type="warn">{{item}}-{{format.joinTgether(item)}}</button>
</block>
- 每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见;
- 一个模块要想对外暴露其内部的私有变量与函数,只能通过
module.exports
实现; - 其他使用参考官网
六,组件
6.1 全局与局部组件注册使用
- 将页面拆分成一个个小的、可复用的组件,这样更加方便组织和管理,并且扩展性也更强
- 在
.json
文件中进行自定义组件声明(将component 字段设为 true 可这一组文件设为自定义组件):
- 在需要使用的
xx.json
文件中导入
{
"usingComponents": {
"sel-info": "/components/selection-info/sel-info"
}
}
- 自定义组件和页面所在项目根目录名 不能
以“wx-”为
前缀,否则会报错。 - 全局组件在
app.json的usingComponents
声明某个组件,那么所有页面和组件可以直接使用该组件
6.2 组件样式
-
组件内的样式 对 外部样式 的影响
- 结论一:组件内的class样式,只对组件wxml内的节点生效, 对于引用组件的Page页面不生效。
- 结论二:组件内不能使用id选择器、属性选择器、标签选择器
-
外部样式 对 组件内样式 的影响
- 结论一:外部使用class的样式,只对外部wxml的class生效,对组件内是不生效
- 结论二:外部使用了id选择器、属性选择器不会对组件内产生影响
- 结论三:外部使用了标签选择器,会对组件内产生影响
-
如何让class可以相互影响
- 在
Component对象
中,可以传入一个options
属性,其中options属性中有一个styleIsolation
(隔离)属性。 - styleIsolation有三个取值:
isolated
表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(默认取值);apply-shared
表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;shared
表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置 了
- 在
options: {
// styleIsolation:"isolated" // 默认值
styleIsolation: "apply-shared"
},
6.3 组件之间的通信
- 文档参考
组件传递数据 -properties
- 定义子组件
<view style="width: 100%;height:80px;background-color: blueviolet;">
<button>{{title}}</button>
<view style="background-color: brown;margin-top: 10px; color: cornsilk;"> {{content}}</view>
</view>
- 子组件做数据接收并默认值
properties: {
title: {
type: String,
value: '默认标题'
},content:{
type:String,
value:'默认内容'
}
},
- 父组件使用子组件并传递值
<props-data />
<view class="styl">
<props-data title="通信" content='组件通信-传递参数-动态数据' />
</view>
<props-data title="z组件传参" content='组件通信-传递参数-动态数据' />
组件传递样式 -externalClasses
- 在Component对象中,定义
externalClasses
属性 - 在组件内的wxml中使用externalClasses属性中的class
- 在页面中传
入对应的class
,并且给这个class设置样式
自定义事件
页面直接调用组件方法 相当于vue中ref- 可在父组件里调用 this.selectComponent ,获取子组件的实例对象。
- 调用时需要传入一个匹配选择器 selector,
6.4 单个插槽的使用
-
组件的插槽也是为了让我们封装的组件更加具有扩展性
注意slot 不支持默认值
可以利用兄弟选中器解决
- 子组件预留插槽
<view class="myslot">
<view class="header">header</view>
<!-- 小程序插槽不支持默认值 -->
<view class="content">
<slot></slot>
</view>
<view class="default">兄弟选择器解决默认值</view>
<view class="footer">footer</view>
</view>
- 父组件传递结构
<my-slot>
<button>按钮</button>
</my-slot>
<my-slot>
<button size="mini" type="primary">default样式</button>
</my-slot>
<my-slot>
</my-slot>
- 兄弟选择器解决默认值问题
.default{
display: none;
}
.content:empty + .default{
display: block;
}
6.5 多个插槽的使用
- 子组件预留插槽
<view class="slot">
<view class="t">
<text >上插槽</text> :
<slot name="t"></slot>
</view>
<view class="c">
<text>中间插槽</text> :
<slot name="c"></slot>
</view>
<view class="b">
<text>下插槽</text> :
<slot name="b"></slot>
</view>
</view>
- 允许可以定义多个插槽
Component({
// 允许定义多个插槽
options: {
multipleSlots: true
},
})
- 父组件传递结构
<more-slot>
<text slot="t">上插入</text>
<text slot="c">中间插入</text>
<text slot="b">下插入</text>
</more-slot>
6.6 混入
- behaviors 是用于组件间代码共享的特性,
类似于Vue中的 “mixins”
。- 每个 behavior 可以包含一组属性、数据、生命周期函数和方法;
- 组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用;
- 每个组件可以
引用多个 behavior ,behavior 也可以引用其它 behavior
; - 文档参考
- 编写混入
export const counterMinxin = Behavior({
data: {
counter: 100
},
methods: {
add() {
// 加一修改 ,不应该使用++,这会导致counter在修改this..data.counter也在修改
this.setData({
counter: this.data.counter + 1
})
}
}
})
- 使用
import { counterMinxin } from "../../behaviors/counter"
Component({
behaviors: [counterMinxin],
})
6.7 组件生命周期
- 组件的的生命周期在
lifetimes
字段内进行声明 - 组件生命周期文档参考
Component({
behaviors: [counterMinxin],
lifetimes:{
created(){
console.log('组件被创建');
},
attached(){
console.log('组件添加到dom树中');
},
detached(){
console.log('组件被删除');
}
}
})
6.8 数据侦听
文档参考链接
七 .生命周期
7.1.应用生命周期
应用生命周期钩子函数
属性 | 说明 |
---|---|
onLaunch | 生命周期回调——监听小程序初始化。 |
onShow | 生命周期回调——监听小程序启动或切前台。 |
onHide | 生命周期回调——监听小程序切后台。 |
onError | 错误监听函数。 |
- 参数对象
- 一般放在生命周期钩子函数的第一个参数。
onLaunch
钩子函数的参数对象为
- 一般放在生命周期钩子函数的第一个参数。
7.2 页面生命周期
- 文档参考
属性 | 说明 |
---|---|
onLoad | 生命周期回调—监听页面加载 |
onShow | 生命周期回调—监听页面显示 |
onReady | 生命周期回调—监听页面初次渲染完成 |
onHide | 生命周期回调—监听页面隐藏 |
onUnload | 生命周期回调—监听页面卸载 |
onPullDownRefresh | 监听用户下拉动作 |
onReachBottom | 页面上拉触底事件的处理函数 |
onShareAppMessage | 用户点击右上角转发 |
onShareTimeline | 用户点击右上角转发到朋友圈 |
onAddToFavorites | 用户点击右上角收藏 |
onPageScroll | 页面滚动触发事件的处理函数 |
onResize | 页面尺寸改变时触发,详见 响应显示区域变化 |
// 1. 页面路径
pages/index/index?id=10086&name='admin'
// 2. onLoad 获取参数
onLoad(query){}
7.3.组件生命周期
- 文档参考
属性 | 说明 |
---|---|
created | 组件生命周期函数 - 在组件实例刚刚被创建时执行,注意此时不能调用 setData ) |
attached | 组件生命周期函数 - 在组件实例进入页面节点树时执行) |
ready | 组件生命周期函数 - 在组件布局完成后执行) |
moved | 组件生命周期函数 - 在组件实例被移动到节点树另一个位置时执行) |
detached | 组件生命周期函数 - 在组件实例被从页面节点树移除时执行) |
八 . API解析
8.1网络请求
- 网络请求:
wx.request(Object object)
- 官网参考
wx.request({
url: "api",
data: {
page: 1
},
success: res => {
console.log(res);
},
fail: err => {}
})
- 封装
//0. 封装成函数
export function hyRequest(options) {
return new Promise((resolve, reject) => {
wx.request({
...options,
success: res => {
resolve(res.data)
},
fail: reject
})
})
}
//0. 类的方法封装
class hyService {
request(options) {
return new Promise((resolve, reject) => {
wx.request({
...options,
success: res => {
resolve(res.data)
},
fail: reject
})
})
}
get(options) {
return this.request({ ...options, method: 'GET'})
}
post(options) {
return this.request({
...options,
method: 'POST'
})
}
}
export const serviceResponse = new hyService()
// 1. 导入
import {hyRequest} from '../../service/request'
// 2. 使用封装调用api
hyRequest({url:"http://123.207.32.32:1888/api/city/all"}).then(res=>{
console.log(res);
})
8.2 展示弹窗效果
- 具体配置参考
8.3 获取设备|位置信息
- 获取当前设备的信息,用于手机信息或者进行一些适配工作
wx.getSystemInfo(Object object)
- 官网参考
- 获取用户的位置信息,以方便给用户提供相关的服务
wx.getLocation(Object object)
reqInfo() {
// 获取设备信息
// 我们需要经常获取当前设备的信息,用于手机信息或者进行一些适配工作
wx.getSystemInfo({
success: arr => {
console.log(arr);
}
}),
wx.getLocation({
success:err=>{
console.log(err);
}
})
}
注意获取位置信息需要相关权限
- 配置参考
"permission": {
"scope.userLocation": {
"desc": "位置信息将用于小程序位置接口的效果展示"
}
}
8.4 Storage存储
- 同步存取数据的方法:
- wx.setStorageSync(string key, any data)
- wx.getStorageSync(string key)
- wx.removeStorageSync(string key)
- wx.clearStorageSync()
- 异步存储数据的方法:
- wx.setStorage(Object object)
- wx.getStorage(Object object)
- wx.removeStorage(Object object)
- wx.clearStorage(Object object)
- 具体使用参考
8.5 页面跳转
- 通过navigator组件 和 通过wx的API跳转
- 路由跳转参考配置
页面跳转 -navigateTo
注意
跳转的页面是tarBar内的页面,需要使用wx.switchTab({})
navigateTo() {
// 跳转的页面是tarBar内的页面,需要使用wx.switchTab({})
wx.navigateTo({
// url: '/navPage/navigateTo/index',
// 传参
url: '/navPage/navigateTo/index?name=admin',
})
}
- 接受页面跳转的参数
Page({
// options接受路径参数
onLoad(options) {
console.log(options);
},
})
8.6 回退页面传参
- 主页面
Page({
navigateTo() {
// 方式二
wx.navigateTo({
url: '/navPage/navigateTo/index?name=admin',
events: {
backEvent(data) {
console.log('接受跳转的参数', data);
}
}
})
}
})
- 跳转的页面
Page({
up() {
wx.navigateBack()
// // 传递数据给上一级
// const pages = getCurrentPages()
// //读取最后一个页面,的实例
// const prePage = pages[pages.length - 2]
// // 设置上一个页面的数据
// prePage.setData({
// message: 'admin'
// })
// console.log(pages);
const eventChannel = this.getOpenerEventChannel()
eventChannel.emit('backEvent', {
name: 'admin',
pad: 'password'
})
},
// 回退过多可以直接在onLoad里面设置
onUnload() {
const pages = getCurrentPages()
const prePage = pages[pages.length - 2]
prePage.setData({
message: 'admin',
username: 'password'
})
},
})
九 .登录流程
- 配置参考
openid: 用户唯一标识
session_key: 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥
// app.js
App({
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
const code = res.code
wx.request({
url: 'url',
data: {
code
},
method: 'POST',
success: res => {
const token = res.data.token
wx.setStorageSync('token', token)
}
})
}
})
},
})
- 参考文章
- 微信小程序开发(超详细保姆式教程)
- coderwhy