小程序

小程序基础

小程序构成

项目结构

pages # 用来存放页面
utils # 用来存放工具类
app.js # 小程序的入口
app.json # 小程序的配置文件
app.wxss # 小程序的全局样式
project.config.json # 小程序的项目配置
sitemap.json # 是否允许被微信索引

页面组成

# 每个页面由四个文件组成
.js # 页面的数据 处理函数
.json # 页面的配置
.wxml # 页面结构
.wxss # 页面样式

WXML和HTML

标签不同

HTML(div, sapn, img,a)
WXML(view,text,image,navigator)

属性节点不同

<a href="#"></a>
<navigator url="/pages/home/home"></navigator>

提供类似vue的模板

  • 数据绑定
  • 列表渲染
  • 条件渲染

WXSS 和 CSS

新增rpx尺寸单位

  • 在不同大小的小程序上会自动进行计算

提供全局的样式和局部样式

  • 全局 app.wxss
  • 局部 页面文件的 .wxss

仅支持部分选择器

  • .class 和 #id
  • element
  • 并集选择器 后代选择器
  • :: after 和 :: before

通讯模式

渲染层和逻辑层之间的通信

  • 由微信客户端进行转发

逻辑层和第三方服务器之间的通讯

  • 由微信客户端进行转发

小程序组件

view

<!--类似div-->
<view></view>

scroll-view滑动

横向滑动

<scroll-view class="main" scroll-x>
<view>1</view>
<view>2</view>
<view>3</view>
</scroll-view>
.main{
height: 100rpx;
width: 100rpx;
white-space: nowrap;
}
.main view{
display: inline-block;
height: 100rpx;
width: 100rpx;
background: rgb(35, 190, 21);
}

竖向滑动

<scroll-view class="main" scroll-y>
<view>1</view>
<view>2</view>
<view>3</view>
</scroll-view>
.main{
height: 100rpx;
width: 100rpx;
/* white-space: nowrap; */
}
.main view{
/* display: inline-block; */
height: 100rpx;
width: 100rpx;
background: rgb(35, 190, 21);
}

swiper和swiper-item 轮播图

<swiper>
<swiper-item>A</swiper-item>
<swiper-item>B</swiper-item>
<swiper-item>C</swiper-item>
</swiper>
# 属性
indicator-dots # 是否显示点 默认false
indicator-color # 指示点的颜色
indicator-active-color # 选中点的指示颜色
autopay # 是否自动切换
interval # 时间间隔
circular # 是否衔接滑动

text 文本

<!--selectable 长摁选中-->
<text selectable>1393939393</text>

rich-text 将渲染html字符串

<rich-text nodes="<h1>qwe</h1>"></rich-text>

小程序API

监听事件API

以on开头,来监听某些事件的触发

wx 类似window

wx.onWindowResize(function) 监听窗口是否变化

同步API

以sync结尾的API

执行的结果可以通过函数返回直接获取

异步API

需要通过success ,fail , complete接收调用的结果

WXML

数据绑定

.js里定义数据

Page({
/**
* 页面的初始数据
*/
data: {
name: 'giao',
age: 18
},
})

.wxml 直接用

<view>{{name}}</view>
<view>{{age}}</view>

事件绑定

渲染层到逻辑层的通讯方式

可以将用户在渲染层的行为通过微信客户端反馈到逻辑层

常用

tap # 触摸(类似点击)
input # 输入框事件
change # 状态改变

事件对象的属性列表

触发回调函数的时候, 会收到事件对象event

type # 事件类型
target # 触发事件的组件
currentTarget # 当前事件所绑定的组件
detail # 额外的信息

bindtap 触摸事件

Page({
/**
* 页面的初始数据
*/
data: {
count: 0
},
/**
* 触摸函数
*/
countAdd(e){
// 通过e.target.dataset 获取参数
console.log(e.target.dataset);
// 修改data的值
this.setData({
count: this.data.count + 1
})
},
/**
* 输入框改变
*/
onInputFn(e){
console.log(e.detail.value);
this.setData({
msg: e.detail.value
})
},
})
<!-- bindtap不能传值 需要通过 data-名字 -->
<button bindtap="countAdd" data-num="{{1}}">+1</button>
<input value="{{msg}}" bindinput="onInputFn" type="text" />

条件渲染

<view wx:if="{{sex === 1}}"></view>
<view wx:elif="{{sex === 2}}"></view>
<view wx:else></view>

包裹性质的组件 ,不会在页面渲染, 可以控制多个组件显示隐藏

<block wx:if="{{false}}">
<view>block包裹</view>
<view>block包裹</view>
</block>

hidden

隐藏元素

<view hidden="{{true}}">block包裹</view>

wx:if和hidden

  • wx:if 是动态销毁
  • hidden 是隐藏

列表渲染

<!-- wx:key 不用{{}} -->
<view wx:for="{{arr}}" wx:key="item">
{{item}}
</view>

小程序配置

全局配置

app.json

pages # 所有小程序页面的存路径
window # 全局设置小程序窗口的外观
tabBar # 设置小程序底部的tabBar
style # 是否启用组件样式

windiw

"window":{
// 下拉刷新时 loading样式
"backgroundTextStyle":"dark",
// 导航栏背景
"navigationBarBackgroundColor": "#345333",
// 导航栏内容
"navigationBarTitleText": "健康宝",
// 导航栏字体颜色
"navigationBarTextStyle":"white",
// 开启下拉刷新
"enablePullDownRefresh" : true,
// 下拉刷新时 背景
"backgroundColor": "#efefef",
// 上拉触底 滚动条距离底部50px 加载数据
"onReachBottomDistance": 50
},

tabBar

用于实现多页面切换, 渲染顶部的时候不显示icon

最少渲染两个, 做多渲染5个

"tabBar": {
// 背景颜色
"backgroundColor": "#fff234",
// 字体颜色
"color": "#fff",
// 边框颜色 black white
"borderStyle": "black",
// 配置内容图标
"list":[
{
// 路径
"pagePath": "pages/nav/nav",
// 内容
"text": "nav",
// 图标
"iconPath": "/img/tabs/home.png",
// 选中图标
"selectedIconPath": "/img/tabs/home-active.png"
},
{},
{}
]
},

页面配置

会覆盖全局配置, 跟 window一致

小程序数据请求

出于安全考虑, 小程序官方对数据接口的请求做出来两个限制

  • 只能请求https类型的接口
  • 必须将接口的域名添加到信任列表
wx.request({
url:'url',
method: 'get',
success: (res)=> {
console.log(res);
}
})
wx.request({
url:'url',
method: 'post',
data:{},
success: (res)=> {
console.log(res);
}
})

视图与逻辑

声明式导航

页面上声明一个导航组件, 点击跳转

<!--
声明式跳转
url="/..."
open-type="switchTab" 跳转配置tabBar
-->
<navigator url="/pages/msg/msg" open-type="switchTab">配置tabBar</navigator>
<!--
声明式跳转
url="/..."
open-type="navigate" (可选) 跳转配置没tabBar
-->
<navigator url="/pages/info/info" open-type="navigate">配置没tabBar</navigator>
<!--
返回
open-type="navigateBack"
delta="1" (为一时可以不写) 返回页面数
-->
<navigator open-type="navigateBack" delta="1">返回</navigator>

传参

<!--
传参
参数与路径之间使用?分隔
参数键与参数值 用等号
不同参数&
-->
<navigator url="/pages/info/info?name=zs&age=18" open-type="navigate">配置没tabBar</navigator>

编程式导航

调用小程序的导航API, 实现跳转

wx.switchTab({
// 路径
url:'',
// 成功
success: () =>{},
// 失败
fail: ()=>{},
// 成功失败都会执行
complete: ()=>{}
})
/**
* 编程式导航
* 跳转tabBar
*/
onNavigator(){
wx.switchTab({
url:"/pages/msg/msg"
})
},
/**
* 编程式导航
* 跳转非tabBar
*/
onNavigatorTo(){
wx.navigateTo({
url: '/pages/info/info'
})
},
/**
* 返回
*/
onBack(){
wx.navigateBack({
// 可选不写就是1
delta: 1,
})
},
<!-- 编程式跳转 -->
<button type="primary" bindtap="onNavigator">编程式跳转tabBar</button>
<button type="primary" bindtap="onNavigatorTo">编程式跳转非tabBar</button>
<!--返回-->
<button type="primary" bindtap="onBack">返回</button>

传参

/**
* 编程式导航
* 跳转非tabBar
*/
onNavigatorTo(){
wx.navigateTo({
url: '/pages/info/info?name=zs&age=18'
})
},

接收参数

/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// 传递的参数
console.log(options);
this.setData({
query: options
})
},

下拉刷新

全局 app.json window节点 enablePullDownRefresh: ture

局部 .json enablePullDownRefresh: true

/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.setData({
count: 0
})
// 关闭下拉刷新
wx.stopPullDownRefresh({
success: (res) => {
console.log(res);
},
})
},

上拉触底

"onReachBottomDistance": 50 距离底部50

/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.getColor()
},

loading显示隐藏

wx.showLoading({
title: '加载',
})
wx.hideLoading()

生命周期

应用生命周期

特指小程序从启动 运行 销毁的过程

页面生命周期

特指小程序, 每个页面的加载 渲染 销毁

/**
* 生命周期函数--监听页面加载
* 只调用一次
* options 当前页面获取的传参
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
* 可以进行交互
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
* 进入前台
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
* 切入后台
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
* navigateBack
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}

wxs

数据类型

number 数值类型
string 字符串
Boolean 布尔
object 对象
function 函数
array 数组
date 日期
regexp 正则

语法

只支持普通函数 var定义 类似Es5 , 遵循commonJs

<view>{{n1.giao('giao')}}</view>
<wxs module="n1">
module.exports.giao = function(str){
return str + 123
}
</wxs>

可以写成wxs文件

<wxs src="" module=""></wxs>

自定义组件

创建组件

创建components文件夹
创建text文件夹 右键 点击新建Component

引用组件

局部引用

只能在当前页面被引用

.json下添加

{
"usingComponents": {
"text-01" : "/components/text/text"
}
}
// 调用 <text-01></text-01>

全局引用

可以再每个页面使用

app.json下添加

{
"usingComponents": {
"text-01" : "/components/text/text"
}
}
// 调用 <text-01></text-01>

组件和页面的区别

  • json 需要声明 "component": true,
  • js 中调用 Component()
  • 事件处理函数定义到methods

组件样式隔离

组件与页面之间互不影响

只有class会有样式隔离 , 不要使用Id , 属性, 标签选择器

修改样式隔离选项

"styleIsolation": "isolated"
// isolated 启用样式隔离
// apply-shared 页面能影响组件 , 组件影响不了页面
// shared 互相影响

数据方法属性

Component({
/**
* 组件的属性列表
* 用来接收外界传的属性
*/
properties: {
max: {
type: Number, //类型
value: 10 // 默认值
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
this.setData({
// 可以用setData修改 properties属性
max: this.properties.max + 1
})

数据监听器

Component({
observers: {
//如果监听的数据太多 可以 obj.**
'字段1,字段2.name':function(字段1,字段2){}
}
})

纯数据字段

options:{
// 正则 匹配上之后就是纯数据字段
pureDataPattern: /^_/
},
_data: true // 只能用于纯数据处理,不能用来渲染

组件声明周期

created # 组件刚创建 (不能调用setData)
attached # 组件进入页面节点树(可以发请求, 初始化数据)
ready # 在视图层布局完后执行
moved # 实例被移动到另一个节点树
detached # 组件被移出
Component({
// 调用生命周期函数
lifetimes: {
attached(){},
detached(){}
}
})

组件在页面的声明周期

show # 组件在页面被展示时
hide # 组件在页面被隐藏时
resize # 组件页面尺寸发生变化
Component({
// 调用页面生命周期函数
pageLifetimes: {
show: function(){},
hide: function(){},
resize: function(size){},
}
})

插槽

<!--组件添加-->
<slot></slot>
<!--页面调用-->
<text-01>
// 插槽内容
123
</text-01>

开启多个插槽

options:{
// 开启多个插槽
multipleSlots: true
},
<slot name="before"></slot>
<slot name="after"></slot>
<text-01>
<text slot="before">before</text>
<text slot="after">after</text>
</text-01>

通讯

属性绑定(父传子)

父向子传值, 只能传递普通类型的数据

<text-01 count="{{count}}"></text-01>
properties: {
count: Number
},
<view>{{count}}</view>

事件绑定(子传父)

// 父页面
// <text-01 bind:giao="countAdd"></text-01>
// 在子js , 调用父函数
this.triggerEvent('giao',{value:this.properties.count})

获取组件实例

可以获取组件的属性方法

<button bindtap="getText">获取text</button>
const child = this.selectComponent('.text')
child.setData({
count: child.properties.count + 1
})

behaviors

实现组件间代码共享, 可以包含属性, 数据, 生命周期函数和方法

Behaviors/index.js

module.exports = Behavior({
//节点属性
properties:{},
// 私有属性
data: {
age:18
},
// 方法
methods:{}
})
import Behavior from '../../Behaviors/index'
Component({
behaviors: [Behavior],
})

npm包

Vant Weapp

小程序项目 直接安装 npm i @vant/weapp@1.3.3 -S --production

然后 点工具 构建npm

修改 project.config.json

{
...
"setting": {
...
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
]
}
}

app.json 引入组件

"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
<van-button type="primary">测试按钮</van-button>

API Promise化

官方提供的API都是基于回调函数实现的, 容易造成回调地狱

miniprogram-api-promise

npm i --save miniprogram-api-promise@1.0.4

注意: 每一次安装完包都要构建npm

import {promisifyAll} from 'miniprogram-api-promise'
const wxp = wx.p = {}
// 把wx放到wxp上 , 在任何页面都可以 wx.p.request()
promisifyAll(wx,wxp)
async getPromise(){
const res = await wx.p.request({
url: 'url',
method: 'get',
})
console.log(res);
},

Mobx

mobx-miniprogram # 创建store
mobx-miniprogram-bindings # 把store 绑定到组件
npm i mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1

store/index.js

import {action, observable} from 'mobx-miniprogram'
// observable 返回值就是store实例
export const store = observable({
count1: 1,
count2: 2,
// get 计算属性
get sum(){
return this.count1 + this.count2
},
// action 修改store值 不能用箭头函数
updateCount: action(function (num) {
this.count1 = this.count1 + num
})
})

页面使用

import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/index'
Page({
countAdd(e){
this.updateCount(e.target.dataset.num)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// createStoreBindings 可以将store数据绑定到页面
this.storeBingings = createStoreBindings(this,{
store,
// 字段和计算属性
fields: ['count1','count2','sum'],
// 方法
actions: ['updateCount']
})
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
this.storeBingings.detroyStoreBindings()
},
})
<text>{{count1}}+{{count2}}={{sum}}</text>
<button type="primary" bindtap="countAdd" data-num="{{1}}">+1</button>
<button bindtap="countAdd" data-num="{{-1}}">-1</button>

组件使用

import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../../store/index'
Component({
behaviors: [storeBindingsBehavior],
storeBindings:{
store,
fields:{
count1: 'count1',
count2: 'count2',
sum: 'sum'
},
actions:{
updateCount: 'updateCount'
}
},
methods:{
countAdd(e){
this.updateCount(e.target.dataset.num)
}
}
})
<text>{{count1}}+{{count2}}={{sum}}</text>
<button type="primary" bindtap="countAdd" data-num="{{1}}">+1</button>
<button bindtap="countAdd" data-num="{{-1}}">-1</button>

分包

什么是分包

把完整的小程序项目 , 按照需求划分成不同的子包 用户使用时按需加载

  • 可以优化小程序首次启动的下载时间
  • 多团队共同开发, 解耦协作

分包后项目构成

  • 主包: 启动页面 + tabBer页面 , 一些公共资源
  • 分包: 只包含和当前分包有关的页面资源

小程序启动时, 默认会下载主包并启动主包页面, 当用户进入分包的某个页面, 客户端会把对应分包下载下来, 进行展示

**注意: ** 整个小程序不能超过16M, 单包不能超过2M

使用分包

小程序会按 subpackages 的配置进行分包, subpackages 之外的目录将被打包到主包中

// 进行分包声明
"subpackages":[
{
"root": "text1", //第一个分包目录
"pages": [ // 分包下的页面
"pages/info/info"
]
},
{
"root": "text2",
"pages": [
"pages/info/info"
]
}
],
  1. 主包无法引用分包的私有资源
  2. 分包之间不能引用私有资源
  3. 分包可以引用公共资源

独立分包

普通分包依赖主包

独立分包独立运行 , 不能引用公共资源

// 进行分包声明
"subpackages":[
{
"root": "text1", //第一个分包目录
"pages": [ // 分包下的页面
"pages/info/info"
],
"independent": true // 声明独立分包
}
],

分包预下载

进入指定页面, 下载需要用的分包

预下载大小限额2M

"preloadRule": {
"pages/message/message":{
// 在指定网络模式进行预下载
"network": "all",
// root名 下载哪些包
"packages": ["text1"]
}
},

自定义TabBar

配置信息 custom: true 是否开启自定义tabbar

app.json

{
"tabBar": {
"custom": true,
// list 要保留 低版本兼容
"list": [{
"pagePath": "page/component/index",
"text": "组件"
}, {
"pagePath": "page/API/index",
"text": "接口"
}]
},
"usingComponents": {}
}

跟根目录添加custom-tab-bar 文件 新建Component

编写代码即可

posted @   rain_sparse  阅读(102)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示