小程序
下载地址
project.content.js
:项目配置文件
AppID
和projectname
sitemap.json
:配置小程序索引,基本都是可索引
App.js
:注册小程序
app.json
:全局配置
pages
:配置路由那个路由在上面就那个为首页
window
:配置窗口表现,导航栏颜色,字体,字色,窗口背景色,下拉loading,
是否下拉刷新,上拉到顶部距离,屏幕旋转
entryPagePath
:不按照pages顺序,指定首页app.wxss
:就是css
文件:微信不能使用ID选择器
pages:里面是页面文件
static:自己创建的文件夹,放置静态文件
view
对于div
,text
对应span
1px = 2rpx
;设计图为750page { heigth: 100% }
将app.json
里window的属性之间拿到当前页面的index.json
{
"usingComponents": {},
"navigationBarTitleText": "Hello" // 当前页面直接设置
// 局部优先级大于全局
}
js
动态修改
wx.setNavigationBarTitle({ title: '旭大王' })
// 文档 => api => 交互 => 导航栏
// 还有其他控制
1、创建初始化数据:
在页面文件下index.js
里面page对象的data里面创建数据
可以通过调试器的appData查看初始化数据
视图层:
视图层:
js
: console.log(this.data.msg)
2、修改数据
js修改数据
:this.setDate({ msg: 'success' })
;同步
Tap 相当于 click
touchstart
:手指点击:e.touches[0].clientY
touchmove
:手指移动touchend
:手指抬起通过距离判断实现上拉自定义动画
style="transform: {{ coverTansform }}"
target
:可能是当前元素,可能是父元素
currentTarget
:肯定是当前元素
detail.value
:表单组件返回的value
事件入参:
<view
id="dataSet"
data-alpha-beta="1"
data-alphaBeta="2"
bindtap="bindViewTap"
> DataSet Test view>
Page({
bindViewTap:function(event){
event.currentTarget.id === dataSet
event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
cosnt value = event.detail.value // 表单组件返回的value
}
})
<view wx.if="{{ isUser }}">有用户view>
<view wx.else >无用户view>
语法:wx:for
默认数组的当前项的下标变量名默认为 index
,数组当前项的变量名默认为 item
<view wx:for="{{array}}">
{{index}}: {{item.message}}
view>
<view
wx:for="{{array}}"
wx:for-index="idx"
wx:for-item="itemName"
>
{{idx}}: {{itemName.message}}
view>
<view wx:for="{{ arr }}" wx:key="name">
{{ item.name }}
view>
新建components文件夹,文件夹创建nav
文件,右键选中新建component
新建后出现的4个文件和页面文件一样,但是不会自动添加路由
引入注册:在页面的.json
文件里usingComponents
配置
{
"usingComponents": {
"HeadBox": "/components/HeadBox/HeadBox"
}
}
组件间传值:无法传值
父传子:
<view>
父组件
<Child title="传入值">子组件Child>
view>
// 子组件的js里面会有properties, 接收传值
// 和vue的props类似,value 相当于 default
properties: {
title: {
type: String,
value: '默认值'
}
}
// 且properties的值会自带同步给data
子传父
父传子:
<component-tag-name bindmyevent="onMyEvent" />
// 父组件
onMyEvent(e) { console.log(e.detail.name) }
<button bindtap="onTap">点击这个按钮将触发“myevent”事件button>
// 子组件
onTap() {
this.triggerEvent('myevent', { name: 'xu' })
}
子传父:
const son = this.selectComponent("#id")
获取子组件son.go()
调用子组件go方法其他方式
pubsub-js
import Pubsub from 'pubsub-js'
// 订阅
const pubsub = Pubsub.subscribe("订阅名", (msg, data) => {
console.log(msg) // 这里将会输出对应设置的 pubsubID
console.log(data) // 这里将会输出对应设置的参数
})
// 取消订阅
Pubsub.unsubscribe(pubsub)
// 取消全部订阅
PubSub.clearAllSubscriptions()
import Pubsub from 'pubsub-js'
// 发布
Pubsub.publish("订阅名", data)
// 或
PubSub.publishSync("订阅名", data)
创建templates文件夹,和pages同级
创建test文件夹,并新建页面
页面里面wxml
写模板,模板样式协助
<template name="msgItem">
<view class="username">
<text>username: {{ name }} text>
view>
template>
/* 模板样式 */
.msgItem {
height: 40px;
border: 1px solid red;
}
.username {
line-height: 30px;
font-size: 16px;
}
页面使用模板
<import src="/templates/test/test.wxml" />
<view>
<template is="msgItem" data="{{...item}}"/>
view>
@import "/templates/test/test.wxss"
/* 下面定义的样式会覆盖模板样式,注意命名 */
编程式跳转
wx.navigateTo()
wx.navigateTo({
url: '/pages/index/index', // 必须加根路径
events: { callback: (data) => { console.log(data) } }
// 被打开页面给当前页面反馈
// 其他还有success回调,fail失败回调,complete跳转回调
success: (res) => {
res.eventChannel.emit('reverse', { name: '大王' })
}
})
// 会保留跳转记录
// 被打开页面
onLoad(options) {
const eventChannel = this.getOpenerEventChannel()
eventChannel.emit('callback', { name: '旭' });
// 调用上个页面的回调
eventChannel.on('reverse', (data) => { console.log(data) });
// 本页面给上个页面的回调
}
wx.navigateBack
:相当于history.go()
wx.redirectTo()
:不传值,不保存记录
wx.reLaunch()
:关闭其他,然后跳转,不传值
wx.switchTab()
:关闭其他,跳转到tabar页面
进行传值
上面的方法以及可以实现路由上下两个组件进行传参
通过get方式传参,传递query(缺点, 传递有限)
获取传值
获取get参数:onLoad(options) {}
:options就是get传递的query
tabBar
底部导航
全局tabBar
就是直接在app.json
里面定义tabBar
属性:和window,pages同级
在文档 => 框架 => 全局配置 => tabBar
里面有说明
顶部无法使用icon,会有下边框,且2 <= list.length <= 5
"tabBar": {
"backgroundColor": "#f0f0f0",
"color": '#333',
"selectedColor": "#d43c33",
"position": "botton/top",
"custom": false,
"list": [
{
"pagePath": "tabBar导航地址",
"text": "tab文字",
"iconPath": "未选中icon图片链接",
"selectedIconPath": "选中icon图片链接"
}
]
}
自定义tabBar
(可以局部,也可以全局)
custom
为true即可,然后配置的list
就会失效pages
同级别下创建custom-tab-bar
文件夹并创建index组件tabBar
组件view
标签,可能会导致页面覆盖tabBar
cover-view
和cover-image
组件替代view
页面生命周期
onLoad() {}
:只执行一次onShow() {}
onReady() {}
:只执行一次onHide() {}
;页面隐藏再次显示会触发onShow() {}
onUnload() {}
组件生命周期:看自定义组件文档
在app.js
文件创建globalData
对象存储store全局数据
在局部使用const appInstance = getApp()
获取
const appInstance = getApp();
Page({
onLoad() {
console.log(appInstance.globalData.name)
appInstance.globalData.name = "hello"
}
})
和js
本地存储差不多:
同步:wx.setStorageSync
,多个异步方法wx.setStorage
同步:wx.getStorageSync
,多个异步方法wx.getStorage
还有remove, clear
首次登录触发授权
<button bindgetuserinfo="handleGetInfo" open-type="getUserInfo">获取授权button>
授权后就可以使用wx.getuserInfo()
;重复获取信息
wx.getUserInfo({
success: () => {}, // 成功回调
fail() {} // 失败回调,错误不会给用户看到
complete() {} // 执行回调无论成败
})
// 用于授权后组件内onLoad周期内使用
1、基础组件
小程序内置组件有轮播图,按钮等等原生组件
swapper
:previous-margin
调整前偏距swapper
:next-margin
调整后偏距2、icon使用
iconfont
文件夹=>index.wxss
index.wxss
文件app.wxss
里面引入@import "/static/iconfont/index.wxss"
3、可滚动视图
微信内置组件scroll-view
实现上下滚动,左右滚动,下拉刷新等等页面滚动功能
接口请求使用wx.request()
进行
初始化请求会放在onLoad
或onReady
里面
url
地址必须是完整的,且在小程序管理页面(就是注册成功后页面),开发 => 开发设置 => 服务器域名设置 => 添加服务器域名
最多添加20个域名,并发不能超过10个
必须是https
协议,不是的话可以先在开发工具详情里面设置不校验
也不需要去小程序管理页面添加域名,可以本地调试了
文件上传wx.UploadTask()
文件下载wx.downloadFile()
cookie携带:
onLoad
onLoad
获取cookie,发送请求,将cookie放在head属性里面wx.request
文档里head和url
同级封装
// utils/request.js
uTools
软件进行操作 => 插件中心 => 内网穿透npm
使用cmd
运行npm init
npm
包npm
npm
第三方插件了wx.login({ success(res) { console.log(res.code) } })
2M
小于16M
的包进行拆分在app.json
里面配置subpackages
;这是一个数组
"subpackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
root
:包的根路径名称
name
:包的别名
pages
:包的路由配置
然后和主包pages同级创建包根路径名称文件夹做分包,如:packageA
然后pageageA
里面也创建pages
文件夹,和主包一样结构
分包可以使用主包资源,路径修改下就可以了
主包跳转分包是路由根路径为分包名
就是在需要独立分包的配置加"independent": true
{
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
],
"independent": true
}
独立分的包无法使用主包资源,路由跳转和常规分包一样
在app.json
里的preloadRule
里面进行配置
"preloadRule": {
"pages/index": {
"network": "all",
"packages": ["packageA"]
},
"sub1/index": {
"packages": ["packageA", "packageB"]
},
"sub3/index": {
"packages": ["packageB"]
},
"indep/index": {
"packages": ["__APP__"]
}
}
"pages/index"
:打开路由路径或打开包index路径
network
:指定网络模式,wifi还是其他
packages
:分包的root
或name
名称,其中主包叫__APP__
子组件模板
<view class='child'>
<view>这是子组件view>
<slot>slot>
view>
父组件
<view class='father'>
<component-tag-name>
<view>这里是插入到组件slot中的内容view>
component-tag-name>
view>
页面使用
<view>
<Father><Child />Father>
view>
多个slot和具名
<view class='child'>
<view>这是子组件view>
<slot name='slotA'>slot>
<slot name='slotB'>slot>
view>
<view class'father'>
<component-tag-name
prop-a="{{dataFieldA}}"
prop-b="{{dataFieldB}}"
>
<view slot="slotA">"slotA"中的内容view>
<view slot="slotB">"slotB"中的内容view>
component-tag-name>
view>
组件data里定义的数据
_
前缀:纯数据字段,不会被渲染,不会传递给其他组件observers
=== watch
observers: {
// 监听obj所有值变化
'obj.**': function (obj) { console.log(obj) }
}
created
=== created
attached
=== mounted
detached
=== destroyed
<view class'father'>
<component-tag-name
prop-a="{{dataFieldA}}"
prop-b="{{dataFieldB}}"
>component-tag-name>
view>
<view class="father">
<component-tag-name bindmyevent="onMyEvent" />
view>
// 父组件
onMyEvent(e) { console.log(e.detail.name) }
// 子组件
handleBtn() {
this.triggerEvent('myevent', { name: 'xu' })
}
<view>
<input type="text" id="text" bindinput="handleInput"/>
<input type="password" id="password" bindinput="handleInput"/>
view>
handleInput(e) {
const type = e.currentTarget.id
this.setData({
[type]: e.detail.value
})
}
wx.showToast({ title: '成功' })
api
=> 界面 => 交互video多个播放不符合逻辑
我们需要video播放下一个停止当前上一个video
wx.createVideoContext
:创造一个VideoContext
对象来操作video
使用案例
<view wx:for="{{array}}" wx:key="src">
<video
bindplay="handlePlay"
src="{{item.src}}"
id="{{item.data.id}}"
/>
view>
handlePlay(e) {
const vid = e.currentTaget.id;
// 判断是否时同一个视频 && 判断上一个video控件是否存在
if (this.vid !== vid && this.VideoContent) {
this.VideoContent.stop(); //停止视频播放
}
this.vid = vid
this.VideoContext = wx.createVideoContext(vid);
}
poster属性添加img链接
wx:if="{{vid === item.data.vid}}"
判断video是否隐藏,实现优化使用video的object-fit
的属性设置
scroll-view
的refresher-enabled开启下拉刷新scroll-view
的bindrefresherrefresh
监视下拉是否触发scroll-view
的下拉可控状态:refresher-triggered
onPullDownRefresh
生命周期函数,监视下拉触发enablePullDownRefresh
为truepage.json
的window里面设置json
里面设置scroll-view
的上拉加载:bindscrolltolower
属性触发onReachBottom
生命周期函数进行监视触发button设置open-type
为share就可以触发分享好友功能
用户点击页面上方头部分享按钮
头部分享菜单是创建onShareAppMessage
生命周期函数才会有
点击菜单后触发onShareAppMessage
通过form判断是按钮触发的分享,还是头部菜单触发分享
自定义分享内容
onShareAppMessage
可以返回一个对象,用来自定义分享
title: 标题 path: 分享页面路径 imageUrl
:分享图片
音乐播放使用背景音频功能:文档 => api
=> 媒体 => 背景音频
效果,关闭后还能继续播放
关键:BackgroundAudioManager
音频关键:在onLoad() {}
里面添加 播放监听,暂停监听,停止监听
播放,暂停,停止,音乐播放自然停止都是BackgroundAudioManager
的方法
还有进入更新监听事件,获取播放进度
播放进度/总时长 * 进度条宽长度 = 当前进度条宽长度
通过wx.createAnimation
创建一个动画对象,通常在onload
初始化时创建
将创建的对象添加到this
上面,方便下面绑定动画时使用
onload() {
this.animation = wx.createAnimation({ duration: 2000 })
// createAnimation是可以进行传参配置的
}
创建动画dom
<view animation="{{ animationData }}">view>
创建动画值
data: {
animationData: {}
}
将动画对象赋值给动画值,触发dom
的动画效果
handleBtn() {
// 先定义需要的动画效果,如旋转45度
this.animation.rotate(45)
this.setData({
// export调用动画
animationData: this.animation.export()
})
// 此时已经实现了动画调用
}
多动画同时调用
handleBtn() {
this.animation.rotate(45).scale(2,2)
this.setData({
animationData: this.animation.export()
})
}
多动画依次调用
handleBtn() {
// 使用step实现动画依次加载
// step停止上一次动画动作
this.animation.rotate(45).step().scale(2,2).step()
this.setData({
animationData: this.animation.export()
})
}
动画还原:就是将动画效果还原成初始状态